Jak znaleźć tagi z tylko określonymi atrybutami - BeautifulSoup

87

Jak mógłbym, używając BeautifulSoup, wyszukiwać tagi zawierające TYLKO atrybuty, których szukam?

Na przykład chcę znaleźć wszystko <td valign="top"> tagi.

Poniższy kod: raw_card_data = soup.fetch('td', {'valign':re.compile('top')})

pobiera wszystkie potrzebne mi dane, ale także pobiera wszystkie <td>znaczniki, które mają ten atrybutvalign:top

Próbowałem też: raw_card_data = soup.findAll(re.compile('<td valign="top">')) i to nic nie zwraca (prawdopodobnie z powodu złego wyrażenia regularnego)

Zastanawiałem się, czy istnieje sposób w BeautifulSoup, aby powiedzieć „Znajdź <td>tagi, których jedynym atrybutem jest valign:top

UPDATE FOR przykład, jeśli dokument HTML zawierał następujące <td>tagi:

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

Chciałbym, aby powrócił tylko pierwszy <td>tag ( <td width="580" valign="top">)

Snaxib
źródło

Odpowiedzi:

98

Jak wyjaśniono w dokumentacji BeautifulSoup

Możesz użyć tego:

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

EDYTOWAĆ :

Aby zwrócić tagi, które mają tylko atrybut valign = "top", możesz sprawdzić długość attrswłaściwości tagu :

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

To wraca:

<td valign="top">.....</td>
Loïc G.
źródło
Zgodnie z moim komentarzem do julio.alegria, To znajdzie wszystkie <tr>tagi z atrybutem valign="top", w tym te z innymi atrybutami ( <td width="580" valign="top">jest również zwracane w tym wyszukiwaniu) Szukam metody znajdowania <tr>tagów, których jedynym atrybutem jestvalign="top"
Snaxib
Możesz więc sprawdzić len (tag.attrs). Jeśli len (tag.attrs)> 1, zignoruj ​​tag (redagowałem swój post)
Loïc G.
52

Możesz używać lambdafunkcji w findAllsposób wyjaśniony w dokumentacji . Aby w twoim przypadku wyszukać tdtag, używając tylko valign = "top"następujących:

td_tag_list = soup.findAll(
                lambda tag:tag.name == "td" and
                len(tag.attrs) == 1 and
                tag["valign"] == "top")
Yogesh
źródło
4
najlepsza odpowiedź, ponieważ wykorzystuje pełną moc BS
Rafael T
2
Świetna odpowiedź, ponieważ daje wynik w bardzo zoptymalizowany sposób.
CrazyGeek,
33

jeśli chcesz wyszukiwać tylko według nazwy atrybutu o dowolnej wartości

from bs4 import BeautifulSoup
import re

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

jak na Steve Lorimer lepiej przekazać True zamiast regex

results = soup.findAll("td", {"valign" : True})
Amr
źródło
2
Brakuje nawiasu po r".*", co powoduje, że to się nie kompiluje.
Jack Cole,
11
Nie potrzeba wyrażenia regularnego, wystarczy podać True:results = soup.findAll("td", {"valign" : True})
Steve Lorimer
17

Najłatwiej to zrobić za pomocą nowej selectmetody stylu CSS :

soup = BeautifulSoup(html)
results = soup.select('td[valign="top"]')
Chris Redford
źródło
Co się stanie, jeśli nie znam wcześniej wartości i po prostu chcę znaleźć tag zawierający atrybut valign?
MasayoMusic
1
@MasayoMusic Możesz zrobić soup.select ('td [valign]'), aby wybrać wszystkie <td> mające atrybut 'valign'. Możesz również pominąć nazwę tagu, aby wybrać wszystkie elementy z atrybutem „valign”
Elben
4

Po prostu podaj to jako argument 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>]
juliomalegria
źródło
1
Co jeśli istnieją znaczniki tak: <td width="580" valign="top">? Nie chcę ich valign="top"
łapać
2

Dodając kombinację odpowiedzi Chrisa Redforda i Amra, możesz również wyszukać nazwę atrybutu o dowolnej wartości za pomocą polecenia 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]')
Wypas Naukowiec
źródło
Próbowałem w ten sam sposób, ale to nie działa, czy jest jakieś obejście?
Phaneendra Charyulu Kanduri
1
@PhaneendraCharyuluKanduri Przepraszamy, w kodzie wystąpił zły błąd kodowania. Teraz kopiowanie i wklejanie powinno działać!
GrazingScientist
0

znajdź używając atrybutu w dowolnym tagu

<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"}) 
 
Shah Vipul
źródło