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

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>

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")

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})

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"]')

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>]

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]')

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.