我想从HTML页面中删除所有带有文字foo
或bar
的scipt标记。
所以我想出了这句话:
$content = preg_replace('#<script((?!foo|bar).)*?</script>#is', '', $content);
echo "Last error: " + preg_last_error();
这适用于较小的页面。但是现在我有一个包含30个大脚本标签的页面,它不起作用。 我得到的错误是:PREG_BACKTRACK_LIMIT_ERROR
因此,我认为我需要改进正则表达式以防止出现此错误,因为此语句有效:
$content = preg_replace('#<script.*?</script>#is', '', $content);
但是此语句将删除所有脚本标记,而我想保留其中的一部分。
有一些关于增加pcre.backtrack_limit
的解决方案,但是我不想走那条路。恕我直言,应该有一个更好的解决方案。
问题是我不知道如何解决此问题,因为就我所知,正则表达式存在问题。
您能否指导我使正则表达式更好,以免发生此错误?
答案 0 :(得分:0)
在此我强烈建议不使用正则表达式,而是改用DOM parsing,这在这种情况下通常更合适:
$doc = new \DOMDocument();
$doc->loadHTML($html, LIBXML_HTML_NODEFDTD);
$xpath = new \DOMXPath($doc);
foreach ($xpath->query('//script[contains(text(), \'foo\') or contains(text(), \'bar\')]') as $script_tag) {
$script_tag->parentNode->removeChild($script_tag);
}
echo $doc->saveHTML();
如果您有更多的单词,则可以改用数组构建xpath查询:
$blacklist = ['foo', 'bar', 'apple', 'cold'];
$query = '//script[' . join(' or ', array_map(function($banword) {
return "contains(text(), '$banword')";
}, $blacklist)) . ']';
foreach ($xpath->query($query) as $script_tag) {
$script_tag->parentNode->removeChild($script_tag);
}