68

HTML Purifier(http://htmlpurifier.org/)を使用しています

<script>タグだけを削除したいだけです。インラインフォーマットなどを削除したくありません。

どうすればこれを達成できますか?

もう1つ、HTMLからスクリプトタグを削除する他の方法があります

4

13 に答える 13

152

この質問はでタグ付けされているため、この状況では貧乏人の解決策で答えます。

$html = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $html);

ただし、正規表現は HTML/XML を解析するためのものではありません。完璧な表現を書いたとしても、最終的には壊れてしまいます。その価値はありませんが、場合によっては、マークアップをすばやく修正するのに役立ちます。セキュリティを忘れてください。信頼できるコンテンツ/マークアップでのみ正規表現を使用してください。

ユーザー入力は安全ではないと見なされるべきであることを忘れないでください。

ここでのより良い解決策DOMDocumentは、このために設計されたものを使用することです。これは、同じことを行うことがいかに簡単で、(正規表現と比較して) クリーンで、(ほぼ) 信頼性が高く、(ほぼ) 安全であるかを示すスニペットです。

<?php

$html = <<<HTML
...
HTML;

$dom = new DOMDocument();

$dom->loadHTML($html);

$script = $dom->getElementsByTagName('script');

$remove = [];
foreach($script as $item)
{
  $remove[] = $item;
}

foreach ($remove as $item)
{
  $item->parentNode->removeChild($item); 
}

$html = $dom->saveHTML();

これでもうまくいかない可能性があるため、意図的に HTML を削除しました。

于 2011-08-20T10:15:47.453 に答える
39

PHPDOMDocumentパーサーを使用します。

$doc = new DOMDocument();

// load the HTML string we want to strip
$doc->loadHTML($html);

// get all the script tags
$script_tags = $doc->getElementsByTagName('script');

$length = $script_tags->length;

// for each tag, remove it from the DOM
for ($i = 0; $i < $length; $i++) {
  $script_tags->item($i)->parentNode->removeChild($script_tags->item($i));
}

// get the HTML string back
$no_script_html_string = $doc->saveHTML();

これは、次のHTMLドキュメントを使用して私に働きました:

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>
            hey
        </title>
        <script>
            alert("hello");
        </script>
    </head>
    <body>
        hey
    </body>
</html>

DOMDocumentパーサーには PHP 5 以上が必要であることに注意してください。

于 2011-08-20T10:03:07.630 に答える
2

Shorter:

$html = preg_replace("/<script.*?\/script>/s", "", $html);

When doing regex things might go wrong, so it's safer to do like this:

$html = preg_replace("/<script.*?\/script>/s", "", $html) ? : $html;

So that when the "accident" happen, we get the original $html instead of empty string.

于 2015-03-25T07:43:42.147 に答える
2
  • これはClandestineCoderBinh WPOの両方のマージです。

スクリプト タグの矢印の問題は、複数のバリアントを持つことができることです。

元。(< = &lt;= &amp;lt;) & ( > = &gt;= &amp;gt;)

したがって、無数のバリアントのようなパターン配列を作成する代わりに、より良い解決策は

return preg_replace('/script.*?\/script/ius', '', $text)
       ? preg_replace('/script.*?\/script/ius', '', $text)
       : $text;

script.../scriptこれにより、矢印コード/バリアントに関係なく、次のように見えるものはすべて削除され、ここでテストできますhttps://regex101.com/r/lK6vS8/1

于 2016-07-31T22:01:28.253 に答える
2

ctf0 の回答を変更する例。これは、preg_replace を 1 回だけ実行するだけでなく、エラーをチェックし、スラッシュのブロック char コードもチェックする必要があります。

$str = '<script> var a - 1; <&#47;script>'; 

$pattern = '/(script.*?(?:\/|&#47;|&#x0002F;)script)/ius';
$replace = preg_replace($pattern, '', $str); 
return ($replace !== null)? $replace : $str;  

PHP 7 を使用している場合は、null 合体演算子を使用してさらに単純化できます。

$pattern = '/(script.*?(?:\/|&#47;|&#x0002F;)script)/ius'; 
return (preg_replace($pattern, '', $str) ?? $str); 
于 2017-03-22T19:05:43.533 に答える
1

私はこの質問に苦労していました。本当に必要な機能は 1 つだけであることがわかりました。爆発('>', $html); タグの唯一の共通点は < と > です。その後は通常、引用符 ( " ) です。共通の分母を見つけると、情報を非常に簡単に抽出できます。これが私が思いついたものです。

$html = file_get_contents('http://some_page.html');

$h = explode('>', $html);

foreach($h as $k => $v){

    $v = trim($v);//clean it up a bit

    if(preg_match('/^(<script[.*]*)/ius', $v)){//my regex here might be questionable

        $counter = $k;//match opening tag and start counter for backtrace

        }elseif(preg_match('/([.*]*<\/script$)/ius', $v)){//but it gets the job done

            $script_length = $k - $counter;

            $counter = 0;

            for($i = $script_length; $i >= 0; $i--){
                $h[$k-$i] = '';//backtrace and clear everything in between
                }
            }           
        }
for($i = 0; $i <= count($h); $i++){
    if($h[$i] != ''){
    $ht[$i] = $h[$i];//clean out the blanks so when we implode it works right.
        }
    }
$html = implode('>', $ht);//all scripts stripped.


echo $html;

ネストされたスクリプトタグは決してないため、これは実際にはスクリプトタグに対してのみ機能することがわかります。もちろん、同じチェックを行い、ネストされたタグを収集するコードを簡単に追加できます。

私はそれをアコーディオンコーディングと呼んでいます。内破();爆発(); 共通の分母がある場合、ロジックを流す最も簡単な方法です。

于 2013-04-15T04:27:19.780 に答える
1

BeautifulSoup が利用可能であれば使用します。この種のことを非常に簡単にします。

正規表現でそれをやろうとしないでください。その方法は狂気です。

于 2011-08-20T10:06:27.257 に答える