Как найти теги только с определенными атрибутами - BeautifulSoup - PullRequest
63 голосов
/ 20 января 2012

Как мне, используя 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"

UPDATE Например, если документ HTML содержал следующие теги <td>:

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

Я бы хотел, чтобы только первый тег <td> (<td width="580" valign="top">) возвращал

Ответы [ 6 ]

81 голосов
/ 20 января 2012

Как описано в документации BeutifulSoup

Вы можете использовать это:

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>
36 голосов
/ 22 апреля 2014

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

td_tag_list = soup.findAll(
                lambda tag:tag.name == "td" and
                len(tag.attrs) == 1 and
                tag["valign"] == "top")
17 голосов
/ 28 июля 2017

, если вы хотите выполнять поиск только по имени атрибута с любым значением

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})
9 голосов
/ 19 февраля 2016

Самый простой способ сделать это с помощью нового стиля CSS select метод:

soup = BeautifulSoup(html)
results = soup.select('td[valign="top"]')
3 голосов
/ 20 января 2012

Просто передайте его как аргумент 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>]
0 голосов
/ 30 октября 2018

Добавляя комбинацию ответа Криса Редфорда и Амра, вы также можете искать имя атрибута с любым значением с помощью команды 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]')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...