编写HTML解析器

时间:2011-08-25 14:26:50

标签: html parsing html-parsing

我目前正在尝试(或计划尝试)编写一个简单的(尽可能)程序来将html文档解析为树。

谷歌搜索后,我发现许多答案说“不要这样做已经完成”(或者说是这样的话);和HTML解析器示例的引用;还有一篇相当有说服力的文章,说明为什么不应该使用常规表达。但是我没有找到任何关于编写解析器的“正确”方法的指南。 (顺便说一句,这是我尝试更多的东西,而不是任何东西,所以我非常喜欢这样做,而不是使用预制的)

我相信我只需通过阅读文档并将标签/文本等添加到树中就可以创建一个有效的XML解析器,每当我点击一个关闭标签时都会升级一个级别(同样,简单,没有花哨的线程或效率要求在这个阶段。)。但是,对于HTML,并非所有标签都已关闭。

所以我的问题是:你会建议什么作为处理这个问题的方法?我唯一的想法是以与XML类似的方式处理它,但是有一个标签列表,这些标签不一定都是封闭的条件(例如< p>结束于< / p>或下一个) < p>标签)。

还有其他人(希望更好)的建议吗?是否有更好的方法完全实现这一目标?

6 个答案:

答案 0 :(得分:12)

通过根据需要找出丢失的打开和关闭标记,可以适应HTML的松散性。这基本上就像整理一样的验证器。

您将保留当前上下文的堆栈(可能隐含地使用树)。例如,{<html><body>}表示您当前位于html文档的正文中。遇到新节点时,将该节点的要求与堆栈中当前的要求进行比较。

假设您的筹码目前只是{html}。您遇到<p>标记。您在表格中查找<p>,该表格告诉您段落必须位于<body>内。由于您不在体内,因此隐式将<body>推入堆栈(或将树节点添加到树中)。然后,您可以将<p>放入树中。

现在假设您看到另一个<p>。您的规则告诉您不能在段落中嵌套段落,因此您知道在将新段落推入堆栈之前必须从堆栈中弹出当前<p>(就像您已经看到过关闭标记一样)。

在文档的末尾,您将每个剩余的元素从堆栈中弹出,就好像您已经看到每个元素的关闭标记一样。

诀窍是找到一种表示每个元素的上下文要求的好方法。

答案 1 :(得分:8)

所以,我会在这里尝试答案 -

基本上,与xml解析不同的是“普通”html解析(不是在谈论有效的xhtml)是大量的规则,如永无止境的<img>标签,或严格来说,即使是最笨拙的事实所有html标记都会在浏览器中呈现。 您将需要一个验证器和解析器来构建您的树。但是你必须决定你想要支持的HTML标准,这样当你遇到标记的弱点时,你就会知道这是一个错误而不仅仅是草率的HTML。

了解所有规则,构建验证器,然后您就可以构建解析器了。这是计划A.

计划B将允许您的解析器具有一定的错误阻力,这将导致验证步骤不必要。例如,解析所有标签,并将它们放在列表中,省略任何属性,以便您可以轻松地对列表进行操作,确定标签是打开还是从未打开过,最终获得“好” “布局树,这将是草率布局的近似解决方案,同时准确的布局正确。

希望有所帮助!

答案 2 :(得分:6)

由于现在存在html5标准,编写html解析器不再是反复试验或神秘知识。

相反,您只需实施标准化的parsing algorithm

答案 3 :(得分:4)

苛刻。去

HTML不是XML。 XHTML是XML。大多数网站都是HTML;一些是XHTML。在XHTML中,所有标签都必须关闭(或者没有主体,它仍然是关闭的)。

如果您想将HTML解析器编写为学习实验,那就去吧。如果你想编写下一个“Greaterest HTML parserer”,那就放弃吧。 Apache(或其他人)获胜;重要信息是:您不仅仅了解专门解析HTML的大型组。

回答“我该如何处理这个问题?” 阅读HTML上的W3C规范。它回答了你的问题。如果你的回答是“但我不想要”那么你实际上是在说“我是一个懒惰的傻瓜,想要假装学习”。如果是这种情况,我建议您删除帖子并继续; Microsoft IE团队可能会提供一些您感兴趣的文档。

不那么严厉的回答

HTML不容易解析。在最宽松的情况下,您不需要头部或身体元素,也不需要关闭大量标签。解析HTML时的基本规则是,如果遇到新的块元素,则自动关闭前一个块元素。您不能使用标准的XML解析器,因为HTML不是XML。

与XML类似,您需要将文档拆分为元素,包括自由文本元素。

XHTML更容易,因为它必须是格式良好的XML。您可以使用XML解析器。

答案 4 :(得分:1)

迟到将近十年,但随便。如果与您无关,那就是将来的访客。

另一种选择是 实施规范

WHATWG具有规范的specification for HTML。在此过程中,我们想到了所有古怪之处,而您不必忘记忘记了一些奇怪的HTML技巧(有很多)。

该规范还包含§ 13.2 Parsing HTML documents部分,其中概述了用户代理(您的解析器)应如何将html文档解析为DOM tree。已经考虑了所有边缘情况。最困难的部分是使用您选择的语言来使用正确的数据结构和程序流来实现它。

祝你好运,保持精神,读者!

答案 5 :(得分:0)

您是否尝试过使用此库:http://simplehtmldom.sourceforge.net/

F。