Micki: strip_tags soll auch javacript löschen

Ich lese mittels file_get_contents eine Webseite ein, anschliessend säubere ich den Code mit strip_tags. Doch leider bleibt, wenn vorhanden javacript zurück. Wie bekomme ich den javascript auch aus dem Code.

Micki

  1. Tach!

    Ich lese mittels file_get_contents eine Webseite ein, anschliessend säubere ich den Code mit strip_tags. Doch leider bleibt, wenn vorhanden javacript zurück. Wie bekomme ich den javascript auch aus dem Code.

    Mit strip_tags() gar nicht. Entweder du hast in deinem Fall ein Muster, das du mittels regulärem Ausdruck finden kannst, oder du willst unbekannte Texte lesen, dann brauchst du einen HTML-Parser, der sowas wie ein DOM erzeugt. Dann kannst du darin die Elemente suchen. Wenn du dann auch noch Javascript-Inhalte in Attributen finden möchtest, ... das wird nicht einfach.

    dedlfix.

    1. Hallo dedlfix,

      Ich lese mittels file_get_contents eine Webseite ein, anschliessend säubere ich den Code mit strip_tags. Doch leider bleibt, wenn vorhanden javacript zurück. Wie bekomme ich den javascript auch aus dem Code.

      Mit strip_tags() gar nicht. Entweder du hast in deinem Fall ein Muster, das du mittels regulärem Ausdruck finden kannst, oder du willst unbekannte Texte lesen, dann brauchst du einen HTML-Parser, der sowas wie ein DOM erzeugt. Dann kannst du darin die Elemente suchen. Wenn du dann auch noch Javascript-Inhalte in Attributen finden möchtest, ... das wird nicht einfach.

      Einfacher als du vielleicht glaubst. JS in Attributen ist irrelevant, das wird durch strip_tags entfernt. JS aus Tags kann man mit DOMDocument entfernen:

      <?php
      
      $dom = new DOMDocument();
      $dom->loadHTML($html);
      
      $scripts = $dom->getElementsByTagName('script');
      
      foreach($scripts as $item) {
        $item->parentNode->removeChild($item); 
      }
      
      $html = strip_tags($dom->saveHTML());
      

      LG,
      CK

      1. Tach!

        JS in Attributen ist irrelevant, das wird durch strip_tags entfernt.

        Da hast du allerdings recht und der Teil meiner Antwort ist dann gegenstandslos.

        dedlfix.

      2. Lieber Christian,

        ich glaube, Du hast da etwas übersehen...

        $scripts = $dom->getElementsByTagName('script');
        
        foreach($scripts as $item) {
          $item->parentNode->removeChild($item); 
        }
        

        getElementsByTagName liefert eine live node list zurück! Im Grunde müsste man das so schreiben:

        $scripts = $dom->getElementsByTagName('script');
        
        while ($scripts->length) {
            $scripts->item(0)->parentNode->removeChild($scripts->item(0));
        }
        

        Zumindest war es meine Erfahrung, dass Du in einer simplen For-Schleife mit einer live node list nur dann Erfolg hast, wenn Du sie von hinten(!) abarbeitest, da das Entfernen des ersten Items dazu führt, dass die Liste neu geordnet wird und wieder ein erstes Element hat:

        $scripts = $dom->getElementsByTagName('script');
        
        for ($i = $scripts->length; $i >= 0; $i--) {
          $scripts->item($i)->parentNode->removeChild($scripts->item($i));
        }
        

        Da finde ich die While-Schleife dann aber doch intuitiver - und man spart sich eine Variable.

        Liebe Grüße,

        Felix Riesterer.

        1. Hallo Felix,

          ich glaube, Du hast da etwas übersehen...

          $scripts = $dom->getElementsByTagName('script');
          
          foreach($scripts as $item) {
            $item->parentNode->removeChild($item); 
          }
          

          Ist nicht gerade foreach der Spezialiterator, der auf derartige Dinge Rücksicht nimmt? Er geht nicht nach den Indexen vor, sondern behandelt die Liste als verkettete Liste. Wenn da ein Element "rausgeschossen" wird, werden die beiden losen Enden wieder zusammengebunden. Das ist für die LiveNodeList entsoprechend implementiert.

          Und wie wäre es überhaupt mit

          $dom = new DomDocument();
          $dom->loadHTML( ... );
          $textcontent = $dom->textContent;
          echo htmlspecialchars($textcontent);
          

          ?

          FrageKlaus

        2. Hallo Felix,

          ich glaube, Du hast da etwas übersehen...

          Das ist richtig :-)

          Da finde ich die While-Schleife dann aber doch intuitiver - und man spart sich eine Variable.

          Ich halte die while-Schleife auf für einen sinnvollen Kompromiss aus Lesbarkeit und Performance und würde den vermutlich auch verwenden. Der Vollständigkeit halber: der idiomatischste und lesbarste Weg wird allerdings wohl der hier sein:

          $scripts = $dom->getElementsByTagName('script');
          $nodes = [];
          
          foreach($scripts as $item) {
            $nodes[] = $item;
          }
          
          foreach($nodes as $item) {
            $item->parentNode->removeChild($item); 
          }
          

          LG,
          CK