那么HTML解析器如何工作?它不使用正则表达式进行解析吗?
好吧,不。
如果您回到大脑中去学习一门计算课程,或者上过编译器课程,或者类似的课程,您可能会记得,存在着不同种类的语言和计算模型。我没有资格讨论所有细节,但我可以和您一起回顾一些要点。
语言和计算(出于这些目的)最简单的类型是常规语言。这些可以用正则表达式生成,并可以用有限自动机识别。基本上,这意味着这些语言中的“解析”字符串使用状态,而不使用辅助存储器。HTML当然不是常规语言。如果您考虑一下,标签列表可以任意嵌套。例如,表可以包含表,并且每个表可以包含很多嵌套标签。使用正则表达式,您可能可以挑选出一对标签,但是当然不能随意嵌套任何标签。
非常规的经典简单语言是正确匹配的括号。尝试一下,您将永远无法构建始终有效的正则表达式(或有限自动机)。您需要内存来跟踪嵌套深度。
具有堆栈用于存储的状态机是计算模型的下一个优势。这称为下推式自动机,它可以识别由上下文无关的语法生成的语言。在这里,我们可以识别正确匹配的括号-实际上,堆栈是它的理想存储模型。
好吧,这对HTML足够好了吗?可悲的是没有。实际上,对于超级Duper而言,也许经过仔细验证的XML始终可以完美地排列所有标签。在实际的HTML中,您可以轻松找到的片段<b><i>wow!</b></i>
。这显然不会嵌套,因此为了正确解析它,堆栈只是不够强大。
下一级别的计算是由通用语法生成的语言,并由图灵机识别。通常公认这是最有效的计算模型-状态机,带有辅助存储器,可以在任何地方修改其存储器。这就是编程语言可以做到的。这就是HTML所处的复杂程度。
用一句话总结一下这里的所有内容:要解析常规HTML,您需要一种真正的编程语言,而不是一个正则表达式。
HTML的解析方式与其他语言的解析方式相同:词法分析和语法分析。词法化步骤将单个字符流分解为有意义的标记。解析步骤使用状态和内存将令牌组合到可以执行的逻辑上一致的文档中。