2016-03-25 5 views
1

Ich finde in Python 2.7, dass ich eine nicht rekursive bs4.BeautifulSoup.find_all nicht tun kann, wenn ich den Builder lxml verwende.Nicht-rekursive Suche mit LXML-Builder

Nehmen Sie das folgende Beispiel HTML-Schnipsel:

<p> <b> Cats </b> are interesting creatures </p> 

<p> <b> Dogs </b> are cool too </p> 

<div> 
<p> <b> Penguins </b> are pretty neat, but they're inside a div </p> 
</div> 

<p> <b> Llamas </b> don't live in New York </p> 

sagen, dass ich alle p Elemente finden möchten, die direkte Kinder sind. Ich mache eine nicht-rekursive find_all mit find_all("p", recursive=False).

Um dies zu testen, setze ich das oben genannte HTML-Snippet in einer Variablen namens html. Dann habe ich zwei BeautifulSoup Fällen a und b:

a = bs4.BeautifulSoup(html, "html.parser") 
b = bs4.BeautifulSoup(html, "lxml") 

Beide richtig ausführen, wenn find_all mit normal:

>>> a.find_all("p") 
[<p> <b> Cats </b> are interesting creatures </p>, <p> <b> Dogs </b> are cool too </p>, <p> <b> Penguins </b> are pretty neat, but they're inside a div </p>, <p> <b> Llamas </b> don't live in New York </p>] 
>>> b.find_all("p") 
[<p> <b> Cats </b> are interesting creatures </p>, <p> <b> Dogs </b> are cool too </p>, <p> <b> Penguins </b> are pretty neat, but they're inside a div </p>, <p> <b> Llamas </b> don't live in New York </p>] 

aber wenn ich rekursive Befund ausschalten, nur a funktioniert. b gibt eine leere Liste zurück:

>>> a.find_all("p", recursive=False) 
[<p> <b> Cats </b> are interesting creatures </p>, <p> <b> Dogs </b> are cool too </p>, <p> <b> Llamas </b> don't live in New York </p>] 
>>> b.find_all("p", recursive=False) 
[] 

Warum ist das? Ist das ein Fehler, oder mache ich etwas falsch? Unterstützt der lxml Builder nicht-rekursive find_all?

Antwort

1

Dies liegt daran, lxml Parser würden Ihren HTML-Code in html/body setzen, wenn es nicht vorhanden ist:

>>> b = bs4.BeautifulSoup(html, "lxml") 
>>> print(b) 
<html><body><p> <b> Cats </b> are interesting creatures </p> 
<p> <b> Dogs </b> are cool too </p> 
<div> 
<p> <b> Penguins </b> are pretty neat, but they're inside a div </p> 
</div> 
<p> <b> Llamas </b> don't live in New York </p> 
</body></html> 

Und damit der find_all() in nicht-rekursive Modus versuchen würde, Elemente innerhalb html Element zu finden, die hat ein nur body Kind:

>>> print(b.find_all("p", recursive=False)) 
[] 
>>> print(b.body.find_all("p", recursive=False)) 
[<p> <b> Cats </b> are interesting creatures </p>, <p> <b> Dogs </b> are cool too </p>, <p> <b> Llamas </b> don't live in New York </p>] 
+0

Dies scheint wie eine Inkonsistenz zu mir, warum sollten sich verschiedene Parser auf diese Weise anders verhalten? –

+1

@LukeTaylor könnte es verwirrend sein, stimme ich zu. Es gibt einige Informationen darüber in [Unterschiede zwischen Parsern] (http://www.crummy.com/software/BeautifulSoup/bs4/doc/#differences-between-parsers) Dokumentation Absatz. Es kommt auf verschiedene Parser an, die ein nicht gut formatiertes HTML zu einem gültigen machen - sie machen es alle anders. – alecxe