簡體   English   中英

使用 JS 正則表達式從 html 中刪除所有腳本標簽

[英]Removing all script tags from html with JS Regular Expression

我想從 Pastebin 的這個 HTML 中去除腳本標簽:

http://pastebin.com/mdxygM0a

我嘗試使用以下正則表達式:

html.replace(/<script.*>.*<\/script>/ims, " ")

但它不會刪除 HTML 中的所有腳本標簽。它只會刪除內聯腳本。 我正在尋找一些可以刪除所有腳本標簽(內聯和多行)的正則表達式。 如果對我的樣品http://pastebin.com/mdxygM0a進行測試,我們將不勝感激

jQuery 在某些情況下使用正則表達式來刪除腳本標簽,我很確定它的開發人員有充分的理由這樣做。 可能某些瀏覽在使用innerHTML插入腳本時會執行腳本。

這是正則表達式:

/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi

在人們開始哭泣“但是 HTML 的正則表達式是邪惡的”之前: 是的,它們是- 但是對於腳本標簽,由於特殊行為它們是安全的 - <script>部分可能根本不包含</script>除非它應該結束在這個 position。 因此,很容易將其與正則表達式匹配。 但是,快速瀏覽一下,上面的正則表達式不考慮結束標記內的尾隨空格,因此您必須測試</script等是否仍然有效。

嘗試使用正則表達式刪除 HTML 標記是有問題的。 您不知道其中的腳本或屬性值是什么。 一種方法是將其作為 div 的 innerHTML 插入,刪除任何腳本元素並返回 innerHTML,例如

  function stripScripts(s) {
    var div = document.createElement('div');
    div.innerHTML = s;
    var scripts = div.getElementsByTagName('script');
    var i = scripts.length;
    while (i--) {
      scripts[i].parentNode.removeChild(scripts[i]);
    }
    return div.innerHTML;
  }

alert(
 stripScripts('<span><script type="text/javascript">alert(\'foo\');<\/script><\/span>')
);

請注意,目前,如果使用 innerHTML 屬性插入,瀏覽器將不會執行腳本,並且可能永遠不會執行,尤其是當元素未添加到文檔中時。

正則表達式是可擊敗的,但如果您有一個不想注入 DOM 的 HTML 的字符串版本,那么它們可能是最好的方法。 你可能想把它放在一個循環中來處理類似的事情:

<scr<script>Ha!</script>ipt> alert(document.cookie);</script>

這是我所做的,使用上面的 jquery 正則表達式:

var SCRIPT_REGEX = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi;
while (SCRIPT_REGEX.test(text)) {
    text = text.replace(SCRIPT_REGEX, "");
}

這個正則表達式也應該工作:

<script(?:(?!\/\/)(?!\/\*)[^'"]|"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\/\/.*(?:\n)|\/\*(?:(?:.|\s))*?\*\/)*?<\/script>

它甚至允許在里面有像這樣的“有問題的”變量字符串:

<script type="text/javascript">
   var test1 = "</script>";
   var test2 = '\'</script>';
   var test1 = "\"</script>";
   var test1 = "<script>\"";
   var test2 = '<scr\'ipt>';
   /* </script> */
   // </script>
   /* ' */
   // var foo=" '
</script>

似乎 jQuery 和 Prototype 在這些上都失敗了……

編輯 2017 年 7 月 31 日:添加了 a) 非捕獲組以獲得更好的性能(並且沒有空組)和 b) 支持 JavaScript 評論。

每當您不得不求助於基於正則表達式的腳本標記清理時。 至少以以下形式在結束標記中添加一個空格

</script\s*>

否則像

<script>alert(666)</script   >

將保留,因為標記名后的尾隨空格有效。

為什么不使用 jQuery.parseHTML() http://api.jquery.com/jquery.parsehtml/

如果你想從一些 HTML 文本中刪除所有 JavaScript 代碼,那么刪除<script>標記是不夠的,因為 JavaScript 仍然可以存在於“onclick”中,“參考錯誤”,“參考”

試試這個處理所有這些的 npm 模塊: https://www.npmjs.com/package/strip-js

在我的情況下,我需要解析頁面標題並擁有 jQuery 的所有其他優點,減去它的觸發腳本。 這是我似乎可行的解決方案。

        $.get('/somepage.htm', function (data) {
            // excluded code to extract title for simplicity
            var bodySI = data.indexOf('<body>') + '<body>'.length,
                bodyEI = data.indexOf('</body>'),
                body = data.substr(bodySI, bodyEI - bodySI),
                $body;

            body = body.replace(/<script[^>]*>/gi, ' <!-- ');
            body = body.replace(/<\/script>/gi, ' --> ');

            //console.log(body);

            $body = $('<div>').html(body);
            console.log($body.html());
        });

這種快捷方式擔心腳本,因為您沒有嘗試刪除腳本標簽和內容,而是將它們替換為注釋呈現方案以破壞它們無用,因為您將使用注釋分隔腳本聲明。

讓我知道這是否仍然存在問題,因為它也會幫助我。

您可以在沒有正則表達式的情況下執行此操作。 只需使用document.createElement()將您的 HTML 字符串轉換為 HTML 節點,找到所有帶有element.getElementsByTagName('script') ,然后remove()它們!

有趣的事實:當你創建一個帶有<script>標簽的元素時,SO 的演示不喜歡它,下面的代碼片段不會運行:但它確實適用於: JSBin.com 的完整工作演示

 var el = document.createElement( 'html' ); el.innerHTML = "<p>Valid paragraph.</p><p>Another valid paragraph.</p><script>Dangerous scripting.;.</script><p>Last final paragraph;</p>"; var scripts = el.getElementsByTagName( 'script' ); // Live NodeList of your anchor elements for(var i = 0; i < scripts.length; i++) { var script = scripts[i]. script.remove(); } console.log(el.innerHTML);

這是一個比正則表達式更清潔的解決方案,恕我直言。

以下是各種 shell 腳本,您可以使用這些腳本去除不同的元素。

# doctype
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/<\!DOCTYPE\s\+html[^>]*>/<\!DOCTYPE html>/gi" {} \;

# meta charset
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/<meta[^>]*content=[\"'][^\"']*utf-8[\"'][^>]*>/<meta charset=\"utf-8\">/gi" {} \;

# script text/javascript
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/\(<script[^>]*\)\(\stype=[\"']text\/javascript[\"']\)\(\s\?[^>]*>\)/\1\3/gi" {} \;

# style text/css
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/\(<style[^>]*\)\(\stype=[\"']text\/css[\"']\)\(\s\?[^>]*>\)/\1\3/gi" {} \;

# html xmlns
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/\(<html[^>]*\)\(\sxmlns=[\"'][^\"']*[\"']\)\(\s\?[^>]*>\)/\1\3/gi" {} \;

# html xml:lang
find . -regex ".*\.\(html\|py\)$" -type f -exec sed -i "s/\(<html[^>]*\)\(\sxml:lang=[\"'][^\"']*[\"']\)\(\s\?[^>]*>\)/\1\3/gi" {} \;

/(?:(?!</s\w)<[^<] ) </s\w*/gi; - 刪除任意組合的任何序列

嘗試這個:

var text = text.replace(/<script[^>]*>(?:(?!<\/script>)[^])*<\/script>/g, "")

不要使用正則表達式來解析 HTML。

考慮以下字符串:

var str = "<script>var false_closing_tag = '</script>';</script>";
var stripped = str.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
console.log(stripped); // Logs: ';</script>

當前投票最多的正則表達式答案將無法完全刪除它。 (嘗試一下)。 我什至無法在 SO 編輯器或 JSFiddle 中運行它,因為它們在運行代碼之前都沒有使用足夠的方法來解析代碼。

另一個涉及將它添加到<div>元素然后拉動 div 的innerText的選項也有負面影響:它實際上會運行代碼(這是一個安全問題)並且它會刪除所有 HTML 而不是只是腳本標簽。

解決方案

您需要實際解析文本:

function stripScriptTags(str){
  if(typeof str !== 'string') {
    return false;
  }
  var opened_quote_type = null;
  var in_script_tag = false;
  var string_buffer = [];
  for (let i = 0; i < str.length; i++) {
    if(opened_quote_type === null && ["'", '"', '`'].includes(str[i])){
      opened_quote_type = str[i];
    }else if(opened_quote_type === str[i]){
      opened_quote_type = null;
    }
    if(str.length > i+7 && str.toUpperCase().substring(i, i+7) === '<SCRIPT'){
      i += 7;
      in_script_tag = true;
    }
    if(in_script_tag && 
       opened_quote_type === null && 
       str.length > i+9 && 
       str.toUpperCase().substring(i, i+9) === '</SCRIPT>'
    ){
      i += 9;
      in_script_tag = false;
    }
    if(!in_script_tag){
      string_buffer.push(str[i]);
    }
  }
  return string_buffer.join('');
}

你可以試試

$("your_div_id").remove();  

或者

 $("your_div_id").html(""); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM