从HTML内容中删除脚本标记

我正在使用HTML净化器(http://htmlpurifier.org/)

我只想删除<script>标签。 我不想删除内联格式或任何其他的东西。

我怎样才能做到这一点?

还有一件事,它有任何其他的方式来从HTML中删除脚本标签

因为这个问题是用正则expression式标记的,所以我将在这种情况下回答穷人的解决scheme:

 $html = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $html); 

但是,正则expression式并不是用来parsingHTML / XML的,即使你编写了完美的expression式,它最终也会被打破,这是不值得的,但是在某些情况下,快速修复一些标记是有用的,忘记安全 。 仅在您信任的内容/标记上使用正则expression式。

记住,任何用户input都应该被认为是不安全的

这里更好的解决scheme是使用专门为此devise的DOMDocument 。 这里是一个片段,演示了如何简单,清洁(与正则expression式相比),(几乎)可靠和(几乎)安全的是做同样的事情:

 <?php $html = <<<HTML ... HTML; $dom = new DOMDocument(); $dom->loadHTML($html); $script = $dom->getElementsByTagName('script'); $remove = []; foreach($script as $item) { $remove[] = $item; } foreach ($remove as $item) { $item->parentNode->removeChild($item); } $html = $dom->saveHTML(); 

我有意删除了HTML,因为即使这可以bork

使用PHP DOMDocumentparsing器。

 $doc = new DOMDocument(); // load the HTML string we want to strip $doc->loadHTML($html); // get all the script tags $script_tags = $doc->getElementsByTagName('script'); $length = $script_tags->length; // for each tag, remove it from the DOM for ($i = 0; $i < $length; $i++) { $script_tags->item($i)->parentNode->removeChild($script_tags->item($i)); } // get the HTML string back $no_script_html_string = $doc->saveHTML(); 

这使我使用以下的HTML文件:

 <!doctype html> <html> <head> <meta charset="utf-8"> <title> hey </title> <script> alert("hello"); </script> </head> <body> hey </body> </html> 

请记住, DOMDocumentparsing器需要PHP 5或更高版本。

如果可用,我会使用BeautifulSoup。 使这种事情很容易。

不要试图用正则expression式来做。 那就是疯狂。

我一直在努力解决这个问题。 我发现你只需要一个function。 explode('>',$ html); 任何标签的唯一公分母是<和>。 然后通常是引号(“),一旦find共同点,就可以很容易地提取信息,这就是我想到的:

 $html = file_get_contents('http://some_page.html'); $h = explode('>', $html); foreach($h as $k => $v){ $v = trim($v);//clean it up a bit if(preg_match('/^(<script[.*]*)/ius', $v)){//my regex here might be questionable $counter = $k;//match opening tag and start counter for backtrace }elseif(preg_match('/([.*]*<\/script$)/ius', $v)){//but it gets the job done $script_length = $k - $counter; $counter = 0; for($i = $script_length; $i >= 0; $i--){ $h[$k-$i] = '';//backtrace and clear everything in between } } } for($i = 0; $i <= count($h); $i++){ if($h[$i] != ''){ $ht[$i] = $h[$i];//clean out the blanks so when we implode it works right. } } $html = implode('>', $ht);//all scripts stripped. echo $html; 

我看到这真的只适用于脚本标记,因为你永远不会有嵌套的脚本标记。 当然,您可以轻松地添加更多的代码来执行相同的检查并收集嵌套的标签。

我把它称为手风琴编码。 爆();爆炸(); 如果你有一个共同的分母,那么让你的逻辑stream动的最简单的方法是。

短:

$html = preg_replace("/<script.*?\/script>/s", "", $html);

做正则expression式的时候可能会出错,所以这样做更安全:

$html = preg_replace("/<script.*?\/script>/s", "", $html) ? : $html;

所以当“事故”发生的时候,我们得到原始的$ html而不是空string。

  • 这是一个合并的ClandestineCoderBinh WPO

脚本标签箭头的问题是它们可以有多个变体

恩。 (<= &lt; = &amp;lt; )&(> = &gt; = &amp;gt;

所以不是像创build一个bazillion变体一样创build一个模式数组,而是一个更好的解决scheme

 return preg_replace('/script.*?\/script/ius', '', $text) ? preg_replace('/script.*?\/script/ius', '', $text) : $text; 

这将删除任何看起来像script.../script无论箭头代码/变体,你可以在这里testing它https://regex101.com/r/lK6vS8/1

修改ctf0的答案的一个例子。 这应该只做preg_replace一次,但也检查错误和阻止正斜杠的字符代码。

 $str = '<script> var a - 1; <&#47;script>'; $pattern = '/(script.*?(?:\/|&#47;|&#x0002F;)script)/ius'; $replace = preg_replace($pattern, '', $str); return ($replace !== null)? $replace : $str; 

如果您使用的是PHP 7,则可以使用空的合并运算符来更简化它。

 $pattern = '/(script.*?(?:\/|&#47;|&#x0002F;)script)/ius'; return (preg_replace($pattern, '', $str) ?? $str);