2009-08-07 3 views
37

Wenn eine Seite <div class="class1"> und <p class="class1"> hat, dann werden soup.findAll(True, 'class1') beide finden.Schöne Suppe kann eine CSS-Klasse nicht finden, wenn das Objekt auch andere Klassen hat.

Wenn es <p class="class1 class2"> hat, aber es wird nicht gefunden werden. Wie finde ich alle Objekte mit einer bestimmten Klasse, unabhängig davon, ob sie auch andere Klassen haben?

+3

** Update **: Diese wurde in 4 Beta angeblich 5 fixiert: https://bugs.launchpad.net/beautifulsoup/+bug/410304 – endolith

Antwort

15

Nur für den Fall, dass jemand auf diese Frage kommt. BeautifulSoup unterstützt jetzt folgendes:

Python 2.7.5 (default, May 15 2013, 22:43:36) [MSC v.1500 32 bit (Intel)] 
Type "copyright", "credits" or "license" for more information. 

In [1]: import bs4 

In [2]: soup = bs4.BeautifulSoup('<div class="foo bar"></div>') 

In [3]: soup(attrs={'class': 'bar'}) 
Out[3]: [<div class="foo bar"></div>] 

Außerdem müssen Sie findAll nicht mehr eingeben.

34

Leider behandelt BeautifulSoup dies als eine Klasse mit einem Leerzeichen 'class1 class2' statt zwei Klassen ['class1','class2']. Eine Problemumgehung besteht darin, einen regulären Ausdruck zu verwenden, um nach der Klasse statt einer Zeichenfolge zu suchen.

Dies funktioniert:

soup.findAll(True, {'class': re.compile(r'\bclass1\b')}) 
+2

https://bugs.launchpad.net/bugs/410304 – endolith

+3

Dies scheint jetzt behoben zu sein. – Kugel

+1

@Kugel: fügen Sie eine andere Antwort dann? – endolith

10

Sie lxml verwenden sollten. Es arbeitet mit mehreren durch Leerzeichen getrennten Klassenwerten ('class1 class2').

Trotz seines Namens ist lxml auch zum Parsen und Scrappen von HTML. Es ist viel, viel schneller als BeautifulSoup und behandelt sogar "kaputtes" HTML besser als BeautifulSoup (ihr Anspruch auf Ruhm). Es hat auch eine Kompatibilitäts-API für BeautifulSoup, wenn Sie die lxml-API nicht lernen wollen.

Ian Bicking agrees und bevorzugt lxml über BeautifulSoup.

Es gibt keinen Grund mehr, BeautifulSoup zu verwenden, es sei denn, Sie befinden sich in der Google App Engine oder in einer anderen Umgebung, in der Python nicht erlaubt ist.

Sie können auch CSS-Selektoren mit lxml verwenden, so ist es viel einfacher zu bedienen als BeautifulSoup. Probieren Sie es in einer interaktiven Python-Konsole aus.

+7

Aus der eigenen Dokumentation von lxml: "Während libxml2 (und damit auch lxml) fehlerhaftes HTML analysieren kann, ist BeautifulSoup etwas fehlerverzeihender und bietet eine bessere Unterstützung für die Erkennung von Kodierungen." – endolith

+0

Ich habe es versucht und es ist in der Tat schöner für diese Art von Sache. – endolith

+0

Froh, dass es Ihnen gefällt. Ich hoffe, Sie werden das Wort auch verbreiten, lxml ist eine unterschätzte Bibliothek. Ich denke, viele übersehen es, da es "XML" im Namen hat und seine Dokumentation ist nicht so schön wie BeautifulSoup's. BS hat mit dem Namen und der Grafik einen Charme, der aus oberflächlichen Gründen etwas an Attraktivität gewinnt. – aehlke

2

Es ist sehr nützlich für einen Tag zu suchen, die eine bestimmte CSS-Klasse, aber der Name des CSS-Attribut „class“, ist ein reserviertes Wort in Python. Wenn Sie die Klasse als Schlüsselwort verwenden, erhalten Sie einen Syntaxfehler. Ab Schöne Suppe 4.1.2 können Sie von CSS-Klasse suchen das Stichwort Argument class_ mit:

Like:

soup.find_all("a", class_="class1") 
+0

Sorry, aber ich glaube deine Antwort ist falsch. Laut dem Beautiful Soup doc (http://www.crummy.com/software/BeautifulSoup/bs3/documentation.html#Searching%20by%20CSS%20class) gibt es zwei Möglichkeiten, 'find_all' zu verwenden, um ein Tag mit einem CSS-Klasse: Übergeben Sie den Klassennamen als String oder erstellen Sie ein Dict mit dem Schlüssel "class" und einem Wert mit dem Namen der CSS-Klasse. –

+0

Froh, dass Sie meine Antwort sehen, aber ich benutze bs4, nicht bs3, vielleicht hat sich die Schnittstelle geändert @ RodrigoTaboada –

+0

Nach dem Beautiful Soup4 doc [link] (http://www.crummy.com/software/BeautifulSoup/bs4/ doc/# searching-by-css-class) –