尝试使用python和bs4从特定的“ td”中抓取所有“ a”文本

时间:2019-04-08 23:19:06

标签: python html web-scraping beautifulsoup

我正在尝试抓取https://www.betexplorer.com/soccer/england/premier-league/fixtures/来提取'a'标记中包含的文本,特别是在带有“ table-main”类的表中,然后针对其中的每一行。第一个td包含带有两个团队名称的文本,其td类为“ h-text-left”。不确定问题是否出在我的循环中,但是我收到的错误消息似乎是我在循环的最后一行中错误地使用了bs4。

我可以使用“ table-main”类抓取表中的每个tr,然后使用“ h-text-left”类抓取每个td。但是,当我尝试仅提取“ a”元素,甚至不提取“ a”文本时,我都陷入了僵局。

import requests
from bs4 import BeautifulSoup

headers = {'User-Agent':
           'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'}

r = requests.get('https://www.betexplorer.com/soccer/england/premier-league/fixtures/', headers=headers)

c = r.content

soup = BeautifulSoup(c)

fixture_table = soup.find('table', attrs = {'class': 'table-main'})

for tr in soup.find_all('tr'):
    match_tds = tr.find_all('td', attrs = {'class': 'h-text-left'})
    matches = match_tds.find_all('a')

当我尝试查找所有'a'标签时,最后一行会跳出以下错误:

...     matches = match_tds.find_all('a')
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "C:\Users\Glypt\AppData\Local\Programs\Python\Python36-32\lib\site-packages\bs4\element.py", line 1884, in __getattr__
    "ResultSet object has no attribute '%s'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?" % key
AttributeError: ResultSet object has no attribute 'find_all'. You're probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?
>>>

4 个答案:

答案 0 :(得分:0)

match_tds是一个列表,而不是单个元素-您可以通过tr.find_all(...)获得它-因此,您必须使用for循环来运行另一个find_all()

for tr in soup.find_all('tr'):
    match_tds = tr.find_all('td', attrs = {'class': 'h-text-left'})
    for item in match_tds:
        matches = item.find_all('a')
        for a in matches:
            print(a['href'])

如果使用find()获取第一个元素,则可以与另一个find()find_all()一起使用

soup.find(...).find(...).find_all(...)

但是您不能在find()之后使用find_all()find_all()

# ERROR
soup.find_all(...).find_all(...) 

# ERROR
soup.find_all(...).find(...) 

答案 1 :(得分:0)

您应该使用内置功能来查找嵌套结构。您可以使用.css指定一个'.class_name'类,并使用“第一个选择器”>“第二个选择器”`(或更多选择器)查找嵌套结构。在一起看起来像:

import requests
from bs4 import BeautifulSoup

s = requests.session()
s.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36'
res = s.get('https://www.betexplorer.com/soccer/england/premier-league/fixtures/')
soup = BeautifulSoup(res.text, 'html.parser')

matches = soup.select('.table-main  tr  td  a')
for match in matches:
    print(match.getText())

matches = soup.select('.table-main tr td a')行将选择a元素内td元素内tr元素内的所有class=table-main元素。另外,您可以使用matches = soup.select('td > a')>运算符)来指定a元素在td元素内直接 。我想这可能会大大简化您的代码!

请注意,由于无法确认SSL证书并引发requests.exceptions.SSLError

,因此我无法在计算机上对此进行测试

答案 2 :(得分:0)

要获取文字,请尝试:

for td in soup.findAll('td', attrs = {'class': 'h-text-left'}):
    print(td.findAll('a')[0].text)

答案 3 :(得分:0)

您可以使用单个类将其缩减为更快的选择器方法。所有链接具有相同的类名,因此您可以将其传递给列表理解内的select,以提供所有链接。

import requests
from bs4 import BeautifulSoup
r = requests.get('https://www.betexplorer.com/soccer/england/premier-league/fixtures/')
soup = BeautifulSoup(r.content, 'lxml')
matches = [item['href'] for item in soup.select('.in-match')]

赔率

import requests
from bs4 import BeautifulSoup
r = requests.get('https://www.betexplorer.com/soccer/england/premier-league/fixtures/')
soup = BeautifulSoup(r.content, 'lxml')
odds = [item['data-odd'] for item in soup.select('.table-main__odds [data-odd]')]
print(odds)