2014-03-27 11 views
6

Ich möchte die BeautifulSoup Entsprechung von this jQuery question.Wrapping Unterabschnitte von Text mit Tags in BeautifulSoup

Ich möchte eine bestimmte Regex-Übereinstimmung in BeautifulSoup Text finden und ersetzen Sie dann dieses Segment des Textes mit einer verpackten Version. Ich kann dies mit Klartextumhüllung tun:

# replace all words ending in "ug" wrapped in quotes, 
# with "ug" replaced with "ook" 

>>> soup = BeautifulSoup("Snug as a bug in a rug") 
>>> soup 
<html><body><p>Snug as a bug in a rug</p></body></html> 
>>> for text in soup.findAll(text=True): 
... if re.search(r'ug\b',text): 
...  text.replaceWith(re.sub(r'(\w*)ug\b',r'"\1ook"',text)) 
... 
u'Snug as a bug in a rug' 
>>> soup 
<html><body><p>"Snook" as a "book" in a "rook"</p></body></html> 

Aber was, wenn ich Fettdruck anstatt Anführungszeichen möchte? z.B. gewünschtes Ergebnis =

<html><body><p><b>Snook</b> as a <b>book</b> in a <b>rook</b></p></body></html> 

Antwort

3

Also hier ist eine Möglichkeit, es zu tun. Sie könnten regex verwenden, um neues HTML mit den fett umrandeten Wörtern zu erstellen, das in den BeautifulSoup-Konstruktor zu werfen und das gesamte übergeordnete p durch das neue p-Tag zu ersetzen.

import bs4 
import re 

soup = bs4.BeautifulSoup("Snug as a bug in a rug") 
print soup 

for text in soup.findAll(text=True): 
    if re.search(r'ug\b',text): 
     new_html = "<p>"+re.sub(r'(\w*)ug\b', r'<b>\1ook</b>', text)+"</p>" 
     new_soup = bs4.BeautifulSoup(new_html) 
     text.parent.replace_with(new_soup.p) 

print soup 

Eine andere Möglichkeit wäre, die soup.new_tag Methode zu verwenden, aber das könnte eine verschachtelte for-Schleife erfordern, die nicht so elegant sein. Ich werde sehen, ob ich es schreiben und es später hier veröffentlichen kann.

5
for text in soup.findAll(text=True): 
    if re.search(r'ug\b',text): 
    text.replaceWith(BeautifulSoup(re.sub(r'(\w*)ug\b',r'<b>\1ook</b>',text),'html.parser')) 

soup 
Out[117]: <html><body><p><b>Snook</b> as a <b>book</b> in a <b>rook</b></p></body></html> 

Die Idee hier ist, dass wir ein Tag durch einen vollständig geformten Syntaxbaum ersetzen. Der einfachste Weg ist, einfach BeautifulSoup auf unserer regex-subbed-Zeichenkette aufzurufen.

Das etwas magische 'html.parser' Argument zum inneren BeautifulSoup Aufruf ist zu verhindern, dass es <html><body><p> Tags hinzufügen, wie bs4 (naja, lxml wirklich) normalerweise tut. More reading on that.

Verwandte Themen