Я пытаюсь очистить https://www.betexplorer.com/soccer/england/premier-league/fixtures/, чтобы извлечь текст, содержащийся в теге «a», особенно в таблице с классом «table-main», а затем для каждой строки в ней. Первый td содержит текст с двумя названиями команд с классом td «h-text-left». Не уверен, связана ли проблема с моим циклом или нет, но сообщение об ошибке, которое я получаю, похоже, что я неправильно использую bs4 в моей последней строке цикла.
Я могу очистить каждый tr в таблице с классом «table-main», а затем, кроме того, каждый td с классом «h-text-left». Однако я захожу в тупик, пытаясь извлечь только элементы «а», даже не текст «а».
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()?
>>>
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(...)
Вы должны использовать встроенную функциональность для поиска вложенных структур. Вы можете указать класс .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
Чтобы получить текст, попробуйте:
for td in soup.findAll('td', attrs = {'class': 'h-text-left'}):
print(td.findAll('a')[0].text)
Вы можете уменьшить это до гораздо более быстрого метода селектора, используя один класс. Все ссылки имеют одно и то же имя класса, поэтому вы можете передать его 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)
Сейчас я пробую этот подход, но на самом деле я пытаюсь извлечь текст ссылки, а не атрибут href. Я попытался изменить ваш пример, чтобы извлечь текст шансов, но я не получаю никакого вывода при его печати, т.е. [] <td class = "table-main__odds" data-oid = "33jkrxv464x0x7k7pm"> <a href = " JavaScript: недействительным (0);" onclick = "my_selections_click('1x2', 'футбол', 'action=3&matchid=tKLzuv9M&outcomeid=33jkrxv464x0x7k7pm&otheroutcomes=33jkrxv498x0x0,33jkrxv464x0x7k7pn');" title = "Добавить к моему выбору">2.08 </a> </td>
Так что извините, эти ссылки не имеют класса «.in-match», а точнее вообще никакого класса. Однако я попытался разобрать атрибут «заголовок», который, кажется, всегда «Добавить к моему выбору». Однако после этого я не получаю вывода при попытке распечатать список совпадений.
Извиняюсь за ужасное форматирование, но для примера элемента, который я привел выше, я хочу извлечь текст «2.08» из элемента a.
Вы бы изменили на item.text для элемента в
match = [item.text для элемента в soap.select('.in-match')] odds = [item.text для элемента в супе.select('Добавить в мой выбор')] Первый работает, как вы описали, однако , второй не работает, когда я пытаюсь настроить таргетинг на атрибут заголовка элемента. Все еще печатаю []
Это то, что вы имели в виду?
Спасибо, получил именно то, что искал.