Попытка очистить весь текст «a» из определенных «td», используя python и bs4 - PullRequest
1 голос
/ 09 апреля 2019

Я пытаюсь очистить https://www.betexplorer.com/soccer/england/premier-league/fixtures/, чтобы извлечь текст, содержащийся в теге 'a', в частности, внутри таблицы с классом "table-main", а затем для каждой строки в этом.Первый тд содержит текст с именами двух команд, с тд классом "h-text-left".Не уверен, что проблема связана с моим циклом или нет, но сообщение об ошибке, которое я получаю, кажется, что я неправильно использую bs4 в своей последней строке цикла.

Я могу очистить каждый tr в таблице с классом,"table-main", затем, кроме того, каждый тд с классом, "h-text-left".Хотя я пытаюсь извлечь один из элементов '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 голосов
/ 09 апреля 2019

Вы можете уменьшить это до гораздо более быстрого метода выбора, используя один класс. Все ссылки имеют одно и то же имя класса, так что вы можете передать его в 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')]

Odds

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)
0 голосов
/ 09 апреля 2019

Вы должны использовать встроенную функциональность для поиска вложенных структур.Вы можете указать класс .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

0 голосов
/ 09 апреля 2019

Чтобы получить текст, попробуйте:

for td in soup.findAll('td', attrs = {'class': 'h-text-left'}):
    print(td.findAll('a')[0].text)
0 голосов
/ 09 апреля 2019

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(...) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...