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

Я пытаюсь очистить 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()?
>>>
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
260
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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(...) 

Спасибо, получил именно то, что искал.

Alex 09.04.2019 04:16

Вы должны использовать встроенную функциональность для поиска вложенных структур. Вы можете указать класс .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&amp;matchid=tKLzuv9M&amp;outcomeid=33jkrxv464x0x7k‌​7pm&amp;otheroutcome‌​s=33jkrxv498x0x0,33j‌​krxv464x0x7k7pn');" title = "Добавить к моему выбору">2.08 </a> </td>

Alex 10.04.2019 01:04

Так что извините, эти ссылки не имеют класса «.in-match», а точнее вообще никакого класса. Однако я попытался разобрать атрибут «заголовок», который, кажется, всегда «Добавить к моему выбору». Однако после этого я не получаю вывода при попытке распечатать список совпадений.

Alex 10.04.2019 01:07

Извиняюсь за ужасное форматирование, но для примера элемента, который я привел выше, я хочу извлечь текст «2.08» из элемента a.

Alex 10.04.2019 01:07

Вы бы изменили на item.text для элемента в

QHarr 10.04.2019 08:16

match = [item.text для элемента в soap.select('.in-match')] odds = [item.text для элемента в супе.select('Добавить в мой выбор')] Первый работает, как вы описали, однако , второй не работает, когда я пытаюсь настроить таргетинг на атрибут заголовка элемента. Все еще печатаю []

Alex 10.04.2019 08:25

Это то, что вы имели в виду?

QHarr 10.04.2019 09:56

Другие вопросы по теме