it-swarm.com.de

Python BeautifulSoup extrahiert Text zwischen Elementen

Ich versuche "DIESES IS MY TEXT" aus dem folgenden HTML zu extrahieren:

<html>
<body>
<table>
   <td class="MYCLASS">
      <!-- a comment -->
      <a hef="xy">Text</a>
      <p>something</p>
      THIS IS MY TEXT
      <p>something else</p>
      </br>
   </td>
</table>
</body>
</html>

Ich habe es so versucht:

soup = BeautifulSoup(html)

for hit in soup.findAll(attrs={'class' : 'MYCLASS'}):
    print hit.text

Aber ich bekomme den gesamten Text zwischen allen verschachtelten Tags plus dem Kommentar.

Kann mir jemand helfen, einfach "DIESES IS MEIN TEXT" herauszuholen?

33

Weitere Informationen zum Navigieren in durch den Analysebaum in BeautifulSoup . Der Parse-Baum hat tags und NavigableStrings (als DIESES IS EIN TEXT). Ein Beispiel

from BeautifulSoup import BeautifulSoup 
doc = ['<html><head><title>Page title</title></head>',
       '<body><p id="firstpara" align="center">This is paragraph <b>one</b>.',
       '<p id="secondpara" align="blah">This is paragraph <b>two</b>.',
       '</html>']
soup = BeautifulSoup(''.join(doc))

print soup.prettify()
# <html>
#  <head>
#   <title>
#    Page title
#   </title>
#  </head>
#  <body>
#   <p id="firstpara" align="center">
#    This is paragraph
#    <b>
#     one
#    </b>
#    .
#   </p>
#   <p id="secondpara" align="blah">
#    This is paragraph
#    <b>
#     two
#    </b>
#    .
#   </p>
#  </body>
# </html>

Um den Analysebaum nach unten zu verschieben, haben Sie contents und string.

  • inhalt ist eine geordnete Liste der in einem Seitenelement enthaltenen Objekte Tag und NavigableString

  • wenn ein Tag nur einen untergeordneten Knoten hat und dieser untergeordnete Knoten eine Zeichenfolge ist, wird der untergeordnete Knoten als tag.string sowie als tag.contents [0] verfügbar gemacht.

Für das Obige heißt das, dass Sie bekommen können

soup.b.string
# u'one'
soup.b.contents[0]
# u'one'

Für mehrere untergeordnete Knoten können Sie beispielsweise haben

pTag = soup.p
pTag.contents
# [u'This is paragraph ', <b>one</b>, u'.']

also können Sie hier mit contents spielen und Inhalte an dem gewünschten Index abrufen.

Sie können auch über ein Tag iterieren. Dies ist eine Verknüpfung. Zum Beispiel,

for i in soup.body:
    print i
# <p id="firstpara" align="center">This is paragraph <b>one</b>.</p>
# <p id="secondpara" align="blah">This is paragraph <b>two</b>.</p>
35
kiriloff

Sie können .contents :

>>> for hit in soup.findAll(attrs={'class' : 'MYCLASS'}):
...     print hit.contents[6].strip()
... 
THIS IS MY TEXT
14
TerryA

Verwenden .children stattdessen:

from bs4 import NavigableString, Comment
print ''.join(unicode(child) for child in hit.children 
    if isinstance(child, NavigableString) and not isinstance(child, Comment))

Ja, das ist ein bisschen wie ein Tanz.

Ausgabe:

>>> for hit in soup.findAll(attrs={'class' : 'MYCLASS'}):
...     print ''.join(unicode(child) for child in hit.children 
...         if isinstance(child, NavigableString) and not isinstance(child, Comment))
... 




      THIS IS MY TEXT
12
Martijn Pieters

mit Ihrem eigenen Suppenobjekt:

soup.p.next_sibling.strip()
  1. sie greifen direkt mit soup.p * auf das <p> zu (dies hängt davon ab, dass es das erste <p> im Analysebaum ist)
  2. verwenden Sie dann next_sibling für das Tag-Objekt, das soup.p zurückgibt, da der gewünschte Text auf derselben Ebene des Analysebaums wie das <p> verschachtelt ist
  3. .strip() ist nur eine Python str-Methode zum Entfernen von führenden und nachfolgenden Leerzeichen

* sonst nur find das Element mit Ihrer Wahl von filter (s)

im Interpreter sieht das so aus:

In [4]: soup.p
Out[4]: <p>something</p>

In [5]: type(soup.p)
Out[5]: bs4.element.Tag

In [6]: soup.p.next_sibling
Out[6]: u'\n      THIS IS MY TEXT\n      '

In [7]: type(soup.p.next_sibling)
Out[7]: bs4.element.NavigableString

In [8]: soup.p.next_sibling.strip()
Out[8]: u'THIS IS MY TEXT'

In [9]: type(soup.p.next_sibling.strip())
Out[9]: unicode
10
Gregory Kremler

Kurze Antwort: soup.findAll('p')[0].next

Reale Antwort: Sie benötigen einen unveränderlichen Bezugspunkt, von dem aus Sie zu Ihrem Ziel gelangen.

Sie erwähnen in Ihrem Kommentar zu Haidros Antwort, dass sich der gewünschte Text nicht immer an derselben Stelle befindet. Finden Sie einen Sinn, in dem es sich in Bezug auf ein Element an derselben Stelle befindet. Finden Sie dann heraus, wie Sie BeautifulSoup dazu bringen, auf diesem unveränderlichen Pfad durch den Analysebaum zu navigieren.

In dem HTML-Code, den Sie im ursprünglichen Beitrag angegeben haben, wird die Zielzeichenfolge beispielsweise unmittelbar nach dem ersten Absatzelement angezeigt, und dieser Absatz ist nicht leer. Da findAll('p') Absatzelemente findet, ist soup.find('p')[0] das erste Absatzelement.

Sie könnten in diesem Fall soup.find('p') verwenden, aber soup.findAll('p')[n] ist allgemeiner, da Ihr tatsächliches Szenario möglicherweise den 5. Absatz oder etwas Ähnliches benötigt.

Das Feldattribut next ist das nächste analysierte Element in der Struktur, einschließlich der untergeordneten Elemente. Also enthält soup.findAll('p')[0].next den Text des Absatzes, und soup.findAll('p')[0].next.next gibt Ihr Ziel in dem bereitgestellten HTML zurück.

6
Bennett Brown
soup = BeautifulSoup(html)
for hit in soup.findAll(attrs={'class' : 'MYCLASS'}):
  hit = hit.text.strip()
  print hit

Dies wird drucken: DIESES IS MY TEXT Try this ..

2
Naiswita

Die BeautifulSoup-Dokumentation enthält ein Beispiel zum Entfernen von Objekten aus einem Dokument mithilfe der extract-Methode. Im folgenden Beispiel sollen alle Kommentare aus dem Dokument entfernt werden:

Elemente entfernen

Sobald Sie einen Verweis auf ein Element haben, können Sie es mit der Methode extract aus dem Baum ziehen. Dieser Code entfernt alle Kommentare aus einem Dokument:

from BeautifulSoup import BeautifulSoup, Comment
soup = BeautifulSoup("""1<!--The loneliest number-->
                    <a>2<!--Can be as bad as one--><b>3""")
comments = soup.findAll(text=lambda text:isinstance(text, Comment))
[comment.extract() for comment in comments]
print soup
# 1
# <a>2<b>3</b></a>
1
alireza sanaee