Я использую HTML очиститель (http://htmlpurifier.org/)
Я просто хочу удалить теги <script>
. Я не хочу удалять встроенное форматирование или любые другие вещи.
Как я могу это достичь?
Еще одна вещь: есть ли другой способ удалить теги скриптов из HTML
Поскольку этот вопрос помечен регулярным выражением, я собираюсь ответить с решением бедного человека в этой ситуации:
$html = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $html);
Однако регулярные выражения не предназначены для синтаксического разбора HTML / XML, даже если вы пишете идеальное выражение, оно в конечном итоге сломается, это не стоит того, хотя в некоторых случаях полезно быстро исправить некоторую разметку и, как и при быстрых исправлениях, забыть о безопасности . Используйте регулярное выражение только по содержимому / разметке, которому вы доверяете.
Помните, что все, что пользовательские входы должны считаться небезопасными .
DOMDocument
решением здесь будет использование 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 .
Используйте парсер 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 или выше.
Я бы использовал BeautifulSoup, если он доступен. Делает это очень легко.
Не пытайтесь делать это с помощью регулярных выражений. Таким образом, безумие.
Я боролся с этим вопросом. Я обнаружил, что вам действительно нужна только одна функция. explode ('>', $ 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;
Я вижу, что это действительно работает только для скриптовых тегов, потому что у вас никогда не будет вложенных тегов скрипта. Конечно, вы можете легко добавить еще один код, который выполняет ту же проверку и собирает вложенные теги.
Я называю это аккордеонным кодированием. лопаются (); взорваться (); это самые простые способы, чтобы ваша логика протекала, если у вас есть общий знаменатель.
Короче:
$html = preg_replace("/<script.*?\/script>/s", "", $html);
При выполнении регулярных выражений все может пойти не так, так что безопаснее делать вот так:
$html = preg_replace("/<script.*?\/script>/s", "", $html) ? : $html;
Так что, когда происходит «авария», мы получаем исходный $ html вместо пустой строки.
проблема с стрелками тега сценария заключается в том, что они могут иметь более одного варианта
ех. (
<
=&lt;
) & (>
=&gt;
>
=&gt;
)&gt;
поэтому вместо создания массива шаблонов, как вариант bazillion, imho лучшим решением будет
return preg_replace('/script.*?\/script/ius', '', $text) ? preg_replace('/script.*?\/script/ius', '', $text) : $text;
это удалит все, что похоже на script.../script
независимо от кода / варианта стрелки, и вы можете проверить его здесь. https://regex101.com/r/lK6vS8/1
Пример модификации ответа ctf0. Это нужно сделать только для preg_replace один раз, а также проверить наличие ошибок и заблокировать код для косой черты.
$str = '<script> var a - 1; </script>'; $pattern = '/(script.*?(?:\/|/|/)script)/ius'; $replace = preg_replace($pattern, '', $str); return ($replace !== null)? $replace : $str;
Если вы используете php 7, вы можете использовать оператор null coalesce, чтобы упростить его еще больше.
$pattern = '/(script.*?(?:\/|/|/)script)/ius'; return (preg_replace($pattern, '', $str) ?? $str);