.NET 从 HTML 页面中删除/剥离 JavaScript 和 CSS 代码块

Posted

技术标签:

【中文标题】.NET 从 HTML 页面中删除/剥离 JavaScript 和 CSS 代码块【英文标题】:.NET Remove/Strip JavaScript and CSS code blocks from HTML page 【发布时间】:2011-09-17 00:25:36 【问题描述】:

我有带有 javascript 和 CSS 代码块的 html 字符串:

<script type="text/javascript">

  alert('hello world');

</script>

<style type="text/css">
  A:link text-decoration: none
  A:visited text-decoration: none
  A:active text-decoration: none
  A:hover text-decoration: underline; color: red;
</style>

如何剥离这些块? 关于可用于删除这些的正则表达式的任何建议?

【问题讨论】:

【参考方案1】:

只需寻找一个开始的&lt;script 标记,然后删除它和结束/script&gt; 标记之间的所有内容。

风格也是如此。 See Google 获取字符串操作技巧。

【讨论】:

如果您的代码中有 document.write("") 则不起作用 在安全意义上这样做就足够了吗? (阻止 javascript 执行)?【参考方案2】:

快速的“n”脏方法是这样的正则表达式:

var regex = new Regex(
   "(\\<script(.+?)\\</script\\>)|(\\<style(.+?)\\</style\\>)", 
   RegexOptions.Singleline | RegexOptions.IgnoreCase
);

string ouput = regex.Replace(input, "");

更好的*(但可能更慢)选项是使用HtmlAgilityPack:

HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(htmlInput);

var nodes = doc.DocumentNode.SelectNodes("//script|//style");

foreach (var node in nodes)
    node.ParentNode.RemoveChild(node);

string htmlOutput = doc.DocumentNode.OuterHtml;

*) 有关为什么它更好的讨论,请参阅this thread。

【讨论】:

你知道Tony The Pony吗? @GvS:我知道使用正则表达式处理 HTML 时可能出现的问题。因此,对于大多数情况,我强烈推荐使用 HtmlAgilityPack 之类的 html 解析器,但这取决于具体情况。如果是一次性批量删除脚本和样式块,并且我知道输入是有效的 html,那么我上面的正则表达式就足够了,特别是因为 &lt;script&gt; 标签和 &lt;style&gt; 标签不能有嵌套标签. @GvS:我添加了一个使用 HtmlAgilityPack 的示例。 也要小心内联脚本?例如。 ?需要有一个更复杂的工具来摆脱它。【参考方案3】:

使用 HTMLAgilityPack 获得更好的结果

或者试试这个功能

public string RemoveScriptAndStyle(string HTML)

    string Pat = "<(script|style)\\b[^>]*?>.*?</\\1>";
    return Regex.Replace(HTML, Pat, "", RegexOptions.IgnoreCase | RegexOptions.Singleline);

【讨论】:

【参考方案4】:

我制造了我的自行车)他可能不如 HtmlAgilityPack 正确,但它在 400 kb 的页面上快了大约 5-6 倍。还要使符号小写并删除数字(为标记器制作)

 private static readonly List<byte[]> SPECIAL_TAGS = new List<byte[]>
                                                            
                                                                Encoding.ASCII.GetBytes("script"),
                                                                Encoding.ASCII.GetBytes("style"),
                                                                Encoding.ASCII.GetBytes("noscript")
                                                            ;

    private static readonly List<byte[]> SPECIAL_TAGS_CLOSE = new List<byte[]>
                                                                  
                                                                      Encoding.ASCII.GetBytes("/script"),
                                                                      Encoding.ASCII.GetBytes("/style"),
                                                                      Encoding.ASCII.GetBytes("/noscript");

public static string StripTagsCharArray(string source, bool toLowerCase)
    
        var array = new char[source.Length];
        var arrayIndex = 0;
        var inside = false;
        var haveSpecialTags = false;
        var compareIndex = -1;
        var singleQouteMode = false;
        var doubleQouteMode = false;
        var matchMemory = SetDefaultMemory(SPECIAL_TAGS);
        for (int i = 0; i < source.Length; i++)
        
            var let = source[i];
            if (inside && !singleQouteMode && !doubleQouteMode)
            
                compareIndex++;
                if (haveSpecialTags)
                
                    var endTag = CheckSpecialTags(let, compareIndex, SPECIAL_TAGS_CLOSE, ref matchMemory);
                    if (endTag) haveSpecialTags = false;
                
                if (!haveSpecialTags)
                
                    haveSpecialTags = CheckSpecialTags(let, compareIndex, SPECIAL_TAGS, ref matchMemory);
                
            
            if (haveSpecialTags && let == '"')
            
                doubleQouteMode = !doubleQouteMode;
            
            if (haveSpecialTags && let == '\'')
            
                singleQouteMode = !singleQouteMode;
            
            if (let == '<')
            
                matchMemory = SetDefaultMemory(SPECIAL_TAGS);
                compareIndex = -1;
                inside = true;
                continue;
            
            if (let == '>')
            
                inside = false;
                continue;
            
            if (inside) continue;
            if (char.IsDigit(let)) continue; 
            if (haveSpecialTags) continue;
            array[arrayIndex] = toLowerCase ? Char.ToLowerInvariant(let) : let;
            arrayIndex++;
        
        return new string(array, 0, arrayIndex);
    

    private static bool[] SetDefaultMemory(List<byte[]> specialTags)
    
        var memory = new bool[specialTags.Count];
        for (int i = 0; i < memory.Length; i++)
        
            memory[i] = true;
        
        return memory;
    

【讨论】:

【参考方案5】:

与 Elian Ebbing 的回答和 Rajeev 的回答类似,我选择了使用 HTML 库而不是正则表达式的更稳定的解决方案。但我没有使用 HtmlAgilityPack,而是在 .NET Core 3 中使用了AngleSharp,它给了我类似 jquery 的选择器:

//using AngleSharp;
var context = BrowsingContext.New(Configuration.Default);
var document = await context.OpenAsync(req => req.Content(sourceHtml)); // generate HTML DOM from source html string
var elems = document.QuerySelectorAll("script, style"); // get script and style elements
foreach(var elem in elems)

    var parent = elem.Parent;
    parent.RemoveChild(elem); // remove element from DOM

var resultHtml = document.DocumentElement.OuterHtml; // HTML result as a string

【讨论】:

以上是关于.NET 从 HTML 页面中删除/剥离 JavaScript 和 CSS 代码块的主要内容,如果未能解决你的问题,请参考以下文章

.NET 库,用于处理 HTML 电子邮件和剥离以前的响应

php 从提供的内容中生成摘录。剥离HTML,删除尾随标点符号,并在删除文本时添加“更多”字符串。

使用nokogiri剥离样式属性

如何在 .NET 中从文本中去除 HTML?

Wordpress 从文档中剥离 <style> 标签

在Java中剥离HTML标签[重复]