我正在尝试找到一种在 Python 中解析(可能格式错误)HTML 的方法,如果满足一组条件,则输出带有位置(行、列)的文档。位置信息是让我在这里绊倒的原因。需要明确的是,我不需要构建对象树。我只是想在原始文档中找到某些数据及其位置(想想拼写检查器,例如:'word "foo" at line x, column y, is拼写错误)'
作为一个例子,我想要这样的东西(使用 ElementTree 的Target API):
import xml.etree.ElementTree as ET
class EchoTarget:
def start(self, tag, attrib):
if somecondition():
print "start", tag, attrib, self.getpos()
def end(self, tag):
if somecondition():
print "end", tag, self.getpos()
def data(self, data):
if somecondition():
print "data", repr(data), self.getpos()
target = EchoTarget()
parser = ET.XMLParser(target=target)
parser.feed("<p>some text</p>")
parser.close()
但是,据我所知,该getpos()
方法(或类似方法)不存在。当然,那是使用 XML 解析器。我想解析可能格式错误的 HTML。
有趣的是,Python 标准库中的HTMLParser类确实提供了对获取位置信息(使用getpos()
方法)的支持,但它在处理格式错误的 HTML 时非常糟糕,并且已作为可能的解决方案被淘汰。我需要在不破坏解析器的情况下解析真实单词中存在的 HTML。
我知道有两个 HTML 解析器可以很好地解析格式错误的 HTML,即lxml和html5lib。事实上,我更愿意使用其中任何一个,而不是 Python 中可用的任何其他选项。
但是,据我所知,html5lib 不提供事件 API,并且需要将文档解析为树对象。然后我将不得不遍历树。当然,到那时,与源文档没有关联,所有位置信息都丢失了。所以,html5lib 出来了,这很可惜,因为它似乎是处理格式错误的 HTML 的最佳解析器。
lxml 库提供了一个 Target API,它主要反映 ElementTree 的,但同样,我不知道有任何方法可以访问每个事件的位置信息。看一眼源代码也没有提供任何提示。
lxml 还为 SAX 事件提供了一个 API。有趣的是,Python 的标准库提到 SAX 支持Locator Objects,但几乎没有提供有关如何使用它们的文档。这个SO Question提供了一些信息(使用 SAX 解析器时),但我看不出这与 lxml 提供的对 SAX 事件的有限支持有何关系。
最后,在有人建议Beautiful Soup之前,我要指出,正如主页上所述,“Beautiful Soup 位于流行的 Python 解析器(如 lxml 和 html5lib)之上”。它给我的只是一个从中提取数据的对象,与原始源文档没有任何联系。与 html5lib 一样,当我访问数据时,所有位置信息都会丢失。我想要/需要直接访问解析器。
为了扩展我在开头提到的拼写检查器示例,我只想检查文档文本中单词的拼写(而不是标签名称或属性),并且可能希望跳过检查特定标签的内容(如脚本或代码标签)。因此,我需要一个真正的 HTML 解析器。但是,在报告拼写错误时,我只对原始源文档中拼写错误的位置感兴趣,不需要构建树对象。需要明确的是,这只是一种潜在用途的示例。我可能会将它用于完全不同的东西,但需求基本相同。事实上,我曾经使用 HTMLParser 构建过非常相似的东西,但从未使用过它,因为错误处理不适用于该用例。那是几年前的事了 而且我似乎在某处丢失了该文件。这次我想改用 lxml 或 html5lib。
那么,有什么我想念的吗?我很难相信这些解析器(除了最没用的 HTMLParser 之外)没有任何方法可以访问位置信息。但如果他们这样做,它必须是无证的,这对我来说似乎很奇怪。