【问题标题】:Beautiful Soup 4: Remove comment tag and its contentBeautiful Soup 4:删除评论标签及其内容
【发布时间】:2014-06-11 13:09:09
【问题描述】:

我正在抓取的页面包含这些 HTML 代码。如何使用 bs4 删除评论标签 <!-- --> 及其内容?

<div class="foo">
cat dog sheep goat
<!-- 
<p>NewPP limit report
Preprocessor node count: 478/300000
Post‐expand include size: 4852/2097152 bytes
Template argument size: 870/2097152 bytes
Expensive parser function count: 2/100
ExtLoops count: 6/100
</p>
-->
</div>

【问题讨论】:

  • 目的是什么?您要解决的问题是什么?

标签: python html web-scraping html-parsing beautifulsoup


【解决方案1】:

有点晚了,但我已经比较了互联网上的主要答案,所以你可以选择最适合你的:

我们也可以通过正则表达式删除 cmets

soupstr=str(soup)
result=re.sub(r'<!.*?->','', soupstr)

但是当我们通过 soupstr=str(soup) 将汤转换为字符串时,这种正则表达式方法比其他人编写的 findAll...isinstance(x,Comment) 慢 4 倍。

但是当您将 html 作为字符串并应用正则表达式处理来删除 cmets 时,速度会快 5 倍。

运行函数 1000 次后的基准测试结果:

bs4,isinstance(x,Comment) method: time: 0.01193189620971680ms
soup convert to string and apply regex: 0.04188799858093262ms
apply regex before converting to soup : 0.00195980072021484ms (WINNER!)

也许你可以在你不想使用 isinstance 方法的情况下使用纯正则表达式。

对于需要快速结果且不想阅读完整答案的人,这里是准备运行的复制粘贴功能:

def remove_comments_regexmethod(soup): 
    #soup argument can be string or bs4.beautifulSoup instance it will auto convert to string, please prefer to input as (string) than (soup) if you want highest speed
    if not isinstance(soup,str): 
        soup=str(soup)
    return re.sub(r'<!.*?->','', soup)#returns a string

【讨论】:

    【解决方案2】:

    From this answer 如果您正在寻找 BeautifulSoup 版本 3 中的解决方案 BS3 Docs - Comment

    soup = BeautifulSoup("""Hello! <!--I've got to be nice to get what I want.-->""")
    comment = soup.find(text=re.compile("if"))
    Comment=comment.__class__
    for element in soup(text=lambda text: isinstance(text, Comment)):
        element.extract()
    print soup.prettify()
    

    【讨论】:

      【解决方案3】:

      可以使用extract()(解决方案基于this answer):

      PageElement.extract() 从树中删除标签或字符串。它 返回提取的标签或字符串。

      from bs4 import BeautifulSoup, Comment
      
      data = """<div class="foo">
      cat dog sheep goat
      <!--
      <p>test</p>
      -->
      </div>"""
      
      soup = BeautifulSoup(data)
      
      div = soup.find('div', class_='foo')
      for element in div(text=lambda text: isinstance(text, Comment)):
          element.extract()
      
      print soup.prettify()
      

      因此,您会在没有 cmets 的情况下获得 div

      <div class="foo">
          cat dog sheep goat
      </div>
      

      【讨论】:

      • 太棒了..这就像魅力,但我在尝试理解 div(text=lambda text: isinstance(text, Comment)): 时遇到问题。你能详细说明它是如何工作的吗?
      • @Flint 是的,这基本上是一种更短的方式来调用find_all()
      • @Flint 以了解 text 在这里的含义 - 请参阅 docs。希望对您有所帮助。
      • 这对于整个文档汤也很有魅力。我使用 html5lib(速度不重要,但验证很重要)。
      【解决方案4】:

      通常不需要修改 bs4 解析树。如果这是您想要的,您可以获取 div 的文本:

      soup.body.div.text
      Out[18]: '\ncat dog sheep goat\n\n'
      

      bs4 将评论分开。但是,如果您确实需要修改解析树:

      from bs4 import Comment
      
      for child in soup.body.div.children:
          if isinstance(child,Comment):
              child.extract()
      

      【讨论】:

      • 看起来很简单,但如果上面问题中的 html 代码是 .find() 的结果,例如bar = soup.find("div", class_="foo"),我将无法使用您的代码
      • text帮了我很多忙
      猜你喜欢
      • 2018-04-26
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      • 2011-07-11
      • 1970-01-01
      • 2011-01-09
      • 1970-01-01
      • 2014-07-11
      相关资源
      最近更新 更多