编写HTML解析器

Jam*_*mes 26 html parsing html-parsing

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

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

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

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

有没有其他任何(希望更好)的建议?是否有更好的方法完成这项工作?

Adr*_*thy 13

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

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

假设你的堆栈目前只是{ html}.你遇到一个<p>标签.你<p>在一张表中查找,告诉你一个段落必须在里面<body>.因为你不在体内,所以你会隐式地推入<body>你的堆栈(或者在树上添加一个体节点).然后你可以把它<p>放进树里.

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

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

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


And*_*tin 9

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

基本上,什么使得"简单"的html解析(不是在这里讨论有效的xhtml)与xml解析不同的是大量的规则,比如永无止境的<img>标签,或者严格来说,甚至最糟糕的所有html标记都会在某种程度上呈现一个浏览器.您将需要一个验证器和解析器来构建您的树.但是你必须决定你想要支持的HTML标准,这样当你遇到标记的弱点时,你会知道这是一个错误而不仅仅是草率的HTML.

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

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

希望有所帮助!


Ben*_*ela 8

从现在开始存在html5标准,编写html解析器不再是试错法或神秘知识.

相反,你只需要实现标准化的 解析算法.


DwB*_*DwB 5

苛刻。走

HTML不是XML。XHTML是XML。大多数网站都是HTML;有些是XHTML。在XHTML中,所有标记都必须关闭(或没有主体,该主体仍处于关闭状态)。

如果您想编写一个HTML解析器作为学习实验,那就去吧。如果要编写下一个“最伟大的HTML解析器”,请放弃它。Apache(或其他人)获胜;重要的信息是:您对专门分析HTML的大型团体了解不多。

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

不太苛刻的答案

HTML不容易解析。最简单的说,您不需要头或身体元素,也不需要关闭许多标签。解析HTML的基本规则是,如果遇到新的block元素,则自动关闭上一个block元素。您不能为此使用标准的XML解析器,因为HTML不是XML。

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

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

  • 老兄,那太残酷了。 (2认同)