Как найти теги только с определенными атрибутами - BeautifulSoup

86

Как мне с помощью 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">)

Снаксиб
источник

Ответы:

98

Как объяснено на документации 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, игнорировать тег (я отредактировал свой пост)
Лоик Г.
52

Вы можете использовать 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
Rafael T
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".*", в результате чего компиляция не выполняется.
Джек Коул,
11
Нет необходимости в регулярном выражении, просто передайте True:results = soup.findAll("td", {"valign" : True})
Стив Лоример
16

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

soup = BeautifulSoup(html)
results = soup.select('td[valign="top"]')
Крис Редфорд
источник
Что делать, если я не знаю заранее значение и просто хочу найти тег, содержащий атрибут valign?
MasayoMusic
1
@MasayoMusic Вы можете сделать soup.select ('td [valign]'), чтобы выбрать все <td>, имеющие атрибут 'valign'. Вы также можете опустить имя тега, чтобы выбрать все элементы с атрибутом 'valign'
Эльбен
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
0

найти с помощью атрибута в любом теге

<th class="team" data-sort="team">Team</th>    
soup.find_all(attrs={"class": "team"}) 

<th data-sort="team">Team</th>  
soup.find_all(attrs={"data-sort": "team"}) 
 
Шах Випул
источник