我正在尝试使用 python 中的 Beutifulsoap4 替换 html 文档中的所有文本,包括其中包含文本和其他元素的元素。例如我想让
<div>text1<strong>text2</strong>text3</div>
变成<div>text1_changed<strong>text2_changed</strong>text3_changed</div>
.
我知道线程 在所有 dom 元素中替换文本的更快方法?,但是这使用 Javascript,因此使用的函数在 python 中不可用。我想使用本机 python 实现相同的目标
如果所有标签都包含标签或文本(rand_text 函数返回一个随机字符串),我有一个代码已经有效:
from bs4 import BeautifulSoup as bs
def randomize(html):
soup = bs(html, features='html.parser')
elements = soup.find_all()
for el in elements:
if el.string == None:
pass
else:
replacement = rand_text(el.text)
el.string.replace_with(replacement)
return soup
然而,当元素的“string”属性为 None 时,这段代码在上面的示例中不起作用,因为它同时包含其他元素和文本。
如果“string”属性为 None,我也尝试创建一个新元素,然后替换整个元素:
from bs4 import BeautifulSoup as bs
def anonymize2(html):
soup = bs(html, features='html.parser')
elements = soup.find_all()
for el in elements:
replacement = rand_text(el.text)
if el.string:
el.string.replace_with(replacement)
else:
new_el = soup.new_tag(el.name)
new_el.attrs = el.attrs
for sub_el in el.contents:
new_el.append(sub_el)
new_el.string = replacement
parent = el.parent
if parent:
if new_el not in soup:
soup.append(new_el)
parent.replace_with(new_el)
return soup
但是这个给出了错误“ValueError:当要替换的元素不是树的一部分时,无法用另一个元素替换一个元素。” 我想我收到了这个错误,因为算法已经替换了它试图替换的元素的父元素。我可以实施什么逻辑来解决这个问题?或者我怎样才能用不同的方法实现我最初的目标?
可以遍历元素的
contents
,检查每一项是否为字符串,然后替换字符串。
from bs4 import BeautifulSoup as bs
def randomize(html):
soup = bs(html, features='html.parser')
elements = soup.find_all()
for el in elements:
replacement = rand_text(el.text)
if el.string:
el.string.replace_with(replacement)
else:
for sub_el in el.contents:
if isinstance(sub_el, str):
sub_el.replace_with(rand_text(sub_el))
return soup
# defined for testing purposes. Replace this with your own logic
def rand_text(text):
return text + "_changed"
html = "<div>text1<strong>text2</strong>text3</div>"
print(randomize(html))
输出:
<div>text1_changed<strong>text2_changed</strong>text3_changed</div>