经过一些额外的研究并更仔细地检查了html5lib的源代码,我发现它html5lib.tokenizer.HTMLTokenizer
确实保留了部分位置信息。“部分”是指它知道给定令牌的最后一个字符的行和列。不幸的是,它没有保留令牌开始的位置(我想可以推断出它的位置,但这感觉就像是反向地重新实现了很多令牌生成器-不,使用前一个的结束位置不会如果标记之间有空白,则可以正常工作)。
无论如何,我都可以包装HTMLTokenizer
和创建一个HTMLParser
克隆,该克隆主要复制API。您可以在这里找到我的作品:https ://gist.github.com/waylan/7d5b7552078f1abc6fac。
但是,由于令牌生成器只是html5lib实现的解析过程的一部分,因此我们放弃了html5lib的大部分内容。例如,在该过程的那个阶段还没有进行规范化,因此您得到的是原始(可能无效)的令牌,而不是规范化的文档。如那里的评论所述,这不是完美的,我质疑它是否有用。
实际上,我还发现Python标准库中包含的HTMLParser已针对Python 3.3更新,并且不再因无效输入而崩溃。据我所知,(对于我的用例)更好的是,它确实提供了实际有用的位置信息(一如既往)。在所有其他方面,我的html5lib包装器并没有好坏(当然,它大概已经接受了更多的测试,因此更加稳定)。不幸的是,此更新尚未反向移植到Python 2或更早的Python 3版本。虽然,我认为自己做起来不会那么困难。
无论如何,我决定继续使用标准库中的HTMLParser,并拒绝自己的html5lib包装器。您可以在这里看到一个早期的工作,该工作似乎需要最少的测试才能很好地工作。
根据Beautiful Soup文档,HTMLParser已更新为支持Python 2.7.3和3.2.2中早于3.3的无效输入。