Open Source im professionellen Einsatz

© Gunnar Pippel, 123RF

Perl-Skript holt dynamisch generierte Werte aus Webseiten

Abgesaugt

Gibt es kein API für das Einsammeln von Webinformationen, hilft oft Perl mit der Brechstange des Screenscraping. Seit Neuestem überwindet es dabei sogar die Hürde Javascript.

Nicht weniger als drei ehrwürdige Linksys-Router schaufeln die Ethernet-Pakete im Wohnbereich der Perlmeister-Labs umher. Auf allen dreien tut die Tomato-Firmware [2] seit Jahren ohne jeglichen Störfall ihren Dienst. Da Tomatos Admin-Webseite nicht nur allerlei nützliche Einstellungen erlaubt (Abbildung 1), sondern darüber hinaus noch informative Statusdaten anzeigt, lag es nahe, einen Screenscraper zu schreiben, um die Daten in regelmäßigen Abständen auf den PC zu holen, in einer Datenbank zu speichern und bei auffälligen Ausreißern Alarm auszulösen.

Abbildung 1: Tomatos Übersichtsseite listet unter anderem die Uptime des Routers in Tagen und Stunden auf.

Aua, Javascript!

Der erste Versuch allerdings ging daneben: Beim Einholen der mit Basic Auth gesicherten Seite via »wget http://root:Passwort@192.162.0.1« zeigte sich, dass Tomato die Felder der Anzeige mittels Javascript auffrischt und einfache Webscraper wie das Perl-Modul WWW::Mechanize statt der begehrten Uptime-Zeit lediglich Javascript-Code runterladen (Abbildung 2).

Abbildung 2: Durch einfaches Einholen der Webseite lässt sich der Uptime-Wert nicht extrahieren.

Damit die Seite die Daten richtig anzeigt, muss auf Client-Seite eine Javascript-Engine anlaufen, die den Code interpretiert und gemäß den darin enthaltenen Anweisungen das DOM (Document Object Model) der im Browser dargestellten Seite auffrischt. Einfache Screenscraper tun das nicht, sondern verhalten sich wie Browser mit abgeschaltetem Javascript und erhalten daher nicht das eigentlich gewünschte Ergebnis.

Das siebte Weltwunder

Die herkulische Aufgabe, diese Browseraktionen in Perl zu implementieren, hat das CPAN-Modul WWW::Scripter erledigt. Zusammen mit dem Plugin WWW::Scripter::Plugin::Ajax für Serverrückrufe, der DOM-Schnittstelle HTML::DOM und der Pure-Perl-ECMA-Skript-(Javascript)-Engine JE stellt es alle notwendigen Funktionen bereit.

Wenn man darüber nachdenkt, wie viele DOM-spezifische Unterschiede bei Browsern es allein zwischen dem Internet Explorer und Firefox gibt, dann lässt sich erahnen, wie viel Arbeit in den Modulen steckt. Außerdem verhält sich das Modul wie ein weiterer Browser, Unterschiede zwischen seiner Implementierung und dem sonst verwendeten Desktopbrowser sind unvermeidlich. Eine weitere Möglichkeit, einen Javascript-gesteuerten Skriptclient zu implementieren, wäre der Einsatz einer Browser-Fernsteuerung wie Selenium [3].

Listing 1 zieht zunächst WWW::Scripter herein und lädt das separat erhältliche Ajax-Plugin mit der Methode »use_plugin()« . Die Klasse ist von WWW::Mechanize und damit auch von LWP::UserAgent abgeleitet und unterstützt demnach die Methode »get()« zum Einholen von Webseiten. Da der Router beim HTTP-Zugang nach einem Passwort für den Rootaccount fragt, stellt das Skript dieses mittels der ebenfalls ererbten Methode »credentials()« zur Verfügung.

Listing 1

tomato-overview

01 #!/usr/local/bin/perl -w
02 use strict;
03 use WWW::Scripter;
04 use Sysadm::Install qw(:all);
05 use HTML::TreeBuilder::XPath;
06
07 my $w = WWW::Scripter->new();
08 $w->use_plugin('Ajax');
09
10 my $pw = slurp "pw.txt";
11 chomp $pw;
12 $w->credentials( "root", $pw );
13 $w->get('http://192.168.0.1');
14
15 $w->wait_for_timers( max_wait => 1 );
16
17 my $tree= HTML::TreeBuilder::XPath->new();
18 $tree->parse( $w->content() );
19 my $uptime =
20   $tree->findvalue(
21     '/html/body//tr[@id="uptime"]/' .
22     'td[@class="content"]');
23
24 print "uptime: $uptime\n";

Damit das Passwort nicht hart im Skript kodiert ist, liest es die Funktion »slurp()« aus der Datei »pw.txt« im aktuellen Verzeichnis ein. Die Datei enthält nur eine Zeile mit dem Passwort und sollte gegen unberechtigte Lese- oder gar Schreibzugriffe geschützt sein. Ganz astrein ist diese Lösung freilich nicht, doch irgendwie muss ich den Schlüssel unter der Fußmatte verstecken, wenn das Skript automatisch laufen soll und der User nicht jedes Mal das Passwort tippen kann.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 3 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook