У меня есть переменная с именем $articleText
и содержит html-код. Существуют коды script
и style
внутри элементов <script>
и <style>
html. Я хочу сканировать $articleText
и удалить эти фрагменты кода. Если я также смогу удалить фактические элементы html <script>
, </script>
, <style>
и </style>
, я тоже это сделаю.
Я предполагаю, что мне нужно использовать регулярное выражение, но я не в этом разбираюсь.
Может ли кто-нибудь помочь?
Хотелось бы, чтобы я мог предоставить некоторый код, но, как я уже сказал, у меня нет опыта в регулярном выражении, поэтому мне нечего показать.
Не используйте RegEx для HTML. PHP предоставляет инструмент для синтаксического анализа структур DOM, называемый соответствующим DomDocument.
<?php // some HTML for example $myHtml = '<html><head><script>alert("hi mom!");</script></head><body><style>body { color: red;} </style><h1>This is some content</h1><p>content is awesome</p></body><script src="someFile.js"></script></html>'; // create a new DomDocument object $doc = new DOMDocument(); // load the HTML into the DomDocument object (this would be your source HTML) $doc->loadHTML($myHtml); removeElementsByTagName('script', $doc); removeElementsByTagName('style', $doc); removeElementsByTagName('link', $doc); // output cleaned html echo $doc->saveHtml(); function removeElementsByTagName($tagName, $document) { $nodeList = $document->getElementsByTagName($tagName); for ($nodeIdx = $nodeList->length; --$nodeIdx >= 0; ) { $node = $nodeList->item($nodeIdx); $node->parentNode->removeChild($node); } }
Вы можете попробовать его здесь: https://eval.in/private/4f225fa0dcb4eb
Документация
DomDocument
– http://php.net/manual/en/class.domdocument.php DomNodeList
– http://php.net/manual/en/class.domnodelist.php DomDocument::getElementsByTagName
– http://us3.php.net/manual/en/domdocument.getelementsbytagname.php Даже регулярное выражение не является хорошим инструментом для такого рода задач, для небольшой простой задачи он может работать.
Если вы хотите удалить только внутренний текст тега (ов), используйте:
preg_replace('/(<(script|style)\b[^>]*>).*?(<\/\2>)/is', "$1$3", $txt);
Смотрите демо здесь .
Если вы хотите удалить также теги, строка замены в приведенном выше коде будет пуста, поэтому просто ""
.
Вот пример данных:
$in = ' <html> <head> <script type="text/javascript">window.location="somehwere";</script> <style> .someCSS {border:1px solid black;} </style> </head> <body> <p>....</p> <div> <script type="text/javascript">document.write("bad stuff");</script> </div> <ul> <li><style type="text/css">#moreCSS {font-weight:900;}</style></li> </ul> </body> </html>';
И теперь прописанная версия:
$dom = new DOMDocument('1.0','UTF-8'); $dom->loadHTML($in); removeByTag($dom,'style'); removeByTag($dom,'script'); var_dump($dom->saveHTML()); function removeByTag($dom,$tag) { $nodeList = $dom->getElementsByTagName($tag); removeAll($nodeList); } function removeAll($nodeList) { for ( $i = $nodeList->length; --$i >=0; ) { removeSelf($nodeList->item($i)); } } function removeSelf($node) { $node->parentNode->removeChild($node); }
И альтернативный (делает то же самое, просто никаких объявлений функций):
$dom = new DOMDocument('1.0','UTF-8'); $dom->loadHTML($in); for ( $list = $dom->getElementsByTagName('script'), $i = $list->length; --$i >=0; ) { $node = $list->item($i); $node->parentNode->removeChild($node); } for ( $list = $dom->getElementsByTagName('style'), $i = $list->length; --$i >=0; ) { $node = $list->item($i); $node->parentNode->removeChild($node); } var_dump($dom->saveHTML());
Хитрость заключается в повторении итерации при удалении узлов . И getElementsByTagName будет пересекать всю DOM для вас, поэтому вам не нужно (ни одно из этого hasChildNodes, nextSibling, nextChild stuff).
Возможно, лучшее решение находится где-то между этими двумя крайними примерами.
Не могу помочь себе, это, наверное, лучшая версия моих предложений. Он не включает в себя инкремент ( $i
) для гашения вещей и удаляет снизу вверх:
$dom = new DOMDocument('1.0','UTF-8'); $dom->loadHTML($in); removeElementsByTagName($dom,'script'); removeElementsByTagName($dom,'style'); function removeElementsByTagName($dom,$tagName) { $list = $dom->getElementsByTagName($tagName); while ( $node = $list->item(0) ) { $node->parentNode->removeChild($node); } } var_dump($dom->saveHTML());
Когда вы удаляете узлы, они перемещаются вверх в дочернем списке родителя, поэтому 1 становится 0 и 2 становится 1 и т. Д. Продолжайте делать это ( while
), пока их больше не будет ( ->item
возвращает null ). Также заверните это в функцию многократного использования.
Я думаю, что это должно делать то, что вам нужно (при условии, что нет вложенных тегов скрипта и стиля):
preg_replace('/(<script[^>]*>.+?<\/script>|<style[^>]*>.+?<\/style>)/s', '', $articleText);
Регулярное выражение для этого было бы невероятно тупым из-за возможности тегов в тегах и таких смешающих конструкций, как атрибуты тегов.
Я бы предложил сделать это в DOM (либо на PHP, либо на JavaScript), который может идентифицировать и удалять нежелательные теги посредством фактического разбора.
Предполагая, что это и проблема, не позволяющая вашему дизайну запутаться в случайных стилях, а также защитить ваш сайт от пользовательских сценариев, удаление этих тегов не только позволит вам оставаться в безопасности.
Рассмотрим случай атрибутов события (например: onmouseover, onclick):
<h1 onclick="console.log('user made this happen');">User Scripting Test</h1>
или еще хуже
<h1 onclick='function addCSSRule(a,b,c,d){"insertRule"in a?a.insertRule(b+"{"+c+"}",d):"addRule"in a&&a.addRule(b,c,d)}var style=document.createElement("style");style.appendChild(document.createTextNode("")),document.head.appendChild(style),sheet=style.sheet,addCSSRule(sheet,"*","color: #ff0!important");'>Messing with your styles!</h1>
При этом довольно тривиально начинать вставлять в документ всевозможные материалы.
Последний пример модов стилей, взятых у Дэвида Уолша – https://davidwalsh.name/add-rules-stylesheets
… заключается в использовании проверенной сторонней библиотеки, которая специализируется на этом. Я предлагаю очиститель HTML . Это избавит пользователя от стилей, скриптов и отвратительных атрибутов событий.