www.farid-hajji.net banner

Farid Hajji

Perl: Einführung, Anwendungen, Referenz (2/e) [Support-Site]

Farid Hajji: Perl - Einführung, Anwendungen, Referenz
2., aktualisierte und erweiterte Auflage
Addison-Wesley Longman, ISBN 3-8273-1535-2

Parsen von HTML-Texten

Motivation

Das Parsen von HTML-Texten ist nicht ganz einfach. Mit der Verwendung einfacher regulärer Ausdrücke ist es noch nicht getan: Kommentare können beispielsweise ebenfalls HTML-Tags enthalten, wodurch einfache Mechanismen versagen können.

Glücklicherweise gibt es das Modul HTML::Parser aus dem CPAN. Dieses Modul kann nicht nur HTML-Daten, sondern ganz allgemein SGML-Daten parsen.

Das HTML::Parser-Modul

Wie wird nun HTML::Parser verwendet? Da dieses Modul als Basisklasse entworfen wurde, sollten Sie eine Subklasse von HTML::Parser, wie in Kapitel 15 gezeigt, bilden. Anschließend können Sie einzelne Funktionen von HTML::Parser überladen. Diese Funktionen sind Callbacks, die automatisch vom Parser aufgerufen werden, wenn ein Tag, normaler Text etc. erkannt werden.

Die Manual-Seite man HTML::Parser liefert eine komplette Liste der überladbaren Funktionen. Wird eine Funktion nicht überladen, so tut sie in den meisten Fällen gar nichts.

Einige nützliche Funktionen sind:



Ein einfaches Beispiel

Das Programm html-parse.pl bildet eine Unterklasse von HTML::Parser mit Hilfe des Schlüsselworts package und des Arrays @ISA. Anschließend werden die Methoden start(), end() und text() überladen.

Beachten Sie die Signaturen der Funktionen! Da es sich um Methoden handelt, wird implizit als erstes Argument immer $self mit übergeben. Erst dann folgt die normale Signatur:

# Die start()-Methode wird bei jedem Start-Tag aufgerufen:
sub start {
    my ($self, $tag, $attr, $attrseq, $origtext) = @_;

In den überladenen Funktionen geben wir einfach die Werte der Argumente aus. HTML-Text wird dabei nicht ausgegeben! Wenn Sie dies möchten, sollten Sie den $origtext der gewünschten Funktionen ausgeben. In unserem Fall beschränken wir uns auf die Ausgabe der Argumente.

Die Argumente $attr und $attrseq sind Zeiger auf Hashes bzw. auf Arrays. Um diese bequem auszugeben, benutzen wir die Funktion Dumper des Stringifizierungsmoduls Data::Dumper, wie dies bereits in Kapitel 13 und Kapitel 18 gezeigt wurde. Dies hätten wir auch genauso gut wie folgt schreiben:

# $attr ist ein Zeiger auf einen Hash.
print "{",
      join(",", 
           map { "$_ => $attr->{$_}" } sort keys %{ $attr }
          ),
      "}\n";

# $attrseq ist ein Zeiger auf ein Array.
print "[", join(",", @{ $attrseq }), "]\n";

Die einzelnen Text-Chunks werden in der Methode text() ausgeben. Damit auch Newlines und Whitespaces sichtbar werden, wurden die Text-Chunks in eckigen Klammern ausgegeben.

Bei folgender Eingabedatei:

<html>
<!-- Eine Testseite für html-parse.pl -->
<head>
  <title>Das ist ein Test-Titel</title>
  <link rel=stylesheet type="text/css" href="../perlv2.css">
  <link rev="Prev" href="../ew/html-parse-intro.html">
  <meta name="Author" content="Farid Hajji">
  <meta name="keywords" content="HTML::Parser,testseite">
</head>
<body>
  <div class="navbar">
  <a href="../cgiwww.html"><img src="../icons/left.gif" width=29
     height=30 border=0 align=bottom alt="[Kapitel 19]"></a>
  <a href="../index.html"><img src="../icons/up.gif" width=29
     height=30 border=0 align=bottom alt="[Hauptseite]"></a>
  </div>
  <div class="title" align="center">
    Das ist der Titel
    <br>
    Hier ist der Untertitel
  </div>
<h1>Eine erste Überschrift</h1>
Text der ersten Überschrift. Dieser Text erstreckt sich
über mehrere Zeilen in der HTML-Datei.</body></html>

sieht die Ausgabe des Programms wie folgt aus:

farid@sun-1:~/ex> ./html-parse.pl html-parse.test
Recognized Tag: html
Attributes: 
$VAR1 = {};
Sequence of Attributes: 
$VAR1 = [];
Original Tag was: <html>
------------------------------------------------------------
Recognized Text-Chunk:
[
]
------------------------------------------------------------
Recognized Text-Chunk:
[
]
------------------------------------------------------------
Recognized Tag: head
Attributes: 
$VAR1 = {};
Sequence of Attributes: 
$VAR1 = [];
Original Tag was: <head>
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized Tag: title
Attributes: 
$VAR1 = {};
Sequence of Attributes: 
$VAR1 = [];
Original Tag was: <title>
------------------------------------------------------------
Recognized Text-Chunk:
[Das ist ein Test-Titel]
------------------------------------------------------------
Recognized End-Tag: title
Orignal End-Tag was: </title>
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized Tag: link
Attributes: 
$VAR1 = {
          'href' => '../perlv2.css',
          'type' => 'text/css',
          'rel' => 'stylesheet'
        };
Sequence of Attributes: 
$VAR1 = [
          'rel',
          'type',
          'href'
        ];
Original Tag was: <link rel=stylesheet type="text/css" href="../perlv2.css">
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized Tag: link
Attributes: 
$VAR1 = {
          'rev' => 'Prev',
          'href' => '../ew/html-parse-intro.html'
        };
Sequence of Attributes: 
$VAR1 = [
          'rev',
          'href'
        ];
Original Tag was: <link rev="Prev" href="../ew/html-parse-intro.html">
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized Tag: meta
Attributes: 
$VAR1 = {
          'content' => 'Farid Hajji',
          'name' => 'Author'
        };
Sequence of Attributes: 
$VAR1 = [
          'name',
          'content'
        ];
Original Tag was: <meta name="Author" content="Farid Hajji">
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized Tag: meta
Attributes: 
$VAR1 = {
          'content' => 'HTML::Parser,testseite',
          'name' => 'keywords'
        };
Sequence of Attributes: 
$VAR1 = [
          'name',
          'content'
        ];
Original Tag was: <meta name="keywords" content="HTML::Parser,testseite">
------------------------------------------------------------
Recognized Text-Chunk:
[
]
------------------------------------------------------------
Recognized End-Tag: head
Orignal End-Tag was: </head>
------------------------------------------------------------
Recognized Text-Chunk:
[
]
------------------------------------------------------------
Recognized Tag: body
Attributes: 
$VAR1 = {};
Sequence of Attributes: 
$VAR1 = [];
Original Tag was: <body>
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized Tag: div
Attributes: 
$VAR1 = {
          'class' => 'navbar'
        };
Sequence of Attributes: 
$VAR1 = [
          'class'
        ];
Original Tag was: <div class="navbar">
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized Tag: a
Attributes: 
$VAR1 = {
          'href' => '../cgiwww.html'
        };
Sequence of Attributes: 
$VAR1 = [
          'href'
        ];
Original Tag was: <a href="../cgiwww.html">
------------------------------------------------------------
Recognized Tag: img
Attributes: 
$VAR1 = {
          'alt' => '[Kapitel 19]',
          'height' => 30,
          'border' => '0',
          'src' => '../icons/left.gif',
          'align' => 'bottom',
          'width' => 29
        };
Sequence of Attributes: 
$VAR1 = [
          'src',
          'width',
          'height',
          'border',
          'align',
          'alt'
        ];
Original Tag was: <img src="../icons/left.gif" width=29
     height=30 border=0 align=bottom alt="[Kapitel 19]">
------------------------------------------------------------
Recognized End-Tag: a
Orignal End-Tag was: </a>
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized Tag: a
Attributes: 
$VAR1 = {
          'href' => '../index.html'
        };
Sequence of Attributes: 
$VAR1 = [
          'href'
        ];
Original Tag was: <a href="../index.html">
------------------------------------------------------------
Recognized Tag: img
Attributes: 
$VAR1 = {
          'alt' => '[Hauptseite]',
          'height' => 30,
          'border' => '0',
          'src' => '../icons/up.gif',
          'align' => 'bottom',
          'width' => 29
        };
Sequence of Attributes: 
$VAR1 = [
          'src',
          'width',
          'height',
          'border',
          'align',
          'alt'
        ];
Original Tag was: <img src="../icons/up.gif" width=29
     height=30 border=0 align=bottom alt="[Hauptseite]">
------------------------------------------------------------
Recognized End-Tag: a
Orignal End-Tag was: </a>
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized End-Tag: div
Orignal End-Tag was: </div>
------------------------------------------------------------
Recognized Text-Chunk:
[
  ]
------------------------------------------------------------
Recognized Tag: div
Attributes: 
$VAR1 = {
          'class' => 'title',
          'align' => 'center'
        };
Sequence of Attributes: 
$VAR1 = [
          'class',
          'align'
        ];
Original Tag was: <div class="title" align="center">
------------------------------------------------------------
Recognized Text-Chunk:
[
    Das ist der Titel
    ]
------------------------------------------------------------
Recognized Tag: br
Attributes: 
$VAR1 = {};
Sequence of Attributes: 
$VAR1 = [];
Original Tag was: <br>
------------------------------------------------------------
Recognized Text-Chunk:
[
    Hier ist der Untertitel
  ]
------------------------------------------------------------
Recognized End-Tag: div
Orignal End-Tag was: </div>
------------------------------------------------------------
Recognized Text-Chunk:
[
]
------------------------------------------------------------
Recognized Tag: h1
Attributes: 
$VAR1 = {};
Sequence of Attributes: 
$VAR1 = [];
Original Tag was: <h1>
------------------------------------------------------------
Recognized Text-Chunk:
[Eine erste Überschrift]
------------------------------------------------------------
Recognized End-Tag: h1
Orignal End-Tag was: </h1>
------------------------------------------------------------
Recognized Text-Chunk:
[
Text der ersten Überschrift. Dieser Text erstreckt sich
über mehrere Zeilen in der HTML-Datei.]
------------------------------------------------------------
Recognized End-Tag: body
Orignal End-Tag was: </body>
------------------------------------------------------------
Recognized End-Tag: html
Orignal End-Tag was: </html>
------------------------------------------------------------

Wir erkennen, daß die Tags richtig erkannt wurden und auch die entsprechenden Methoden getriggert haben. Interessant ist auch, daß hier die Verschachtelung der Tags offenbar nicht vom Parser berücksichtig wurde. Dies sollten Sie natürlich bei Bedarf selbst tun oder weitere fertige HTML-Klassen aus dem CPAN verwenden.

Weitere HTML-Klassen
Neben HTML::Parser gibt es noch eine Reihe weiterer nützlicher HTML-Klassen:
Einige nützliche Anwendungen
In Vorbereitung.

[Prev] [Up] [Next]

[Alte Quelle]


Last modified: $Date: 2006/05/18 12:55:48 $
FH. Search :: Sitemap :: Disclaimer :: Copyright :: Privacy
FreeBSD Logo