supprimer la balise script du contenu HTML

j'utilise le purificateur HTML (http://htmlpurifier.org/)

je veux juste supprimer <script> tags seulement. Je ne veux pas supprimer le formatage en ligne ou autre chose.

Comment puis-je y parvenir?

encore une chose, il n'y a aucune autre façon de supprimer les balises de script de HTML

48
demandé sur I-M-JM 2011-08-20 13:18:11

10 réponses

parce que cette question est marquée avec je vais répondre avec la solution du pauvre dans cette situation:

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

cependant, les expressions régulières ne sont pas pour l'analyse HTML/XML, même si vous écrivez l'expression parfait il se brisera éventuellement, il n'en vaut pas la peine, Bien que, dans certains cas, il est utile de corriger rapidement un certain balisage, et comme il est avec des corrections rapides, oubliez sécurité . Utilisez regex uniquement sur le contenu / le markup en lequel vous avez confiance.

rappelez-vous, tout ce que l'utilisateur entre doit être considéré comme pas sûr .

mieux la solution ici serait d'utiliser DOMDocument qui est conçu pour cela. Voici un extrait qui démontre à quel point il est facile, propre (par rapport à regex), (presque) fiable et (presque) sécuritaire de faire la même chose:

<?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();

j'ai supprimé le HTML intentionnellement parce que même cela peut bork .

105
répondu Dejan Marjanovic 2014-04-23 00:41:40

Utiliser le PHP DOMDocument analyseur.

$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();

Ce travaille me moi, en utilisant le document HTML suivant:

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

il suffit de garder à l'esprit que L'analyseur DOMDocument nécessite PHP 5 ou plus.

36
répondu Alex 2012-12-01 18:48:11

j'utiliserais BeautifulSoup si c'est disponible. Ce genre de chose très facile.

Ne pas essayez de le faire avec les expressions régulières. De cette façon se trouve la folie.

1
répondu Malvolio 2011-08-20 10:06:27

j'avais été aux prises avec cette question. J'ai découvert que vous avez seulement besoin d'une fonction. explode('>', $html); Le seul dénominateur commun à toute balise est < et >. Ensuite, il y a généralement des guillemets ( " ). Vous pouvez extraire l'information si facilement une fois que vous trouvez le dénominateur commun. C'est ce que j'ai trouvé:

$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;

je vois que cela ne fonctionne vraiment que pour les balises script parce que vous n'aurez jamais de balises script imbriquées. Bien sûr, vous pouvez facilement ajouter plus de code qui fait la même vérification et rassembler les tags imbriqués.

j'appelle ça du codage en accordéon. implode();explode(); sont les moyens les plus faciles pour obtenir votre logique qui coule si vous avez un dénominateur commun.

1
répondu ClandestineCoder 2013-04-16 07:49:43
$html = <<<HTML
...
HTML;
$dom = new DOMDocument();
$dom->loadHTML($html);
$tags_to_remove = array('script','style','iframe','link');
foreach($tags_to_remove as $tag){
    $element = $dom->getElementsByTagName($tag);
    foreach($element  as $item){
        $item->parentNode->removeChild($item);
    }
}
$html = $dom->saveHTML();
1
répondu prasanthnv 2018-01-24 07:59:16

plus court:

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

quand on fait du regex, les choses peuvent mal tourner, donc c'est plus sûr de faire comme ça:

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

de sorte que lorsque le" accident " se produit, nous obtenons l'original $html au lieu de chaîne vide.

0
répondu Binh WPO 2015-03-25 07:43:42
  • il s'agit d'une fusion des deux ClandestineCoder & Binh WPO .

le problème avec les flèches de l'étiquette de script est qu'ils peuvent avoir plus d'une variante

ex. (< = &lt; = &amp;lt; ) & ( > = &gt; = &amp;gt; )

donc au lieu de créer un tableau de motifs avec comme un bazillion variante, imho une meilleure solution serait

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

cela supprimera tout ce qui ressemble à script.../script quel que soit le code de la flèche/variante et u peut le tester ici https://regex101.com/r/lK6vS8/1

0
répondu ctf0 2016-07-31 22:01:28

un exemple modifiant la réponse de ctf0. Cela ne devrait faire le preg_replace qu'une seule fois, mais devrait également vérifier les erreurs et le code de bloc de caractères pour la barre oblique vers l'avant.

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

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

si vous utilisez php 7, vous pouvez utiliser l'opérateur null coalesce pour le simplifier encore plus.

$pattern = '/(script.*?(?:\/|&#47;|&#x0002F;)script)/ius'; 
return (preg_replace($pattern, '', $str) ?? $str); 
0
répondu tech-e 2017-05-09 21:51:27

c'est une variante simplifiée de la réponse de Dejan Marjanovic:

function removeTags($html, $tag) {
    $dom = new DOMDocument();
    $dom->loadHTML($html);
    foreach (iterator_to_array($dom->getElementsByTagName($tag)) as $item) {
        $item->parentNode->removeChild($item);
    }
    return $dom->saveHTML();
}

peut être utilisé pour enlever tout type d'étiquette, y compris <script> :

$scriptlessHtml = removeTags($html, 'script');
0
répondu mae 2018-01-21 00:01:19

utilisez la fonction str_replace pour les remplacer par de l'espace vide ou quelque chose

$query = '<script>console.log("I should be banned")</script>';

$badChar = array('<script>','</script>');
$query = str_replace($badChar, '', $query);

echo $query; 
//this echoes console.log("I should be banned")

?>

0
répondu Oliver Kalima Tembo 2018-06-29 19:58:14