【问题标题】:Escape catastrophic backtracking in HTML markup逃避 HTML 标记中的灾难性回溯
【发布时间】:2017-08-22 06:26:50
【问题描述】:

正如我在标题中所说,我的数据集是标记,看起来有点像这样

<!DOCTYPE html>
<html>
<head>
    <title>page</title>
</head>
<body>
<main>

<div class="menu">
    <img src=mmayboy.jpg>
    <p> stackoverflow is good </p>
</div>

<div class="combine">
    <p> i have suffered <span>7</span></p>
</div>
</main>
</body>
</html> 

我的正则表达式引擎尝试分别匹配以下每个节点块,即我可以尝试匹配combinemenu。一口气,这就是我的正则表达式引擎的样子,尽管我在它下面深入研究了它的内部。

/(<div class="menu">(\s+.*)+<\/div>(?:(?=(\s+<div))))/

它会尝试深入该标记并获取所需的节点块。就这些。至于内部,我们开始吧

/
(
 <div class="menu"> // match text that begins with these literals
  (
   \s+.*
  )+ /* match any white space or character after previous. But the problem is that this matches up till the closing tag of other DIVs i.e greedy. */
  <\/div> // stop at the next closing DIV (this catches the last DIV)
  (?: // begin non-capturing group 
   (?=
    (
     \s+<div
     ) /* I'm using the positive lookahead to make sure previous match is not followed by a space and a new DIV tag. This is where the catastrophic backtracking is raised. */
   )
  )
 )
/

我用 cmets 缩进了它,以帮助任何愿意提供帮助的人。我还从博客中寻找解决方案,the manual他们说这是由具有太多可能性的表达式引起的,可以通过减少结果的机会来补救,即+?而不是*但是尽我所能,我无法将其中任何一个应用到我目前的困境中。

【问题讨论】:

标签: javascript regex parsing html-parsing


【解决方案1】:
(\s+.*)+

大概可以简化为

[^]*?

这应该可以防止灾难性的回溯。整体简化:

/<div class="menu">[^]*?<\/div>/

您是否考虑过改用an HTML parser

var parser = new DOMParser();
var doc = parser.parseFromString(data, 'text/html');
var menu = doc.getElementsByClassName('menu')[0];

console.log(menu.innerHTML);

【讨论】:

  • 是的,使用 HTML 解析器。
  • “简化”正则表达式无法工作,因为在字母数字和符号之前有大量空格字符。其次,DOMParser 仍处于试验阶段,因此在 nodejs 上尚不可用(恰好是我需要它的地方)
  • @Mmayboy:啊,抱歉,正则表达式已更新。但是使用an HTML parser for Node,然后。 (这不是它在 Node 上不可用的原因。)
  • 您应该从 [^]* 再次更新它吗?到 [^.]*? :p 当我只想要这个微小的 Dom 元素时,我还需要一个节点解析器模块吗?更好的是,您介意解释一下这是如何工作的吗?
  • @Mmayboy:呃,哪一部分需要再更新一下?是的,如果你想要可靠的 HTML 解析,你应该使用 HTML 解析器。例如,如果另一个 &lt;div&gt; 最终出现在 &lt;div class="menu"&gt; 中,您会发现无法使用正则表达式来提取单个元素。
猜你喜欢
  • 1970-01-01
  • 2016-12-26
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-24
  • 1970-01-01
相关资源
最近更新 更多