2009-05-14 6 views
52

Ich versuche, die Elemente in einem HTML-Dokument zu erhalten, die das folgende Muster von Text enthalten: # \ S {11}BeautifulSoup Mit einem HTML-Tag zu finden, die einen bestimmten Text enthält

<h2> this is cool #12345678901 </h2> 

Also, die

soup('h2',text=re.compile(r' #\S{11}')) 

Und die Ergebnisse wären so etwas wie:

[u'blahblah #223409823523', u'thisisinteresting #293845023984'] 

ich bin in der Lage zu bekommen alle den Text, den m vorherige unter Verwendung würde passen atches (siehe Zeile oben). Aber ich möchte, dass das Elternelement des Textes übereinstimmt, also kann ich das als Ausgangspunkt für das Durchlaufen des Dokumentenbaums verwenden. In diesem Fall möchte ich, dass alle h2-Elemente zurückgegeben werden, nicht die Textübereinstimmungen.

Ideen?

+3

Tatsächlich wird die h2-Einschränkung gemäß der BeautifulSoup-Dokumentation ignoriert: "Wenn Sie Text verwenden, werden alle Werte, die Sie für den Namen und die Schlüsselwortargumente angeben, ignoriert." – Rabarberski

+0

@Rabarberski Nicht sicher, was die Situation in 2010 war, aber [bis 2012] (https://web.archive.org/web/20120427003845/http://www.crummy.com/software/BeautifulSoup/bs4/doc/ # the-text-argument) findet, dass 'text' (oder' string', die es ersetzt) ​​keine anderen Einschränkungen ignoriert. –

Antwort

61
from BeautifulSoup import BeautifulSoup 
import re 

html_text = """ 
<h2>this is cool #12345678901</h2> 
<h2>this is nothing</h2> 
<h1>foo #126666678901</h1> 
<h2>this is interesting #126666678901</h2> 
<h2>this is blah #124445678901</h2> 
""" 

soup = BeautifulSoup(html_text) 


for elem in soup(text=re.compile(r' #\S{11}')): 
    print elem.parent 

Drucke:

<h2>this is cool #12345678901</h2> 
<h2>this is interesting #126666678901</h2> 
<h2>this is blah #124445678901</h2> 
+0

Danke! Es ist verwirrend, dass es eine Liste mit Unicode-Strings zurückgegeben hat. Ich schätze die Hilfe. – sotangochips

+2

'.parent' war super! Ich habe niemals darüber nachgedacht. Danke @nosklo. +1 –

+0

Wenn Sie die Ausgabe von der Suche sofort iterieren wollen, dann ist für perfekt. Wie wäre es mit einem Listenverständnis als solches: [elem.parent für element in suppe (text = re.compile (r '# \ S {11}'))] – peterb

12

BeautifulSoup Suchoperationen liefern [Liste] BeautifulSoup.NavigableString Objekte, wenn text= als Kriterium verwendet wird, wie in anderen Fällen zu BeautifulSoup.Tag gegenüber. Überprüfen Sie die __dict__ des Objekts, um die Attribute zu sehen, die Ihnen zur Verfügung gestellt werden. Von diesen Attributen ist parent gegenüber previous wegen changes in BS4 bevorzugt.

from BeautifulSoup import BeautifulSoup 
from pprint import pprint 
import re 

html_text = """ 
<h2>this is cool #12345678901</h2> 
<h2>this is nothing</h2> 
<h2>this is interesting #126666678901</h2> 
<h2>this is blah #124445678901</h2> 
""" 

soup = BeautifulSoup(html_text) 

# Even though the OP was not looking for 'cool', it's more understandable to work with item zero. 
pattern = re.compile(r'cool') 

pprint(soup.find(text=pattern).__dict__) 
#>> {'next': u'\n', 
#>> 'nextSibling': None, 
#>> 'parent': <h2>this is cool #12345678901</h2>, 
#>> 'previous': <h2>this is cool #12345678901</h2>, 
#>> 'previousSibling': None} 

print soup.find('h2') 
#>> <h2>this is cool #12345678901</h2> 
print soup.find('h2', text=pattern) 
#>> this is cool #12345678901 
print soup.find('h2', text=pattern).parent 
#>> <h2>this is cool #12345678901</h2> 
print soup.find('h2', text=pattern) == soup.find('h2') 
#>> False 
print soup.find('h2', text=pattern) == soup.find('h2').text 
#>> True 
print soup.find('h2', text=pattern).parent == soup.find('h2') 
#>> True 
+0

Für mich 'supp.find ('h2', text = pattern) 'gibt das Tag direkt an, kein Aufruf von' .parent'. Auch die [Dokumentation] (https://www.crummy.com/software/BeautifulSoup/bs4/doc/#the-string-argument) sagt, dass Sie den Parameter 'string' (' text' in früheren Versionen) mit kombinieren können Argumente, die Tags finden. In diesem Fall gibt BeautifulSoup das Tag zurück – raffamaiden

0

Mit BS4 (Schöne Suppe 4), der Versuch des OP funktioniert genau wie erwartet:

from bs4 import BeautifulSoup 
soup = BeautifulSoup("<h2> this is cool #12345678901 </h2>") 
soup('h2',text=re.compile(r' #\S{11}')) 

kehrt [<h2> this is cool #12345678901 </h2>].