首页 文章

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

提问于
浏览
7

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

说我有我原来的html文档:

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

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

例如,如果我想在 test 中搜索"here is some silly text",则所需的输出为:

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

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

1 回答

  • 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() 的函数,后者在某些情况下会找不到你想要的内容 .

    在某些情况下, 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) 而不是使用 == ,但您必须了解您的需求以及如何让它选择正确的答案 .

相关问题