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步骤将单个字符流分解为有意义的标记.解析步骤使用状态和内存将令牌组装成可以被操作的逻辑连贯文档.
解析HTML是将线性文本转换为树结构.正则表达式通常不能处理树结构.每个点所需的正则表达式可以随时更改下一个标记.您可以在解析器中使用正则表达式,但是对于每种可能的解析状态,您将需要一整套正则表达式.