可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am using HTML Purifier (http://htmlpurifier.org/)
I just want to remove <script>
tags only.
I don\'t want to remove inline formatting or any other things.
How can I achieve this?
One more thing, it there any other way to remove script tags from HTML
回答1:
Because this question is tagged with regex I\'m going to answer with poor man\'s solution in this situation:
$html = preg_replace(\'#<script(.*?)>(.*?)</script>#is\', \'\', $html);
However, regular expressions are not for parsing HTML/XML, even if you write the perfect expression it will break eventually, it\'s not worth it, although, in some cases it\'s useful to quickly fix some markup, and as it is with quick fixes, forget about security. Use regex only on content/markup you trust.
Remember, anything that user inputs should be considered not safe.
Better solution here would be to use DOMDocument
which is designed for this.
Here is a snippet that demonstrate how easy, clean (compared to regex), (almost) reliable and (nearly) safe is to do the same:
<?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();
I have removed the HTML intentionally because even this can bork.
回答2:
Use the PHP DOMDocument
parser.
$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();
This worked me me using the following HTML document:
<!doctype html>
<html>
<head>
<meta charset=\"utf-8\">
<title>
hey
</title>
<script>
alert(\"hello\");
</script>
</head>
<body>
hey
</body>
</html>
Just bear in mind that the DOMDocument
parser requires PHP 5 or greater.
回答3:
$html = <<<HTML
...
HTML;
$dom = new DOMDocument();
$dom->loadHTML($html);
$tags_to_remove = array(\'script\',\'style\',\'iframe\',\'link\');
foreach($tags_to_remove as $tag){
$element = $dom->getElementsByTagName($tag);
foreach($element as $item){
$item->parentNode->removeChild($item);
}
}
$html = $dom->saveHTML();
回答4:
I had been struggling with this question. I discovered you only really need one function. explode(\'>\', $html); The single common denominator to any tag is < and >. Then after that it\'s usually quotation marks ( \" ). You can extract information so easily once you find the common denominator. This is what I came up with:
$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;
I see this really only working for script tags because you will never have nested script tags. Of course, you can easily add more code that does the same check and gather nested tags.
I call it accordion coding. implode();explode(); are the easiest ways to get your logic flowing if you have a common denominator.
回答5:
I would use BeautifulSoup if it\'s available. Makes this sort of thing very easy.
Don\'t try to do it with regexps. That way lies madness.
回答6:
Shorter:
$html = preg_replace(\"/<script.*?\\/script>/s\", \"\", $html);
When doing regex things might go wrong, so it\'s safer to do like this:
$html = preg_replace(\"/<script.*?\\/script>/s\", \"\", $html) ? : $html;
So that when the \"accident\" happen, we get the original $html instead of empty string.
回答7:
- this is a merge of both ClandestineCoder & Binh WPO.
the problem with the script tag arrows is that they can have more than one variant
ex. (< = <
= &lt;
) & ( > = >
= &gt;
)
so instead of creating a pattern array with like a bazillion variant,
imho a better solution would be
return preg_replace(\'/script.*?\\/script/ius\', \'\', $text)
? preg_replace(\'/script.*?\\/script/ius\', \'\', $text)
: $text;
this will remove anything that look like script.../script
regardless of the arrow code/variant and u can test it in here https://regex101.com/r/lK6vS8/1
回答8:
An example modifing ctf0\'s answer. This should only do the preg_replace once but also check for errors and block char code for forward slash.
$str = \'<script> var a - 1; </script>\';
$pattern = \'/(script.*?(?:\\/|/|/)script)/ius\';
$replace = preg_replace($pattern, \'\', $str);
return ($replace !== null)? $replace : $str;
If you are using php 7 you can use the null coalesce operator to simplify it even more.
$pattern = \'/(script.*?(?:\\/|/|/)script)/ius\';
return (preg_replace($pattern, \'\', $str) ?? $str);
回答9:
This is a simplified variant of Dejan Marjanovic\'s answer:
function removeTags($html, $tag) {
$dom = new DOMDocument();
$dom->loadHTML($html);
foreach (iterator_to_array($dom->getElementsByTagName($tag)) as $item) {
$item->parentNode->removeChild($item);
}
return $dom->saveHTML();
}
Can be used to remove any kind of tag, including <script>
:
$scriptlessHtml = removeTags($html, \'script\');
回答10:
use the str_replace function to replace them with empty space or something
$query = \'<script>console.log(\"I should be banned\")</script>\';
$badChar = array(\'<script>\',\'</script>\');
$query = str_replace($badChar, \'\', $query);
echo $query;
//this echoes console.log(\"I should be banned\")
?>
回答11:
A simple way by manipulating string.
$str = stripStr($str, \'<script\', \'</script>\');
function stripStr($str, $ini, $fin)
{
while(($pos = mb_stripos($str, $ini)) !== false)
{
$aux = mb_substr($str, $pos + mb_strlen($ini));
$str = mb_substr($str, 0, $pos).mb_substr($aux, mb_stripos($aux, $fin) + mb_strlen($fin));
}
return $str;
}