在 HTML BeautifulSoup 中按文本查找和替换
Posted
技术标签:
【中文标题】在 HTML BeautifulSoup 中按文本查找和替换【英文标题】:Find by Text and Replace in HTML BeautifulSoup 【发布时间】:2013-05-23 21:43:53 【问题描述】:我正在尝试使用 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 或正则表达式更合适,我也愿意接受这些解决方案。
【问题讨论】:
接近另一个问题的副本。 ***.com/questions/8936030/… @melwil - 很接近,但仅涵盖问题的(区分大小写的)文本检索部分。如何使用类似的搜索字符串,在 html 中查找不区分大小写的匹配项,并将这些匹配项包装在标记标签中? 找到文本后,只需将其插入到标记标记中的父级中。 你想如何处理<h1> here is some </h1> <h2> silly text </h2>
?如果你把它变成<h1><mark> here is some </h1> <h2> silly text </mark></h2>
,那么mark
标签跨越两个兄弟元素之间。可以吗?
@Kevin - 是的!我很好
【参考方案1】:
>>> 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()
的函数,因为后者不会在某些情况下找到您显然想要的内容。
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)
而不是使用==
,但您必须了解您想要什么以及如何获得它才能选择正确的答案。
【讨论】:
非常感谢!看起来你可以只用for match in matches: match.wrap(soup.new_tag('mark'))
@MuradSalahi:我只是在测试它。它似乎适用于 4.1.3,但不适用于 4.0.5。我不知道为什么,但我会将其更改为简单版本,并附上解释或不适用于任何人。谢谢!
.lower()
might not be enough for a case-insensitive search in a Unicode text.
@J.F.塞巴斯蒂安:是的。但是如果不知道用例,就不可能描述什么是正确。我会更新答案以涵盖这一点。
如果我想要标记的是“傻文字”怎么办?它跨越了2个标签,所以你不能通过iter all tags找到它。以上是关于在 HTML BeautifulSoup 中按文本查找和替换的主要内容,如果未能解决你的问题,请参考以下文章