Beautiful Soup - tag im tag entfernen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
SimGeh
User
Beiträge: 15
Registriert: Mittwoch 4. Dezember 2013, 16:11

Hallo Leute,

ich versuche derzeit ein HTML-Document zu parsen. Alles funkioniert soweit auch ganz gut. Allerdings stoße ich auf mehrere kleine Probleme. Mein größtes Problem findet sich hiet:

Code: Alles auswählen

<P><FONT FACE="Arial, Helvetica"><B>Text </B>Text Text Text Text;<AUTHOR><B><AUTHORNAME>Text</AUTHORNAME>, <AUTHORNAME>Text</AUTHORNAME></B></AUTHOR></FONT></P
Im Prinzip habe ich alles gefunden was ich haben möchte. Jedoch würde ich gerne den tag von <author> bis </author> mit allem darin entfernen. Gibt es da eine einfache Möglichkeit für?

Gruß,
Simon
BlackJack

@SimGeh: Man kann das Element (und all seine Kinder) einfach durch eine leere Zeichenkette ersetzen:

Code: Alles auswählen

In [18]: soup = BeautifulSoup('<P><FONT FACE="Arial, Helvetica"><B>Text </B>Text Text Text Text;<AUTHOR><B><AUTHORNAME>Text</AUTHORNAME>, <AUTHORNAME>Text</AUTHORNAME></B></AUTHOR></FONT></P>')

In [19]: soup.author.replace_with('')
Out[19]: <author><b><authorname>Text</authorname>, <authorname>Text</authorname></b></author>

In [20]: soup
Out[20]: <html><body><p><font face="Arial, Helvetica"><b>Text </b>Text Text Text Text;</font></p></body></html>
SimGeh
User
Beiträge: 15
Registriert: Mittwoch 4. Dezember 2013, 16:11

Vielen Dank. Hat super funktioniert...
SimGeh
User
Beiträge: 15
Registriert: Mittwoch 4. Dezember 2013, 16:11

Kleiner Follow-Up.
Das ganze funktioniert bisher wunderbar. Ich bin jetzt jedoch auf einen Tag gestoßen, der durch einen Punkt getrennt wird und die ganze Syntax durcheinander wirft.

Code: Alles auswählen

soup.aa.aa.replace_with("")
Ich habe versuch durch einen backslash vor dem Punkt das Problem zu beheben. Leider kam immer folgende Fehlermeldung
SyntaxError: unexpected character after line continuation character
Ich bin mir sicher, dass die Lösung relativ einfach wird. Jedoch habe ich jetzt schon eine ganze Weile gesucht und keine Lösung gefunden.
Wenn jemand ne Idee hat wäre das super...
BlackJack

@SimGeh: Die gezeigte Ausnahme hat nichts mit dem gezeigten Quelltext zu tun. Die Ausnahme sagt das Du irgendwo in Deinem Quelltext einen Backslash hast um eine logische Zeile über mehrere ”physische” Zeilen zu verteilen und das nach diesen Backslash noch ein Zeichen kommt das da nicht hingehört. Das kann zum Beispiel auch ein Leerzeichen sein. Ein Grund warum ich grundsätzlich keine Backslashes für so etwas verwende sondern lieber ein zusätzlich Paar Klammern einführe oder den Ausdruck auf mehrere aufteile.
SimGeh
User
Beiträge: 15
Registriert: Mittwoch 4. Dezember 2013, 16:11

Sorry, ich veilleicht bisschen konfus. Also ich versuche aus meinem HTML-Code einzelne Tags zu entfernen. Das ganze funktioniert wie oben beschrieben wie folgt:

Code: Alles auswählen

soup.irgendeintag.replace_with("")
Das Problem in meinem Fall war jetzt jedoch, dass ich einen Tag habe, der durch einen Punkt getrennt ist.

Code: Alles auswählen

soup.sz.dt.replace_with("")
Der Punkt zerschießt mit leider die ganze Syntax und für zu folgendem Fehler:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'dt'
Ich habe versucht den Punkt mit einem Backslash escapen der jedoch den vorhin zitierten Fehler versachte hat.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Für BeautifulSoup bedeutet soup.foo.bar, dass soup ein Element namens foo und das wiederum ein Element names bar besitzt. Wenn du ein Element hast, dass foo.bar heißt, dann kannst du vermutlich die find() Methode verwenden: soup.find('foo.bar'). Hatte das Problem noch nicht, deswegen habe ich im source code von BeautifulSoup nachgesehen und vermute, dass es so gehen müsste. Ausprobiert habe ich es nicht,
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

Wobei Tagnamen mit Punkt in HTML sehr eigenartig sind, weil es die eigentlich nicht gibt. :?:
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@BlackJack: Dachte ich auch erst. Ein kurzes ddg förderte den XML-Wikipedia-Artikel zu Tage, worin ich fand:
The element tags are case-sensitive; the beginning and end tags must match exactly. Tag names cannot contain any of the characters !"#$%&'()*+,/;<=>?@[\]^`{|}~, nor a space character, and cannot start with -, ., or a numeric digit.

Wie es bei HTML ist, weiß ich nicht. Schau gleich mal.
In specifications, Murphy's Law supersedes Ohm's.
SimGeh
User
Beiträge: 15
Registriert: Mittwoch 4. Dezember 2013, 16:11

Ich habe ein kleines workaround gefunden:
Den Tag habe ich einfach umbenannt und anschließend dann mit replace entfernt :

Code: Alles auswählen

soup.find("sz.dt").name = "sz_dt"
soup.sz_dt.replace_with("")
Das ist etwas umständlicher aber das Ergbenis passt.
Vielen Dank für eure Hilfe!
BlackJack

@pillmuncher: Dass das in XML geht wusste ich aber in Standard HTML gibt es halt keine solchen Tags. Und zwar in keiner Version.

@SimGeh: Oh warum nur!? Du bekommst doch mit `find()` das Element. Dann benennst Du es um, nur um es dann mit dem neuen Namen erneut zu suchen. Du hattest es doch schon. Das macht keinen Sinn.
SimGeh
User
Beiträge: 15
Registriert: Mittwoch 4. Dezember 2013, 16:11

@BlackJack

Im der zweiten Zeile suche ich das Element nicht sondern ich lösche es.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nachdem du es gesucht hast. Da du es aber mittels `find` gefunden hast, kannst du es auch direkt ersetzen, statt es zuerst umzubenennen, wieder zu suchen und dann zu ersetzen.
Antworten