9

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

假设我有我的原始 html 文档:

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

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

例如,如果我想在test中搜索“here is some silly text” ,那么所需的输出是:

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

有任何想法吗?如果使用 lxml 或正则表达式更合适,我也愿意接受这些解决方案。

4

1 回答 1

7
>>> 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>

我必须将一个函数作为nameto find_allthat compares传递的原因x.text.lower(),而不是仅仅将text参数与一个 compares 函数一起使用x.lower(),是因为后者在某些情况下找不到您显然想要的内容。

在某些情况下,该wrap功能可能无法以这种方式工作。如果没有,您将不得不改为enumerate(matches), 并设置matches[i] = match.wrap(soup.new_tag('mark')). (您不能使用replace_with引用自身的新标签替换标签。)

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

于 2013-05-28T20:31:51.820 回答