2017-02-13 4 views
1

Ich habe ein Problem, wo supple.find_all für ein bestimmtes Tag h2 erfolgreich ist, aber supp.find, das den Text angibt, schlägt fehl.Beautifulsoup-Tag - find_all erfolgreich, aber nicht erfolgreich gefunden

Ich muss die h2-Tags mit verschiedenen Text wie Einführung, Ergebnisse usw. wie im beigefügten Bild gezeigt finden.

Kann jemand bitte beraten? Vielen Dank.

print(soup.find_all('h2')) 
[<h2 class="Heading">Abstract</h2>, 
<h2 class="Heading" data-role="collapsible-handle" tabindex="-1">Introduction<span class="section-icon"></span></h2>, 
<h2 class="Heading" data-role="collapsible-handle" tabindex="-1">Patients and methods<span class="section-icon"></span></h2>, 
<h2 class="Heading" data-role="collapsible-handle" tabindex="-1">Results<span class="section-icon"></span></h2>, 
<h2 class="Heading" data-role="collapsible-handle" tabindex="-1">Discussion<span class="section-icon"></span></h2>, 
<h2 class="Heading" data-role="collapsible-handle" id="copyrightInformation" tabindex="-1">Copyright information<span class="section-icon"></span></h2>, 
<h2 class="Heading" data-role="collapsible-handle" id="aboutarticle" tabindex="-1">About this article<span class="section-icon"></span></h2>, 
<h2 class="u-isVisuallyHidden">Article actions</h2>, <h2 class="u-h4 u-jsIsVisuallyHidden">Article contents</h2>, 
<h2 class="u-isVisuallyHidden">Cookies</h2>] 

print(soup.find('h2', text='Introduction')) 
None 
+0

Bitte zeigen Sie das HTML-Dokument, das Sie als Eingabe verwenden. Vielen Dank! Weitere Hilfe: http://stackoverflow.com/help/mcve. –

Antwort

2

Versuchen Sie folgendes:

soup.find(lambda el: el.name == "h2" and "Introduction" in el.text) 
+0

Danke. Ich brauche aber auch die h2-Tags als reine "Einführung", ohne dass sie anderen Strings wie "Einführung in das Dokument" entsprechen. Neben dem Hinzufügen einer Regex zum Entfernen der Span-Tags gibt es noch einen anderen Weg? –

+1

'supp.find (Lambda el: el.name ==" h2 "und el.text == 'Einführung')' –

+0

Danke. Dies ist eine ausgezeichnete Lösung. Wie löste diese Methode das Problem bei der Verwendung von text = "Einführung" wie in der Frage nicht? Es scheint mir, dass beide nach der Textvariablen suchen, um "Einführung" zu sein. –

-2

text='Introduction' sucht nach navigable strings, nicht tags

Aus der Dokumentation:

Text ist ein Argument, das Sie für NavigableString Objekte suchen können anstelle von Tags

Sie sollten versuchen:

print(soup.find(text='Introduction').parent) 
+0

"Einführung" Text kann in einem beliebigen Tag sein (zum Beispiel in "span"). –

+0

Das OP hat nicht versucht nach Tags mit 'text = 'Einführung' zu suchen, Sie müssen die Frage falsch verstanden haben. –

+1

Sie haben Recht mit NavigableString, aber in diesem Fall ist es 'None' wegen der' h2' Tag enthält ein anderes Tag –

0

Wenn wir text/string als Filter verwenden, was unter der Haube passiert ist, wir tag.string, um den Text zu erhalten und mit dem Filter, in diesem Fall vergleichen:

import bs4 

html = '''<h2 class="Heading" data-role="collapsible-handle" tabindex="-1">Introduction<span class="section-icon"></span></h2>''' 
soup = bs4.BeautifulSoup(html,'lxml') 
print(soup.h2.string) 

aus:

None 

Wh y die Zeichenfolge Rückkehr None:

Wenn ein Tag mehr als eine Sache enthält, dann ist es nicht klar, was .String sollte beziehen, so ist .String definiert Keine sein:

die h2 Tag enthält den span Tag mit leerem Text, es ist verwirrt und wird None

zurückgeben

@Thomas Lehoux 's Antwort ist richtiger Ansatz.

Dies ist BS3 API:

findNextSiblings(name, attrs, text, limit, **kwargs) 

Dies ist BS4 API:

find_next_siblings(name, attrs, string, limit, **kwargs) 

Sie, dass die alte Nutzung text, die aktuelle Nutzung string, aber sie alle gleich bemerken, sie alle verwenden tag.string, um Wert zu erhalten, können Sie beide verwenden. BS4 hat nur das alte Format, das ist alles.

Ich kann keine tag.text API in beiden Versionen finden, aber es verhält sich wie tag.get_text(), es verkettet den gesamten Text unter dem Tag.

in Ihnen Fall:

soup.h2.string >>> None 
soup.h2.text  >>> Introduction 
soup.h2.get_text()>>> Introduction 

Kurz:

text in filter is tag.string 
text in tag itself is tag.text 

Ich glaube, Sie find(string=' ') in der Praxis zu verwenden, es ist weniger verwirrend.

+0

Danke. Ich wusste nicht, dass es durch das Span-Tag verwirrt werden würde. Ja, ich denke @ Thomas Lehoux nähert sich ihm. Aber ich möchte h2 Tags, wo die Zeichenfolge rein "Einführung" ist. Neben dem Hinzufügen einer Regex zum Entfernen der Span-Tags gibt es noch einen anderen Weg? –

+0

@Michael Lam 'supp.find (Lambda el: el.name ==" h2 "und el.text ==" Einführung "). Text', da der Text des span-Tags leer ist, liefert der Text genau die Zeichenkette von h2 Tag –

+0

Warum funktioniert die Übergabe einer Lambda-Funktion mit text == "Einführung" anders als die Verwendung von .find ("h2", text = "Einführung")? –

Verwandte Themen