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.