我有一个名为$articleText
的变量,它包含html代码。 script
和style
html元素中有<script>
和<style>
个代码。我想扫描$articleText
并删除这些代码。如果我还可以删除实际的html元素<script>
,</script>
,<style>
和</style>
,我也会这样做。
我想我需要使用正则表达式,但我不熟练。
有人可以帮忙吗?
我希望我能提供一些代码,但就像我说我不熟练的正则表达式所以我没有任何东西可以显示。
答案 0 :(得分:22)
不要在HTML上使用RegEx。 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 答案 1 :(得分:19)
即使正则表达式也不是这类任务的好工具,对于它可能有用的小型简单任务。
如果您只想删除标签的内部文本,请使用:
preg_replace('/(<(script|style)\b[^>]*>).*?(<\/\2>)/is', "$1$3", $txt);
参见演示 here 。
如果你想删除也是标签,上面代码中的替换字符串将为空,所以只有""
。
答案 2 :(得分:2)
以下是示例数据:
$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());
诀窍是iterate backwards when deleting nodes。并且getElementsByTagName将为您遍历整个DOM,因此您不必(没有hasChildNodes,nextSibling,nextChild东西)。
也许最好的解决方案就在这两个极端例子之间。
无法帮助自己,这可能是我建议的最佳版本。它不包括一个增量器($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
)直到不再存在({{ 3}})。还将其包装在可重复使用的功能中。
答案 3 :(得分:2)
我认为这应该做你需要的(假设没有嵌套的脚本和样式标签):
preg_replace('/(<script[^>]*>.+?<\/script>|<style[^>]*>.+?<\/style>)/s', '', $articleText);
答案 4 :(得分:0)
执行此操作的正则表达式会非常钝,因为标记内部可能存在标记,以及标记属性等混杂构造。
我建议在DOM(使用PHP或JavaScript)中执行此操作,这可以通过实际解析来识别和删除不需要的标记。
答案 5 :(得分:0)
假设这不是让您的设计被随机样式弄乱以及保护您的网站免受用户脚本攻击的问题,那么删除这些标记并不能保证您的安全。
考虑event attributes的情况(例如: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>
有了这个,开始在文档中插入各种东西是相当简单的。
样式表mod的最后一个例子取自David Walsh - https://davidwalsh.name/add-rules-stylesheets
...是使用经过验证的专门从事此问题的第三方库。我建议HTML Purifier。它将消除用户对样式,脚本和讨厌的事件属性的输入。