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

Posted

技术标签:

【中文标题】如何使用标准库在 python 中解析格式错误的 HTML【英文标题】:How to parse malformed HTML in python, using standard libraries 【发布时间】:2011-02-10 05:40:55 【问题描述】:

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 分钟和一行代码来做到这一点的,所以我认为我可以咨询 *** 社区以寻求类似但更好的解决方案...

from xml.etree.ElementTree import fromstring
DOM = fromstring("<html>%s</html>" % html.replace('&nbsp;', '&#160;'))

【问题讨论】:

我不明白。你期待我们做什么?你知道 stdlib 中没有这样的模块。你有什么问题? @bukzor:我认为你误解了标准库背后的想法。 @bukzor:如果你能用 std. libs,指出一些你不能做的明确例子。如果您在可以轻松传递 Python 脚本的地方工作,那么您的听众不应该在 15 秒内安装一个漂亮的打包库,特别是如果您将它下载到您的内部网并提供了一个方便的花花公子链接在电子邮件中。如果您是系统管理员,也许重新打包一堆有用的并将它们推出? @SilentGhost:一个常见的 python 座右铭是“包含电池”,这意味着您应该能够使用 stdlib 完成大多数任务。也许 HTML DOM 不是其中之一。这就是这个问题想要澄清的。 @buzkor:正如 mikerobi 所指出的,BeautifulSoup 源非常小,所以如果你真的想要一个没有 3P 依赖的单文件脚本,复制粘贴听起来是你最好的选择,然后跳过试图将一些标准库拼接在一起。 【参考方案1】:

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

解析 HTML 的合理方法实际上只有 3 种(可在网上找到):lxml.html、BeautifulSoup 和 html5lib。 lxml 是迄今为止最快的,但安装起来可能有点棘手(在 App Engine 这样的环境中是不可能的)。 html5lib 基于 HTML 5 如何指定解析;尽管在实践中与其他两个相似,但它在解析损坏的 HTML 的方式上可能更“正确”(它们都同样解析非常好的 HTML)。他们在解析损坏的 HTML 方面都做得很好。 BeautifulSoup 可以很方便,尽管我发现它的 API 不必要地古怪。

【讨论】:

很好的答案。谢谢!我没有足够的代表来提升你。 QQ 我希望人们不要对棘手的问题那么敏感。优秀的科学家也会寻求负面实验。 @Ian Bicking:终于有足够的代表来打击你了。只是为了确认一下,没有已知的方法可以让 ElementTree(因为它存在于标准库中)来解析真实世界的 HTML? 你可以让 BeautifulSoup (with ElementSoup) 或 html5lib 解析 HTML 并生成 ElementTree 结构,但 ElementTree 本身肯定无法解析 HTML。 经过一些修改和一些 HTML 更正,我已经让 ElementTree 解析所有 RosettaCode.org。最烦人的部分是手动将所有 html 实体添加到解析器中。在 etree 文档中甚至还有一个选项,但由于未记录的原因,它没有实现。你可以在这里看到代码:bukzor.hopto.org/svn/software/python/rosetta_pylint.py【参考方案2】:

获取 BeautifulSoup 的源代码并将其复制到您的脚本中 ;-) 我只是在开玩笑......您可以编写的任何可以完成这项工作的内容或多或少都会复制库中已经存在的功能像这样。

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

【讨论】:

这不是那么重要。这只是我的问题。正如我所说,python 库中有大量的 html 和 xml 支持。似乎那里的东西应该支持这一点。如果不是,那也是一个答案,但我还不相信。 请注意,BeautifulSoup 不再维护。我自己更喜欢 lxml.html。总的来说,这是一个很好的答案。 你从哪里听到的? BeautifulSoup 网站没有显示它不再被维护的证据。事实上,最近一次发布是在 11 天前。 (当然,任何其他第三方 HTML 解析器都适用于我在答案中提出的论点) 也许他认为 BS 3.0 仅适用于 Python 3.x?他们的网站指出 BS 3.0 适用于 Py 2.3-2.6,而 BS 3.1 适用于 Py 3.x(具有讽刺意味的是,BS 3.1 的最后一个版本大约有一年的历史,而 BS 3.0 则需要几周时间) @bukzor,ElementSoup 是 ElementTree 的一个实现,使用 BeautifulSoup 进行解析。 ElementTree 是一种 API,具有许多用于解析 XML 和 HTML 的实现。【参考方案3】:

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

Beautiful soup 由一个包含大约 2000 行代码的单个 python 文件组成,如果依赖关系太大,那就自己写吧,它不会那么好用,可能不会是一个整体小很多。

【讨论】:

如果它真的那么紧凑(从不费心去看 :P)并且他一心想要让脚本工作没有任何其他依赖项,那么复制粘贴听起来是个不错的计划。 文字复制粘贴是一种添加依赖的荒谬方式。【参考方案4】:

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

【讨论】:

这是我引用的库之一:“我已经为这项任务找到了很多很棒的第三方库,但这个问题是关于 python 标准库的。”【参考方案5】:

我想不出任何流行的语言在其标准库中具有良好、健壮、启发式的 HTML 解析库。 Python 当然没有,我想你知道这一点。

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

所以你想要的是lxml.html。如果这是一个问题,则将 lxml 与您的代码一起提供,此时它在功能上等同于自己编写,除了难度、错误和可维护性。

【讨论】:

根据我的研究,我认为这是最常见的答案,但我不知道,我仍然不相信 stdlib 中没有这样的功能。您必须承认,不使用外部库的脚本更有可能对新手用户正常工作。 @bukzor,好吧,相信事实吧。 =p 我根本不必承认这一点。 ;) 解析 HTML 是人们在几年前才真正广泛理解的东西。它花费了令人震惊的时间。所以可以相当肯定地说,标准库中什么都没有:BeautifulSoup、html5lib、lxml.html 构成了一个完整的列表。 @Ian Bicking:如果您愿意回答,我会检查一下。我是否仅仅因为我的答案是否定的而被降级?【参考方案6】:

如前所述,目前仅使用标准库没有令人满意的解决方案。当我尝试在过时的托管环境中运行我的程序之一而无法安装自己的扩展并且只能安装 python2.6 时,我遇到了与您相同的问题。解决方案:

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

from StringIO import StringIO
import ElementSoup

tree = ElementSoup.parse(StringIO(input_str))

lxml 本身和 html5lib 都需要您编译一些 C 代码以使其运行。让它们发挥作用需要付出更多的努力,如果您的环境受到限制,或者您的目标受众不愿意这样做,请避免使用它们。

【讨论】:

html5lib 没有它所依赖的扩展(例如,C 代码)。它可以可选地使用多个(例如datrie)来提高性能,但没有它也可以正常工作。

以上是关于如何使用标准库在 python 中解析格式错误的 HTML的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用标准库在 Go 中嵌套模板?

如何解析 ISO 8601 格式的日期?

如何在python中解析格式错误的HTML

如何使用 CSV 库在 python 中打开 CSV? [复制]

解析非标准 XML(CDATA 标记)

python常用标准库(压缩包模块zipfile和tarfile)