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

时间:2010-04-20 16:29:21

标签: python html dom parsing html-parsing

有很多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 个答案:

答案 0 :(得分:43)

可靠地解析HTML是一个相对现代的发展(尽管可能看起来很奇怪)。因此,标准库中绝对没有任何内容。 HTMLParser可能出现是一种处理HTML的方法,但事实并非如此 - 它在很多非常常见的HTML上都失败了,虽然你可以解决这些失败,但总会有另一种情况你没有想到(如果你真的成功地处理了每一次失败,你基本上都会重建BeautifulSoup)。

实际上只有3种合理的方法可以解析HTML(因为它可以在网络上找到):lxml.htmlBeautifulSouphtml5lib。到目前为止,lxml是最快的,但安装起来可能有点棘手(在App Engine这样的环境中也是如此)。 html5lib基于HTML 5如何指定解析;虽然在实践中与其他两个类似,但它在解析破碎的HTML方面可能更“正确”(它们都解析相当好的HTML)。他们都在解析破碎的HTML方面做得很好。尽管我发现它的API不必要地古怪,但是BeautifulSoup可以很方便。

答案 1 :(得分:5)

获取BeautifulSoup的源代码并将其复制到您的脚本中;-)我只是在开玩笑......你能编写的任何能够完成工作的东西都会或多或少地复制库中已经存在的功能那样的。

如果那个真的无法正常工作,我不得不问,为什么只使用标准库组件这么重要?

答案 2 :(得分:4)

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

漂亮的汤包含一个包含大约2000行代码的python文件,如果这个代码太大,那么请继续编写自己的代码,它将无法正常工作,可能不会是一个整体很小。

答案 3 :(得分:1)

不符合您对std的要求,但beautifulsoup很好

答案 4 :(得分:1)

我想不出任何流行的语言在其stdlib中有一个好的,健壮的,启发式的HTML解析库。 Python肯定没有,这是我认为你知道的。

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

所以你想要的是lxml.html。如果这是一个问题,请使用您的代码发送lxml,此时它在功能上等同于自己编写,除了难度,bugginess和可维护性。

答案 5 :(得分:0)

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

抓取this file以及3er系列的最新稳定BeautifulSoup版本(截至目前为3.2.1)。从那里的tar文件中,只选择BeautifulSoup.py,它是您真正需要随代码一起提供的唯一一个。所以你在你的路径中有这两个文件,你需要做的就是从一些HTML字符串中获取一个偶然的etree对象,就像从lxml中得到它一样,是这样的:

from StringIO import StringIO
import ElementSoup

tree = ElementSoup.parse(StringIO(input_str))

lxml本身和html5lib都​​需要你编译一些C代码才能使它运行。要让它们正常工作要付出相当大的努力,如果您的环境受到限制,或者您的目标受众不愿意这样做,请避免使用它们。