在HTML BeautifulSoup中按文本查找并替换

时间:2013-05-28 19:45:30

标签: python regex html-parsing beautifulsoup lxml

我正在尝试使用python和BeautifulSoup标记一个HTML文件(字面上用“mark”标签包装字符串)。问题基本上如下......

说我有原始的html文档:

test = "<h1>oh hey</h1><div>here is some <b>SILLY</b> text</div>"

我想对本文档中的字符串进行不区分大小写的搜索(忽略HTML)并将其包装在“mark”标记中。所以我想说我想在html中找到“这里有一些愚蠢的文字”(忽略粗体标签)。我想把匹配的html包装成“mark”标签。

例如,如果我想在测试中搜索“这里有一些愚蠢的文字”,那么所需的输出是:

"<h1>oh hey</h1><div><mark>here is some <b>SILLY</b> text</mark></div>"

有什么想法吗?如果使用lxml或正则表达式更合适,我也会对这些解决方案持开放态度。

1 个答案:

答案 0 :(得分:5)

>>> soup = bs4.BeautifulSoup(test)
>>> matches = soup.find_all(lambda x: x.text.lower() == 'here is some silly text'):
>>> for match in matches:
...     match.wrap(soup.new_tag('mark'))
>>> soup
<html><body><h1>oh hey</h1><mark><div>here is some <b>SILLY</b> text</div></mark></body></html>

我必须将一个函数作为name传递给find_all来比较x.text.lower(),而不是仅使用text参数和一个比较{x.lower()的函数1}},后者在某些情况下找不到你想要的内容。

wrap函数在某些情况下可能无法正常工作。如果没有,则必须改为enumerate(matches),并设置matches[i] = match.wrap(soup.new_tag('mark'))。 (您无法使用replace_with将标记替换为引用自身的新标记。)

另请注意,如果您的预期用例允许任何非ASCII字符串匹配'here is some silly text'(或者如果您想扩展代码以处理非ASCII搜索字符串),则上面的代码使用{{1可能不正确。您可能需要致电lower()和/或str.casefold()和/或使用locale.strxfrm(s)而不是使用locale.strcoll(s, t),但您必须了解您的需求以及如何获取它选择了正确的答案。