удалить тег скрипта из содержимого HTML - PullRequest
52 голосов
/ 20 августа 2011

Я использую очиститель HTML (http://htmlpurifier.org/)

Я просто хочу удалить только <script> теги. Я не хочу удалять встроенное форматирование или любые другие вещи.

Как мне этого добиться?

Еще одна вещь, это любой другой способ удалить теги скрипта из HTML

Ответы [ 11 ]

119 голосов
/ 20 августа 2011

Поскольку этот вопрос помечен Я собираюсь ответить решением бедняка в этой ситуации:

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

Однако регулярные выражения не предназначены для парсинга HTML / XML, даже если вы напишите выражение perfect , оно в конце концов сломается, оно того не стоит, хотя в некоторых случаях полезно быстро исправить некоторую разметку и, как и в случае с быстрыми исправлениями, забудьте о security . Используйте regex только для контента / разметки, которым вы доверяете.

Помните, что все, что вводит пользователь, следует считать небезопасным .

Лучше решение здесь будет использовать DOMDocument, который предназначен для этого. Вот фрагмент кода, демонстрирующий, как легко, чисто (по сравнению с регулярными выражениями), (почти) надежно и (почти) безопасно делать то же самое:

<?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 .

36 голосов
/ 20 августа 2011

Используйте синтаксический анализатор PHP DOMDocument.

$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>

Просто имейте в виду,парсер DOMDocument требует PHP 5 или выше.

2 голосов
/ 24 января 2018
$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();
1 голос
/ 15 апреля 2013

Я боролся с этим вопросом.Я обнаружил, что вам действительно нужна только одна функция.взорваться ('>', $ html);Единственным общим знаменателем для любого тега является <и>.Затем после этого это обычно кавычки ("). Вы можете легко извлечь информацию, когда найдете общий знаменатель. Вот что я придумал:

$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;

Я вижу, что это действительно работает только для тегов скриптапотому что у вас никогда не будет вложенных тегов сценария. Конечно, вы можете легко добавить больше кода, который выполняет такую ​​же проверку и собирать вложенные теги.

Я называю это аккордеонным кодированием. implode (); explode ();Самый простой способ получить логику, если у вас есть общий знаменатель.

0 голосов
/ 31 октября 2018

Простой способ манипулирования строкой.

$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;
}
0 голосов
/ 29 июня 2018

используйте функцию str_replace, чтобы заменить их пустым пространством или чем-то

$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")

?>

0 голосов
/ 21 января 2018

Это упрощенный вариант ответа Деяна Марьяновича:

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();
}

Может использоваться для удаления любых тегов, в том числе <script>:

$scriptlessHtml = removeTags($html, 'script');
0 голосов
/ 22 марта 2017

Пример изменения ответа 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, вы можете использовать оператор null coalesce, чтобы еще больше упростить его.

$pattern = '/(script.*?(?:\/|&#47;|&#x0002F;)script)/ius'; 
return (preg_replace($pattern, '', $str) ?? $str); 
0 голосов
/ 01 августа 2016
  • это объединение ClandestineCoder & Binh WPO .

проблема со стрелками тега сценария заключается в том, что они могут иметьболее одного варианта

отл.(<= <code>&lt; = &amp;lt;) & (> = &gt; = &amp;gt;)

, поэтому вместо создания массива шаблонов с вариантом, подобным bazillion, имхо, лучшее решение будетbe

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

это удалит все, что похоже на script.../script независимо от кода / варианта стрелки, и вы можете проверить это здесь https://regex101.com/r/lK6vS8/1

0 голосов
/ 25 марта 2015

Короче:

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

При выполнении регулярных выражений все может пойти не так, поэтому безопаснее сделать так:

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

Так что, когда произойдет «несчастный случай», мы получим оригинальный $ html вместо пустой строки.

...