使用正则表达式删除 JavaScript
Posted
技术标签:
【中文标题】使用正则表达式删除 JavaScript【英文标题】:Remove JavaScript with Regex 【发布时间】:2011-12-23 21:23:51 【问题描述】:我无法使用 C# 从 html 页面中删除所有 javascript。我有三个正则表达式删除了很多但也错过了很多。使用 MSHTML DOM 解析器解析 javascript 会导致 javascript 实际运行,这是我试图通过使用正则表达式来避免的。
"<script.*/>"
"<script[^>]*>.*</script>"
"<script.*?>[\\s\\S]*?</.*?script>"
有谁知道我缺少什么导致这三个正则表达式缺少 JavaScript 块?
我要删除的示例:
<script src="do_files/page.js" type="text/javascript"></script>
<script src="do_files/page.js" type="text/javascript" />
<script type="text/javascript">
<!--
var Time=new Application('Time')
//-->
</script>
<script type="text/javascript">
if(window['com.actions'])
window['com.actions'].approvalStatement = "",
window['com.actions'].hasApprovalStatement = false
</script>
【问题讨论】:
你能举一个错过区块的例子吗? 使用 HTML 解析器(如 Nokogiri)并修改 DOM; do not use a regex 在原始 HTML 上。您是尝试在 Web 浏览器客户端还是在服务器上执行此操作?如果是服务器,什么编程语言? 如果有的话,看起来你的正则表达式会比你想要的匹配更多。你的 #2 正在做一个贪婪的.*
,所以它会匹配从页面上的第一个 <script>
到最后一个 </script>
的所有内容,可能包括你没有的内容 between 脚本标签意思是删除。
语言是 C#。使用 mshtml 解析器实际上运行 java 脚本,这是我试图通过首先删除它来避免的。
Regex 对 PARSING HTML 不是特别好——但那是因为 HTML 允许嵌套构造(如 <span><b><i><u>hello <span class="mundo">world</span></u></i></b></span>
)脚本标签基本上没有嵌套,所以它远不及相关的(注释或 CDATA 标记经常在脚本标记中使用,但这些都不是一个不容忽视的挑战)。 REMOVING 或 STRIPPING HTML 稍有不同,因为表达式的复杂性可以大大降低。
【参考方案1】:
我假设您正在尝试简单地清理 JavaScript 的输入。坦率地说,我担心这是一个过于简单的解决方案,因为它看起来非常简单。在表达式之后(在 C# 字符串中),请参见下面的推理:
@"(?s)<script.*?(/>|</script>)"
就是这样 - 我希望! (它当然适用于您的示例!)
我之所以简单的原因是,尝试使用正则表达式解析 HTML 的主要问题是嵌套标签的可能性——与其说是不同标签的嵌套,不如说是同义标签的嵌套
例如,
<b> bold <i> AND italic </i></b>
...还不错,但是
<span class='BoldText'> bold <span class='ItalicText'> AND italic </span></span>
会更难解析,因为结束标签是相同的。
但是,由于嵌套script
标签是无效的,/>
(</script>的下一个实例是这个脚本块的结尾。
脚本标签中总是有可能包含 HTML cmets 或 CDATA 标签,但如果它们不包含 </script>
应该没问题。但是:如果他们这样做,肯定有可能通过一些“代码”。我不认为页面会呈现,但是一些 HTML 解析器非常灵活,所以你永远不会知道。要处理一些额外的可能空格,您可以使用:
@"(?s)<\s?script.*?(/\s?>|<\s?/\s?script\s?>)"
请告诉我你是否能想出一种方法来打破它,让 VALID HTML 代码使用可运行的 JavaScript(我知道有几种方法可以得到 一些 东西通过,但如果它通过了,它应该以许多不同的方式之一被破坏,并且不应该是可运行的 JavaScript 代码。)
【讨论】:
当然,这应该处理所有有效脚本块的完全删除,并且有效的 HTML 输入应该是有效的 HTML 输出(减去脚本块) 太棒了!非常感谢。【参考方案2】:人们普遍认为,尝试使用正则表达式解析 HTML 是一个坏主意,并且会产生不好的结果。相反,您应该使用 DOM 解析器。 jQuery 很好地包裹了浏览器的 DOM,并允许您非常轻松地删除所有 <script>
标记。
【讨论】:
嘿。我喜欢使用 jQuery 删除 JavaScript 的讽刺意味。 HTML Agility Pack 似乎是标准的 C# 解决方案。【参考方案3】:好的,当我需要从任何可能的 javascript-ing 中清除“富文本”(具有 HTML 格式的文本)时,我也遇到过类似的情况。
有几种方法可以将 javascript 添加到 HTML:
通过使用
通过在 HTML 元素上使用事件,例如“onload”或“onmouseover” 例如:
通过创建调用 javascript 代码的超链接 例如:...
暂时能想到的就这些了。
所以提交的 HTML 代码需要从这 3 种情况中清除。一个简单的解决方案是使用 Regex 查找这些模式,并将它们替换为 "" 或做任何你想做的事情。
这是一个简单的代码:
public static string CleanHTMLFromScript(string str)
Regex re = new Regex("<script[^>]*>", RegexOptions.IgnoreCase);
str = re.Replace(str, "");
re = new Regex("<[a-z][^>]*on[a-z]+=\"?[^\"]*\"?[^>]*>", RegexOptions.IgnoreCase);
str = re.Replace(str, "");
re = new Regex("<a\\s+href\\s*=\\s*\"?\\s*javascript:[^\"]*\"[^>]*>", RegexOptions.IgnoreCase);
str = re.Replace(str, "");
return(str);
此代码负责处理可能添加或不添加的任何空格和引号。它似乎工作正常,并不完美,但它确实有效。欢迎任何改进。
【讨论】:
【参考方案4】:如果这样做是为了防止跨站点脚本,那么创建自己的 HTML 解析器或脚本检测器是一个特别糟糕的主意。手动执行此操作是一个非常糟糕的主意,因为有许多极端情况和技巧可用于击败此类尝试。这被称为“黑名单”,因为它试图从 HTML 中删除不安全的项目,而且几乎注定要失败。
使用白名单处理器(例如AntiSamy)要安全得多,它只会通过自动转义其他所有内容来允许已批准的项目通过。
当然,如果这不是您正在做的事情,那么您可能应该编辑您的问题以提供更多背景信息...
编辑:
既然我们知道您正在使用 C#,请按照建议的 here 尝试 HTMLAgilityPack。
【讨论】:
我过去曾遇到过敏捷包中的错误,因此我倾向于远离它……但感谢您的建议。【参考方案5】:您使用哪种语言?一般来说,正则表达式不适合解析 HTML。
如果您在 .net 平台上,HTML Agility Pack 提供了更好的解析器。
【讨论】:
【参考方案6】:您应该使用真正的 html 解析器来完成这项工作。话虽这么说,对于简单的剥离 脚本块,您可以使用如下的基本正则表达式。
这个想法是您需要一个回调来确定捕获组 1 是否匹配。 如果是这样,回调应该将隐藏 html 的东西(如 cmets)传回 通过不变,脚本块作为空字符串传回。
不过,这不会替代 html 处理器。祝你好运!
搜索正则表达式:(修饰符 - 扩展的、全局的、在点中包含换行符、回调函数)
(?:
<script (?:\s+(?:".*?"|\'.*?\'|[^>]*?)+)? \s*> .*? </script\s*>
| </?script (?:\s+(?:".*?"|\'.*?\'|[^>]*?)+)? \s*/?>
)
|
( # Capture group 1
<!(?:DOCTYPE.*?|--.*?--)> # things that hide html, add more constructs here ...
)
替换func伪代码:
string callback ()
if capture buffer 1 matched
return capt buffer 1
else return ''
【讨论】:
以上是关于使用正则表达式删除 JavaScript的主要内容,如果未能解决你的问题,请参考以下文章