So finden Sie Tags mit nur bestimmten Attributen - BeautifulSoup

84

Wie würde ich mit BeautifulSoup nach Tags suchen, die NUR die Attribute enthalten, nach denen ich suche?

Zum Beispiel möchte ich alle <td valign="top">Tags finden.

Der folgende Code: raw_card_data = soup.fetch('td', {'valign':re.compile('top')})

Ruft alle gewünschten Daten ab, greift aber auch auf jedes <td>Tag mit dem Attribut zuvalign:top

Ich habe es auch versucht: raw_card_data = soup.findAll(re.compile('<td valign="top">')) und dies gibt nichts zurück (wahrscheinlich wegen schlechten Regex)

Ich habe mich gefragt, ob es in BeautifulSoup eine Möglichkeit gibt, " <td>Tags finden, deren einziges Attribut ist valign:top" zu sagen.

UPDATE Zum Beispiel, wenn ein HTML-Dokument die folgenden <td>Tags enthielt :

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

Ich möchte, dass nur das erste <td>Tag ( <td width="580" valign="top">) zurückgegeben wird

Snaxib
quelle

Antworten:

96

Wie in der BeutifulSoup-Dokumentation erläutert

Sie können dies verwenden:

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

EDIT:

Um Tags zurückzugeben, die nur das Attribut valign = "top" haben, können Sie die Länge der Tag- attrsEigenschaft überprüfen :

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

Das kehrt zurück:

<td valign="top">.....</td>
Loïc G.
quelle
Gemäß meinem Kommentar zu julio.alegria werden hiermit alle <tr>Tags mit dem Attribut gefunden valign="top", auch diejenigen mit anderen Attributen ( <td width="580" valign="top">wird auch bei dieser Suche zurückgegeben). Ich suche nach einer Methode, um <tr>Tags zu finden, deren einziges Attributvalign="top"
Snaxib
Sie können also len (tag.attrs) überprüfen. Wenn len (tag.attrs)> 1 ist, ignoriere das Tag (ich habe meinen Beitrag bearbeitet)
Loïc G.
51

Sie können lambdaFunktionen findAllwie in der Dokumentation beschrieben verwenden . Damit Sie in Ihrem Fall nach tdTags suchen, verwenden Sie nur valign = "top"Folgendes:

td_tag_list = soup.findAll(
                lambda tag:tag.name == "td" and
                len(tag.attrs) == 1 and
                tag["valign"] == "top")
Yogesh
quelle
4
beste Antwort, da es die volle Kraft von BS nutzt
Rafael T
2
Tolle Antwort, weil Sie auf sehr optimierte Weise Ergebnisse erzielen.
CrazyGeek
32

Wenn Sie nur mit einem Attributnamen mit einem beliebigen Wert suchen möchten

from bs4 import BeautifulSoup
import re

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

Laut Steve Lorimer ist es besser, True statt Regex zu bestehen

results = soup.findAll("td", {"valign" : True})
Amr
quelle
2
Sie vermissen danach eine Klammer r".*", was dazu führt, dass diese nicht kompiliert wird.
Jack Cole
9
Keine Notwendigkeit für einen regulären Ausdruck, nur bestehen True:results = soup.findAll("td", {"valign" : True})
Steve Lorimer
14

Der einfachste Weg, dies zu tun, ist mit der neuen CSS- selectStilmethode:

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

Übergeben Sie es einfach als Argument von 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
quelle
1
Was ist, wenn es Tags wie diese gibt : <td width="580" valign="top">? Ich möchte diese nicht greifen, nur Tags, deren einziges Attribut istvalign="top"
Snaxib
2

Wenn Sie eine Kombination aus der Antwort von Chris Redford und Amr hinzufügen, können Sie mit dem Befehl select auch nach einem Attributnamen mit einem beliebigen Wert suchen:

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]')
GrazingScientist
quelle
Ich habe den gleichen Weg versucht, aber das funktioniert nicht. Gibt es eine Problemumgehung?
Phaneendra Charyulu Kanduri
1
@PhaneendraCharyuluKanduri Entschuldigung, es gab einen fehlerhaften Codierungsfehler im Code. Jetzt sollte Kopieren und Einfügen funktionieren!
GrazingScientist