2017-01-13 2 views
1

Ich versuche Beautifuloup zu verwenden, um HTML-Tags zu extrahieren und den Text zu löschen. Zum Beispiel nehmen Sie diesen HTML:schöne Suppe extrahieren Tags löschen Text

html_page = """ 
<html> 
<body> 
<table> 
<tr class=tb1><td>Lorem Ipsum dolor Sit amet</td></tr> 
<tr class=tb1><td>Consectetuer adipiscing elit</td></tr> 
<tr><td>Aliquam Tincidunt mauris eu Risus</td></tr> 
<tr><td>Vestibulum Auctor Dapibus neque</td></tr> 
</table> 
</body> 
</html> 
""" 

Das gewünschte Ergebnis ist:

<html> 
<body> 
<table> 
<tr><td></td></tr> 
<tr><td></td></tr> 
<tr><td></td></tr> 
<tr><td></td></tr> 
</table> 
</body> 
</html> 

Hier ist, was ich bisher habe:

def get_tags(soup): 
    copy_soup = soup 
    for tag in copy_soup.findAll(True): 
     tag.attrs = {} # removes attributes of a tag 
     tag.string = '' 

    return copy_soup 

print get_tags(soup) 

Mit tag.attrs = {} arbeitet für Entfernen aller Tag-Attribute Aber wenn ich tag.string oder tag.clear() versuche, bin ich nur mit <html></html> verlassen. Ich verstehe, dass was wahrscheinlich passiert, ist auf der ersten Iteration mit tag.string oder tag.clear() Entfernen aller Inhalte innerhalb der HTML-Tags.

Ich bin mir nicht sicher, wie Sie das beheben können. Vielleicht rekursiv Text von Kindern zuerst rekursiv löschen? Oder gibt es einen einfacheren Ansatz, den ich vermisse?

Antwort

1

Sie können einfach nicht .string auf eine leere Zeichenfolge zurückgesetzt, da, wenn ein Element ein einzelnes Kind mit Text hat, wie tr Elemente in Ihrem Beispiel, würden Sie unbeabsichtigt die td Elemente aus dem Baum entfernen.

Sie können .clear() nicht verwenden, da rekursiv alle untergeordneten Knoten ebenfalls entfernt werden. Ich würde verwenden Sie die folgende Vorgehensweise -

ich die HTML-Baumstruktur, ohne dass die Daten in BeautifulSoup zu bekommen keine integrierte Möglichkeit erinnern:

for elm in soup.find_all(): 
    if not elm.find(recursive=False): # if not children 
     elm.string = '' 
    elm.attrs = {} 

Hier sind wir Zurücksetzen des .string nur dann, wenn sind keine Kinder.

Demo:

>>> from bs4 import BeautifulSoup 
>>> 
>>> html_page = """ 
... <html> 
... <body> 
... <table> 
... <tr class=tb1><td>Lorem Ipsum dolor Sit amet</td></tr> 
... <tr class=tb1><td>Consectetuer adipiscing elit</td></tr> 
... <tr><td>Aliquam Tincidunt mauris eu Risus</td></tr> 
... <tr><td>Vestibulum Auctor Dapibus neque</td></tr> 
... </table> 
... </body> 
... </html> 
... """ 
>>> 
>>> soup = BeautifulSoup(html_page, "html.parser") 
>>> for elm in soup.find_all(): 
...  if not elm.find(recursive=False): 
...   elm.string = '' 
...  elm.attrs = {} 
... 
>>> print(soup.prettify()) 
<html> 
<body> 
    <table> 
    <tr> 
    <td> 
    </td> 
    </tr> 
    <tr> 
    <td> 
    </td> 
    </tr> 
    <tr> 
    <td> 
    </td> 
    </tr> 
    <tr> 
    <td> 
    </td> 
    </tr> 
    </table> 
</body> 
</html> 
+0

Ah danke für die Erklärung, vor allem für die Beschreibung genau, warum wurde mein ursprünglicher Ansatz fehlerhaft. –

+0

@ hannahbanana2.0 froh zu helfen, ich versuche zu sehen, ob es einen schöneren Weg, um Ihr Problem zu lösen ... Blick in 'lxml' und' lxml.objectify' .. – alecxe

+0

@ hannahbanana2.0 BTW, hier ist ein [ziemlich verwandtes Thema] (http://stackoverflow.com/questions/24640959/get-a-structure-of-html-code) mit einem alternativen Ansatz - möglicherweise einfacher als das, was wir hier tun. – alecxe