Як знайти теги лише з певними атрибутами - BeautifulSoup


85

Як би я, використовуючи BeautifulSoup, шукав теги, що містять ТІЛЬКИ атрибути, які я шукаю?

Наприклад, я хочу знайти всі <td valign="top">теги.

Наступний код: raw_card_data = soup.fetch('td', {'valign':re.compile('top')})

отримує всі потрібні дані, але також захоплює будь-який <td>тег, що має атрибутvalign:top

Я також спробував: raw_card_data = soup.findAll(re.compile('<td valign="top">')) і це нічого не повертає (можливо, через поганий регулярний вираз)

Мені цікаво, чи є у BeautifulSoup спосіб сказати "Знайти <td>теги, єдиним атрибутом яких є valign:top"

ОНОВИТИ Для прикладу, якщо документ HTML містив такі <td>теги:

<td valign="top">.....</td><br />
<td width="580" valign="top">.......</td><br />
<td>.....</td><br />

Я хотів би, щоб повернувся лише перший <td>тег ( <td width="580" valign="top">)

Відповіді:


97

Як пояснюється в документації BeautifulSoup

Ви можете використовувати це:

soup = BeautifulSoup(html)
results = soup.findAll("td", {"valign" : "top"})

РЕДАГУВАТИ:

Щоб повернути теги, які мають лише атрибут valign = "top", можна перевірити довжину властивості тегу attrs:

from BeautifulSoup import BeautifulSoup

html = '<td valign="top">.....</td>\
        <td width="580" valign="top">.......</td>\
        <td>.....</td>'

soup = BeautifulSoup(html)
results = soup.findAll("td", {"valign" : "top"})

for result in results :
    if len(result.attrs) == 1 :
        print result

Це повертає:

<td valign="top">.....</td>

Відповідно до мого коментаря до julio.alegria, у ньому будуть знайдені всі <tr>теги з атрибутом valign="top", включаючи ті з іншими атрибутами ( <td width="580" valign="top">також повертається у цьому пошуку). Я шукаю метод для пошуку <tr>тегів, єдиним атрибутом яких єvalign="top"
Snaxib

Отже, ви можете перевірити len (tag.attrs). Якщо len (tag.attrs)> 1, ігноруйте тег (я відредагував свій пост)
Loïc G.

51

Ви можете використовувати lambdaфункції, findAllяк описано в документації . Так що у вашому випадку для пошуку tdтегу valign = "top"використовуйте лише наступне:

td_tag_list = soup.findAll(
                lambda tag:tag.name == "td" and
                len(tag.attrs) == 1 and
                tag["valign"] == "top")

4
найкраща відповідь, оскільки він використовує всю потужність BS
Рафаель Т

2
Чудова відповідь, тому що це дає вам результат в дуже оптимізованому вигляді.
CrazyGeek

32

якщо ви хочете шукати лише з іменем атрибута з будь-яким значенням

from bs4 import BeautifulSoup
import re

soup= BeautifulSoup(html.text,'lxml')
results = soup.findAll("td", {"valign" : re.compile(r".*")})

за Стівом Лорімером, краще передавати True замість регулярного виразу

results = soup.findAll("td", {"valign" : True})

2
Ви втрачаєте дужки після r".*", внаслідок чого це не компілюється.
Джек Коул,

9
Не потрібно регулярного виразу, просто передайте True:results = soup.findAll("td", {"valign" : True})
Стів Лорімер

14

Найпростіший спосіб зробити це за допомогою нового selectметоду стилю CSS :

soup = BeautifulSoup(html)
results = soup.select('td[valign="top"]')

4

Просто передайте це як аргумент findAll:

>>> from BeautifulSoup import BeautifulSoup
>>> soup = BeautifulSoup("""
... <html>
... <head><title>My Title!</title></head>
... <body><table>
... <tr><td>First!</td>
... <td valign="top">Second!</td></tr>
... </table></body><html>
... """)
>>>
>>> soup.findAll('td')
[<td>First!</td>, <td valign="top">Second!</td>]
>>>
>>> soup.findAll('td', valign='top')
[<td valign="top">Second!</td>]

1
Що робити, якщо є такі мітки <td width="580" valign="top">:? Я не хочу захоплювати їх, лише теги, єдиним атрибутом яких єvalign="top"
Snaxib

2

Додавши комбінацію відповідей Кріса Редфорда та Амра, ви також можете шукати ім'я атрибута з будь-яким значенням за допомогою команди select:

from bs4 import BeautifulSoup as Soup
html = '<td valign="top">.....</td>\
    <td width="580" valign="top">.......</td>\
    <td>.....</td>'
soup = Soup(html, 'lxml')
results = soup.select('td[valign]')

Я пробував так само, але це не працює, чи є якийсь обхідний шлях?
Phaneendra Charyulu Kanduri

1
@PhaneendraCharyuluKanduri На жаль, у коді сталася помилка кодування. Тепер копіювання та вставка повинні працювати!
GrazingScientist
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.