【问题标题】:Catastophic backtracking issue with HTML [duplicate]HTML的灾难性回溯问题[重复]
【发布时间】:2015-11-03 19:39:19
【问题描述】:

我正在尝试使用 PHP 抓取一系列网页,抓取标签和最早标签之间的所有内容。这是我正在使用的正则表达式:

|(?<=div id="body">).*?</div>|s

对于我正在查看的大多数页面,这似乎工作得很好。但是,它并没有为其他一些人返回任何东西。我将正则表达式插入 regex101.com 测试器,它告诉我问题出在灾难性的回溯上。我尝试删除后视语言,甚至玩弄以下内容:

|id="body">.*?</div>|s

但是,问题仍然存在。我查看了有关灾难性回溯的其他一些问题,以及 http://www.regular-expressions.info/catastrophic.html 文章,但我不知道如何将它们的修复应用到这种特殊情况。

【问题讨论】:

  • 我不认为这会陷入灾难性的回溯。您能否将我们链接到您尝试过的 regex101 示例?
  • 为什么需要后视? div id="body"&gt;.*?&lt;/div&gt; 也可以。
  • 因为这是一个固定宽度的lookbehind并且结尾是一个文字,.*? 不应该导致回溯问题。

标签: php html regex


【解决方案1】:

众所周知,正则表达式会对大型 HTML 内容造成灾难性的回溯。在这种情况下,问题肯定出在后视和惰性点匹配上,当正则表达式引擎每次向右推进一个符号时,它必须检查该符号前面是否有指定的子字符串,以及它是否达到了足够的字符产生一个匹配。

查看 regex101 regex debugger 部分,了解此正则表达式的工作原理。

至于如何解析你的 HTML,PHP DOMDocument 和 DOMXPath 是你最好的朋友:

$html = "<<YOUR_HTML_STRING_HERE>>";
$dom = new DOMDocument('1.0', 'UTF-8');
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
// Above is the DOM initialization from string example, below is parsing
$xpath = new DOMXPath($dom);
$divs = $xpath->query('//div[@id="body"]'); // Get all DIV tags with id=body

foreach($divs as $div) { 
  echo $dom->saveHTML($div); // Echo the HTML, can be added to array
}

IDEONE demo

【讨论】:

  • 非常感谢!这正是我所需要的。
  • @stribizhev 你确定这是灾难性回溯,因为问题不在于嵌套量词会发生的指数回溯步骤吗? - 注意它会在没有后视的情况下引发相同的错误,我相信这是一个普通的旧 O(n) 超时。
  • @Mariano:我广泛使用灾难性回溯这个词。超时是由大量的回溯步骤引起的。
  • 我明白了。我也不知道有没有正式的定义。我明天去看看
  • 我不会说这是灾难性的回溯。对于一个普通的 HTML 文档,这至多是一个线性操作。但是,在一个长的 HTML 文档中,在.*? 上回溯以前进到下一个字符会耗尽回溯限制,从而导致匹配被中断。
猜你喜欢
  • 2016-12-26
  • 2017-02-24
  • 2016-03-24
  • 2017-08-22
  • 2020-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多