2016-08-09 45 views
2

arbeiten Ich habe einige seltsame Verhalten von findAll ‚s Methode bemerkt:BeautifulSoup wie funktioniert findAll

>>> htmls="<html><body><p class=\"pagination-container\">slytherin</p><p class=\"pagination-container and something\">gryffindor</p></body></html>" 
>>> soup=BeautifulSoup(htmls, "html.parser") 
>>> for i in soup.findAll("p",{"class":"pagination-container"}): 
    print(i.text) 


slytherin 
gryffindor 
>>> for i in soup.findAll("p", {"class":"pag"}): 
    print(i.text) 


>>> for i in soup.findAll("p",{"class":"pagination-container"}): 
    print(i.text) 


slytherin 
gryffindor 
>>> for i in soup.findAll("p",{"class":"pagination"}): 
    print(i.text) 


>>> len(soup.findAll("p",{"class":"pagination-container"})) 
2 
>>> len(soup.findAll("p",{"class":"pagination-containe"})) 
0 
>>> len(soup.findAll("p",{"class":"pagination-contai"})) 
0 
>>> len(soup.findAll("p",{"class":"pagination-container and something"})) 
1 
>>> len(soup.findAll("p",{"class":"pagination-conta"})) 
0 

Wenn wir also für pagination-container Suche gibt es sowohl das erste und das zweite p-Tag. Es ließ mich denken, dass es nach einer partiellen Gleichheit sucht: so etwas wie if passed_string in class_attribute_value:. Also habe ich die Saite in findAll Methode gekürzt und es hat nie etwas gefunden!

Wie ist das möglich?

Antwort

4

Zunächst ist class eine spezielle multi-valued space-delimited attribute und hat eine spezielle Handhabung. Wenn Sie soup.findAll("p", {"class":"pag"}) schreiben, sucht BeautifulSoup nach Elementen mit der Klasse pag. Es würde Elementklasse-Wert nach Platz teilen und überprüfen, ob pag unter den aufgeteilten Elementen vorhanden ist. Wenn Sie ein Element mit class="test pag" oder class="pag" hätten, würde es angepasst werden.

Beachten Sie, dass im Fall soup.findAll("p", {"class": "pagination-container and something"}), BeautifulSoup ein Element mit dem genauen class Attributwert übereinstimmen würde. In diesem Fall gibt es keine Aufteilung. Es sieht nur, dass es ein Element gibt, bei dem der vollständige Wert class der gewünschten Zeichenfolge entspricht.

Um einen teilweise Übereinstimmung auf einer der Klassen haben Sie eine regular expression oder a function als Klasse Filterwert bieten kann:

import re 

soup.find_all("p", {"class": re.compile(r"pag")}) # contains pag 
soup.find_all("p", {"class": re.compile(r"^pag")}) # starts with pag 

soup.find_all("p", {"class": lambda class_: class_ and "pag" in class_}) # contains pag 
soup.find_all("p", {"class": lambda class_: class_ and class_.startswith("pag")}) # starts with pag 

Es gibt viel mehr zu sagen, aber Sie sollten auch wissen, dass BeautifulSoup hat CSS selector Unterstützung (eine begrenzte, aber deckt die meisten der häufigsten Anwendungsfälle). Sie können Dinge wie schreiben:

soup.select("p.pagination-container") # one of the classes is "pagination-container" 
soup.select("p[class='pagination-container']") # match the COMPLETE class attribute value 
soup.select("p[class^=pag]") # COMPLETE class attribute value starts with pag 

Handhabung class Attributwerte in BeautifulSoup ist eine gemeinsame Quelle der Verwirrung und Fragen finden Sie in diesen Themen mehr Verständnis zu gewinnen: