似乎stackoverflow上的每个问题,其中提问者使用正则表达式从HTML中获取一些信息将不可避免地有一个"答案",表示不使用正则表达式来解析HTML.
为什么不?我知道那里有引用 - 不引用"真正的"HTML解析器,比如Beautiful Soup,我相信它们是强大而有用的,但是如果你只是做一些简单,快速或肮脏的事情,那么为什么当一些正则表达式语句运行得很好时,麻烦使用如此复杂的东西?
此外,是否有一些基本的东西,我不了解正则表达式,这使得它们一般是解析的错误选择?
正则表达式无法进行整个HTML解析,因为它依赖于匹配开头和结束标记,这是正则表达式无法实现的.
正则表达式只能匹配常规语言,但HTML是无上下文的语言,而不是常规语言(正如@StefanPochmann所指出的,常规语言也是无上下文的,因此无上下文并不一定意味着不规则).你可以用HTML上的regexp做的唯一的事情就是启发式,但这并不适用于所有条件.应该可以呈现一个HTML文件,该文件将被任何正则表达式错误地匹配.
对于quick'n'dirty regexp会很好.但要知道的根本事情是,构建一个正确解析HTML 的正则表达式是不可能的.
原因是regexp无法处理任意嵌套表达式.请参阅可以使用正则表达式来匹配嵌套模式吗?
(来自http://htmlparsing.com/regexes)
假设您有一个HTML文件,您尝试从标记中提取URL.
所以你在Perl中写这样的正则表达式:
if ( $html =~ /在这种情况下,
$url
确实会包含https://img.devbox.cn/3cccf/16086/243/0882c115fe0762fb.png
.但是当你开始像这样开始获取HTML时会发生什么:要么
要么
要么
或者你开始得到误报
它看起来很简单,对于一个单一的,不变的文件来说可能很简单,但对于你将要对任意HTML数据做的任何事情,正则表达式只是未来心痛的一个秘诀.
这看起来是真正的答案 - 虽然它可能用正则表达式解析任意HTML,因为今天的正则表达式不仅仅是一个有限的自动机,为了解析任意的html而不仅仅是一个具体的页面,你必须重新实现regexp中的HTML解析器和正则表达式肯定会变得无法辨认1000次.
这个答案的推理是*方式*过时,今天比原来应用的更少(我认为它没有).(引用OP:"如果你只是做一些简单,快速或肮脏的事情......".)
4> Hank Gay..:两个快速的原因:
编写一个可以抵御恶意输入的正则表达式很难; 比使用预建工具更难
写一个可以使用你将不可避免地被困的荒谬标记的正则表达式很难; 比使用预建工具更难
关于正则表达式一般用于解析的适用性:它们不适合.您是否见过解析大多数语言所需的各种正则表达式?
基本上所有在运输产品或内部工具中完成的快速和脏的html解析最终都是一个巨大的安全漏洞,或者等待发生的错误.一定要津津乐道.如果可以使用正则表达式,可以使用正确的html解析器.
哇?2年后的一次downvote?如果有人想知道,我没有说"因为理论上不可能",因为这个问题清楚地问及"快速而肮脏",而不是"正确".OP显然已经阅读了覆盖理论上不可能的领域的答案,但仍然不满意.
5> Vatine..:就解析而言,正则表达式在"词法分析"(lexer)阶段非常有用,其中输入被分解为标记.它在实际的"构建解析树"阶段不太有用.
对于HTML解析器,我希望它只接受格式良好的HTML,并且需要正则表达式之外的功能(它们不能"计数"并确保给定数量的开放元素由相同的数字平衡关闭元素).
6> Tamas Czineg..:因为有很多方法可以"搞砸"浏览器会以相当自由的方式处理的HTML,但是需要花费很多精力来重现浏览器的自由行为来覆盖所有具有正则表达式的情况,所以你的正则表达式将不可避免地失败一些特殊的案例,这可能会在您的系统中引入严重的安全漏洞.
ntownsend:例如,你认为你已经从HTML中剥离了所有的脚本标签,但你的正则表达式失败涵盖了一个特殊情况(比方说,只适用于IE6):繁荣,你有一个XSS的虚拟性!
+1提及安全角度.当你与整个互联网连接时,你不能写出hacky"大部分时间都在工作"的代码.
7> okoman..:问题是,大多数提出与HTML和正则表达式有关的问题的用户都会这样做,因为他们无法找到有效的正则表达式.然后,我们必须考虑在使用DOM或SAX解析器或类似的东西时是否一切都会更容易.它们经过优化和构建,目的是使用类似XML的文档结构.
当然,有些问题可以通过正则表达式轻松解决.但重点在于轻松.
如果您只想查找看起来像
http://.../
regexp 一样好的所有网址.但是,如果要查找具有类"mylink"的a-Element中的所有URL,则最好使用适当的解析器.
8> Peter Bought..:正则表达式不是为处理嵌套标记结构而设计的,最好处理所有可能的边缘情况(最糟糕的是,不可能).
9> taggers..:我相信答案在于计算理论.对于使用正则表达式解析的语言,它必须按照定义"常规"(链接).HTML不是常规语言,因为它不符合常规语言的许多标准(与html代码中固有的许多嵌套级别有很大关系).如果您对计算理论感兴趣,我会推荐这本书.