【问题标题】:BeautifulSoup 3.1 parser breaks far too easilyBeautifulSoup 3.1 解析器太容易崩溃了
【发布时间】:2010-10-02 08:28:43
【问题描述】:

我在用 BeautifulSoup 解析一些不可靠的 HTML 时遇到了麻烦。事实证明,较新版本中使用的 HTMLParser 比以前使用的 SGMLParser 容错性差。


BeautifulSoup 是否有某种调试模式?我正试图弄清楚如何阻止它在我从一个螃蟹网站加载的一些讨厌的 HTML 上运行:

<HTML>
    <HEAD>
        <TITLE>Title</TITLE>
        <HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
    </HEAD>
    <BODY>
        ...
        ...
    </BODY>
</HTML>

BeautifulSoup 在&lt;HTTP-EQUIV...&gt; 标签后放弃

In [1]: print BeautifulSoup(c).prettify()
<html>
 <head>
  <title>
   Title
  </title>
 </head>
</html>

问题显然是 HTTP-EQUIV 标记,它实际上是一个 非常 格式错误的 &lt;META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE"&gt; 标记。显然,我需要将此指定为自动关闭,但无论我指定什么,我都无法修复它:

In [2]: print BeautifulSoup(c,selfClosingTags=['http-equiv',
                            'http-equiv="pragma"']).prettify()
<html>
 <head>
  <title>
   Title
  </title>
 </head>
</html>

有没有一种详细的调试模式,BeautifulSoup 会告诉我它在做什么,这样我就可以弄清楚在这种情况下它把什么当作标签名称?

【问题讨论】:

    标签: python html parsing beautifulsoup


    【解决方案1】:

    试试lxml(及其 html 模块)。尽管它的名字,它也用于解析和抓取 HTML。它比 BeautifulSoup 快得多,它甚至比 BeautifulSoup 更好地处理“损坏”的 HTML。如果你不想学习 lxml API,它也有一个 BeautifulSoup 的兼容性 API。

    Ian Blicking agrees.

    没有理由再使用 BeautifulSoup,除非您使用的是 Google App Engine 或不允许使用任何非纯 Python 的东西。

    【讨论】:

      【解决方案2】:

      Having problems with Beautiful Soup 3.1.0? 建议使用html5lib 的解析器作为解决方法之一。

      #!/usr/bin/env python
      from html5lib import HTMLParser, treebuilders
      
      parser = HTMLParser(tree=treebuilders.getTreeBuilder("beautifulsoup"))
      
      c = """<HTML>
          <HEAD>
              <TITLE>Title</TITLE>
              <HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
          </HEAD>
          <BODY>
              ...
              ...
          </BODY>
      </HTML>"""
      
      soup = parser.parse(c)
      print soup.prettify()
      

      输出:

      <html>
       <head>
        <title>
         Title
        </title>
       </head>
       <body>
        <http-equiv="pragma" content="NO-CACHE">
         ...
              ...
        </http-equiv="pragma">
       </body>
      </html>
      

      输出显示 html5lib 在这种情况下并没有解决问题。

      【讨论】:

        【解决方案3】:

        你的问题一定是别的;它对我来说很好用:

        In [1]: import BeautifulSoup
        
        In [2]: c = """<HTML>
           ...:     <HEAD>
           ...:         <TITLE>Title</TITLE>
           ...:         <HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
           ...:     </HEAD>
           ...:     <BODY>
           ...:         ...
           ...:         ...
           ...:     </BODY>
           ...: </HTML>
           ...: """
        
        In [3]: print BeautifulSoup.BeautifulSoup(c).prettify()
        <html>
         <head>
          <title>
           Title
          </title>
          <http-equiv>
          </http-equiv>
         </head>
         <body>
          ...
                ...
         </body>
        </html>
        
        
        In [4]: 
        

        这是 Python 2.5.2 和 BeautifulSoup 3.0.7a — 可能在旧/新版本中有所不同?这正是 BeautifulSoup 处理得如此漂亮的那种汤,所以我怀疑它在某些时候被改变了……问题中你没有提到的结构还有其他什么吗?

        【讨论】:

        • 我有 Python 2.5.1 和 BeautifulSoup 3.1.0.1。原来的破碎结构不同,但问题中的简化结构也会出现问题。我刚刚运行了您示例中的代码,并且遇到了与以前相同的问题,在 之后没有任何问题。现在我真的很困惑!
        • 一种可能性是 BeautifulSoup 在更新时破坏了某些东西......您是否尝试过从您的问题中复制的文本?
        • crummy.com/software/BeautifulSoup/CHANGELOG.html BeautifulSoup 3.1 基于 HTMLParser 而不是 SGMLParser(因为后者在 Python 3.0 中已消失),这可能是这里的问题。太可惜了……
        • 是的,我尝试使用问题中的确切文本,并且我刚刚再次复制并粘贴以确保。听起来解析器已经改变了。也许我应该删除一个快速的正则表达式来删除 borked HTML。我不会在其他地方遇到类似的事情。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-23
        • 2015-08-25
        • 2017-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多