如果HTML解析不使用正则表达式,它们如何工作?

And*_*y E 96 html regex parsing html-parsing

我每天都会看到问题,询问如何从某些HTML字符串中解析或提取某些内容,第一个答案/注释始终是"不要使用RegEx解析HTML,以免感到愤怒!" (有时省略最后一部分).

这对我来说相当混乱,我一直认为,解析任何复杂字符串的最佳方法是使用正则表达式.那么HTML解析器如何工作呢?它不使用正则表达式来解析.

使用正则表达式的一个特殊参数是,并不总是有一种解析替代方法(例如JavaScript,其中DOMDocument不是普遍可用的选项).例如,jQuery似乎可以使用正则表达式将HTML字符串转换为DOM节点.

不知道是否CW这个,这是一个真正的问题,我想要回答,而不是真正想成为一个讨论主题.

JXG*_*JXG 132

那么HTML解析器如何工作呢?它不使用正则表达式来解析吗?

好吧,不.

如果你回到脑中学习计算理论课程,如果你选择了一门课程,或者编写了一个编程课程,或者类似的东西,你可能会记得有不同种类的语言和计算模型.我没有资格详细介绍所有细节,但我可以和你一起回顾几个要点.

最简单的语言和计算类型(用于这些目的)是一种常规语言.这些可以使用正则表达式生成,并使用有限自动机进行识别.基本上,这意味着这些语言中的"解析"字符串使用状态,而不是辅助存储器.HTML当然不是常用语言.如果你考虑一下,标签列表可以任意嵌套.例如,表可以包含表,每个表可以包含许多嵌套标记.使用正则表达式,您可以选择一对标签,但肯定不能任意嵌套.

非常规的经典简单语言是正确匹配的括号.尽量尝试,你将永远无法构建一个永远有效的正则表达式(或有限自动机).你需要记忆来跟踪嵌套深度.

具有用于存储器的堆栈的状态机是计算模型的下一个优势.这称为下推自动机,它识别由无上下文语法生成的语言.在这里,我们可以识别正确匹配的括号 - 实际上,堆栈是它的完美内存模型.

嗯,这对HTML来说还算不错吗?可悲的是没有.也许对于超级经验丰富的经过验证的XML,实际上,所有标签总是完美排列.在真实世界的HTML中,您可以轻松找到类似的代码段<b><i>wow!</b></i>.这显然不会嵌套,所以为了正确解析它,堆栈不够强大.

下一级计算是由一般语法生成的语言,并由图灵机器识别.这通常被认为是有效的最强计算模型 - 具有辅助存储器的状态机,其存储器可以在任何地方进行修改.这就是编程语言可以做的事情.这是HTML所处的复杂程度.

用一句话概括这里的所有内容:要解析一般HTML,你需要一种真正的编程语言,而不是正则表达式.

HTML的解析方式与解析其他语言的方式相同:lexing和parsing.lexing步骤将单个字符流分解为有意义的标记.解析步骤使用状态和内存将令牌组装成可以被操作的逻辑连贯文档.

  • +1很好的解释,你肯定解释得很好.:) (2认同)

Que*_*tin 64

通常使用tokeniser.HTML5规范草案具有处理"真实世界HTML" 的广泛算法.

  • HTML解析器的主要问题是,在遇到错误时,您不能吐出"解析错误"并将其留在那里.你进入怪癖模式并尝试从你遇到的混乱中找到最好的东西,包括不匹配的标签,[{]}样式交错和各种怪异,试图让结果看起来尽可能好,不可避免失败最痛苦......这不是你可以用正则表达式做的事情. (8认同)
  • @Timothy K:'注意:由于这种算法导致元素改变父母的方式,它被称为"采用代理算法"(与其他可能的处理错误内容的算法相比,其中包括"乱伦算法", "秘密事务算法"和"海森堡算法"). (7认同)

T.J*_*der 22

正则表达式只是解析器的一种形式.使用递归下降,预测和其他几种技术来正确解释文本时,诚实的HTML解析器将比使用正则表达式表达的复杂得多.如果你真的想进入它,你可以查看lex&yacc和类似的工具.

禁止使用正则表达式进行HTML解析应该更准确地写成:"不要使用朴素的正则表达式来解析HTML ......" (以免你感到愤怒) "......并谨慎对待结果." 对于某些特定目标,正则表达式可能完全足够,但您需要非常小心地了解正则表达式的局限性,并且要谨慎对待正在解析的文本的来源(例如,如果它是用户输入,确实非常小心).


Sva*_*nte 6

解析HTML是将线性文本转换为树结构.正则表达式通常不能处理树结构.每个点所需的正则表达式可以随时更改下一个标记.您可以在解析器中使用正则表达式,但是对于每种可能的解析状态,您将需要一整套正则表达式.