代码之家  ›  专栏  ›  技术社区  ›  bukzor

如何使用标准库在Python中解析格式错误的HTML

  •  35
  • bukzor  · 技术社区  · 16 年前

    有那么多 html and xml libraries built into python 很难相信没有对真实HTML解析的支持。

    我已经为这个任务找到了很多优秀的第三方库,但这个问题是关于Python标准库的。

    要求:

    • 仅使用Python标准库组件(任何2.x版本)
    • DOM支持
    • 处理HTML实体(   )
    • 处理部分文档(如: Hello, <i>World</i>! )

    加分:

    • XPath支持
    • 处理未闭合/格式错误的标签。( <big>does anyone here know <html ???

    这是我90%的解决方案。这适用于我尝试过的有限的HTML集,但正如每个人都能清楚地看到的,这并不完全可靠。因为我是通过盯着文档看15分钟和一行代码来做到这一点的,所以我想我可以向stackoverflow社区咨询类似但更好的解决方案…

    from xml.etree.ElementTree import fromstring
    DOM = fromstring("<html>%s</html>" % html.replace('&nbsp;', '&#160;'))
    
    6 回复  |  直到 16 年前
        1
  •  43
  •   Ian Bicking    16 年前

    可靠地解析HTML是一种相对现代的开发(尽管看起来很奇怪)。因此,标准库中肯定没有任何内容。 HTMLParser 可以 出现 作为一种处理HTML的方法,但它不是——它在许多非常常见的HTML上失败了,尽管您可以解决这些失败,但总会有另一种情况是您没有想到的(如果您真的成功地处理了每一个失败,那么基本上您将重新创建漂亮的汤)。

    实际上,只有3种合理的方法来解析HTML(在Web上可以找到): lxml.html , BeautifulSoup html5lib . LXML是目前最快的,但安装起来可能有点困难(在应用程序引擎这样的环境中是不可能的)。HTML5lib是基于HTML5如何指定解析的;尽管在实践中与其他两种方法类似,但它在如何解析损坏的HTML(它们都解析了非常好的HTML)方面可能更“正确”。他们都在分析损坏的HTML方面做了一项体面的工作。虽然我觉得它的API不必要地古怪,但它还是很方便的。

        2
  •  5
  •   David Z    16 年前

    把beautifulsoup的源代码复制到你的脚本中;-)我只是在开玩笑…你能写的任何能完成这项工作的东西,或多或少都会复制类似库中已经存在的功能。

    如果那是 真的? 我不得不问,为什么只使用标准库组件如此重要?

        3
  •  4
  •   mikerobi    16 年前

    您的选择是更改您的需求或复制第三方模块开发人员完成的所有工作。

    漂亮的soup由一个包含大约2000行代码的单独python文件组成,如果这是一个太大的依赖项,那么继续编写自己的代码,它将不会工作得很好,可能也不会小很多。

        4
  •  1
  •   PW.    16 年前

    不符合你对性病的要求,但是 beautifulsoup 很好

        5
  •  1
  •   Mike Graham    16 年前

    我想不出任何流行的语言在其stdlib中都有一个好的、健壮的、启发式的HTML解析库。python当然没有,这是我想你知道的。

    为什么需要stdlib模块?大多数时候,当我听到人们提出这样的要求时,他们是愚蠢的。对于大多数主要任务,您将需要第三方模块或 整批 重新实施的工作。引入依赖关系是 好的 事情,因为那是你不必做的工作。

    所以你想要的是 lxml.html . 如果这是一个问题,那么将LXML与您的代码一起发送,此时它在功能上就相当于您自己编写它,除了在困难、错误和可维护性方面。

        6
  •  0
  •   Michael    13 年前

    如前所述,目前只有StandardLib没有令人满意的解决方案。当我试图在一个过时的主机环境中运行我的程序时,我遇到了和你一样的问题,没有可能安装自己的扩展,只有python2.6。解决方案:

    抓住 this file 最新的马厩 BeautifulSoup 3ER系列的版本(从现在起为3.2.1)。从那里的tar文件中,只有pick BeautifulSoup.py ,这是唯一一个你真正需要与你的代码一起发送的代码。所以你有这两个文件在你的路径中,你需要做的就是,得到一个临时的 etree 来自某些HTML字符串的对象,如从lxml获得的对象,是:

    from StringIO import StringIO
    import ElementSoup
    
    tree = ElementSoup.parse(StringIO(input_str))
    

    lxml本身和html5lib都要求您编译一些C代码以使其运行。让他们工作要付出相当大的努力,如果你的环境受到限制,或者你的目标受众不愿意这样做,就要避免他们。