WWW::Mechanize::Firefox

Max Maischein

Frankfurt.pm

Übersicht

  • Warum WWW::Mechanize::Firefox?

  • Was ist WWW::Mechanize::Firefox?

  • Verwendungsmöglichkeiten

Wer bin ich

  • Max Maischein

  • DZ BANK Frankfurt

  • Deutsche Zentralgenossenschaftsbank

  • Informationsmanagement

Mein Leitmotiv

Automation

  • Wenn ich es manuell machen kann

  • ... kann es der Computer wiederholen

  • ... und zwar immer wieder korrekt

Meine Werkzeuge

  • Perl (natürlich)

  • WWW::Mechanize

  • WWW::Mechanize::Shell (GPW 2002)

  • Win32::OLE (GPW 2007)

  • WWW::Mechanize::Shell (2002)

  • ... reicht nicht mehr aus

Web 2.0

  • Webanwendungen sind auf dem Vormarsch

  • Web 2.0 ist problematisch

  • Anwendungen halten Status im Client

  • Anwendungen verwenden Javascript

  • Javascript ist nicht Perl's Stärle

Javascript

  • Javascript::SpiderMonkey von Mike Schili, Thomas Busch auf CPAN

  • Mozilla Javascript Interpreter

  • Viele externe Prerequisites

  • Nur Javascript, kein DOM

Javascript (II)

  • Javascript::Engine von Father Chrysostomos auf CPAN

  • Reines Perl

  • Laaaaaangsam

  • WWW::Mechanize::Javascript, WWW::Scripter

  • Benutzt Javascript::Engine

Firefox

Was, wenn ich Firefox verwenden könnte?

  • Anerkannte Platform

  • Kompatible Platform

  • Interaktive Platform

Kommunikation Firefox/Perl

  • Mausklicks senden?

  • Tastaturkommandos senden?

  • nicht interaktiv

  • nicht robust bei anderer Verwendung des Rechners

mozrepl to the rescue

Mozrepl bietet eine Netzwerkschnittstelle zu Firefox

Perl spricht TCP

WWW::Mechanize::Firefox

 1:  my $mech = WWW::Mechanize::Firefox->new();
 2:  $mech->get('http://www.froscon.de');

Was ist WWW::Mechanize::Firefox

  • eine erweiterte Schnittstelle

  • von WWW::Mechanize

  • mit Firefox als Backend

Features

  • Normale WWW::Mechanize API

  • Javascript

  • CSS Selektoren (via HTML::Selector::XPath)

  • XPath Selektoren

  • Javascript events (onLoad)

  • Javascript Fehlermeldungen!

Wofür kann ich WWW::Mechanize::Firefox verwenden?

  • Webseitenautomation

  • Integrierte JS Unit-Tests

  • Eingabevalidierung mit Javascript auch Server-side

  • Verrückte Dinge

Live demo

Firefox steuern

 1:  my $mech = WWW::Mechanize::Firefox->new();
 2:  $mech->get('http://www.froscon.de');

Live demo

Firefox steuern

01-open-local.pl

 1:  my $mech = WWW::Mechanize::Firefox->new();
 2:  $mech->get_local('datei.html');

Live demo

Firefox zuhören

02-urlbar.pl

Live demo

Listen to Firefox events

02-urlbar.pl

Live demo

Webseiten Bedienungstests

03-dump-links.pl

 1:  my $mech = WWW::Mechanize::Firefox->new();
 2:  $mech->get_local('link.html');
 3:
 4:  sleep 5;
 5:  $mech->highlight_node(
 6:      $mech->selector('a.download'));
 7:  
 8:  print $_->{href}, " - ", $_->{innerHTML}, "\n"
 9:      for $mech->selector('a.download');

Live demo

Javascript ausfuehren

04-javascript.pl

 1:  my $mech = WWW::Mechanize::Firefox->new();
 2:  $mech->get_local('datei.html');
 3:  $mech->eval_in_page(<<'JS');
 4:      alert('Hallo FrOSCon');
 5:  JS

Live demo

Webseitenmanipulation:

 1:  var secret = "12345"  + "geheim";

Live demo

Webseitenmanipulation:

 1:  var secret = "12345"  + "geheim";

Javascript Variablen auslesen (und setzen)

Live demo

05-manipulate-javascript.pl

 1:  my $mech = WWW::Mechanize::Firefox->new();
 2:  $mech->get_local('javascript.html');
 3:
 4:  my ($val,$type) = $mech->eval_in_page(<<'JS');
 5:      secret
 6:  JS
 7:
 8:  print "Das Kennwort ist $val";
 9:
10:  # Wert setzen
11:  sleep 5;
12:  $mech->value('pass',$val);

Screenshots zur Dokumentation/Logging

06-screenshot.pl

 1:  my $png = $mech->content_as_png()

Was benötigt WWW::Mechanize::Firefox?

  • Firefox

  • mozrepl Add-On

  • MozRepl::RemoteObject (+ MozRepl + Net::Telnet)

  • WWW::Mechanize

Was fehlt WWW::Mechanize::Firefox?

  • (A)Synchrones Eventmodell

  • Asynchrone Kommunikation (AnyEvent)

  • Mehr gekapselte Firefox API (MDC)

  • Mehr WWW::Mechanize API

  • Firefox ohne Display ("headless")

  • DOM ohne Firefox (js_env), V8 Javascript Engine

Verrückte Ideen

  • Fenster öffnen / schliessen

  • Downloads

  • Dateikonversion

  • HTML nach PNG

  • SVG nach PNG

  • JPG nach PNG

Verrückte Ideen

  • Firefox als Charting-Engine mit Flot(r)

  • Statt Inkscape

  • Firefox auf anderen Rechnern steuern (TCP)

  • Firefox als Medienkonverter

  • Movie Resize / Video Element

  • Webcam in Perl?

Beispielcode

Alle Beispiele auch auf CPAN unter

WWW::Mechanize::Firefox::Examples

Danke

Fragen?

Alle Folien liegen unter

http://corion.net/talks/

Bonus - Using W:M:F right here!

Reauthenticate to the Wifi using W:M:F

Bonus - Using W:M:F right here!

Reauthenticate to the Wifi using W:M:F

  • Check whether http://google.it is reachable

  • if not

  • Switch off the SOCKS proxy

  • Connect to http://google.it

  • Enter credentials

  • Submit (does some Javascript)

  • Launch PuTTY for ssh tunneling

  • Re-enable SOCKS proxy

FF Settings

 1:  # Get Firefox settings
 2:  my $prefs = $mech->repl->expr(<<'JS');
 3:  Components.classes["@mozilla.org/preferences-service;1"]
 4:    .getService(Components.interfaces.nsIPrefBranch);
 5:  JS

FF Proxy Settings

 1:  # Get Firefox settings
 2:  my $prefs = $mech->repl->expr(<<'JS');
 3:  Components.classes["@mozilla.org/preferences-service;1"]
 4:    .getService(Components.interfaces.nsIPrefBranch);
 5:  JS
 6:
 7:  # Switch off the SOCKS proxy
 8:  if ($prefs->getIntPref('network.proxy.type') != 0) {
 9:      $prefs->setIntPref('network.proxy.type',0);
10:  };

Reauthenticate to DevItalia

 1:  $mech->get('http://google.it');
 2:  if ($mech->title =~ /\bdevitalia\b/i) {
 3:    # We need to log in
 4:    print "Reauthenticating";
 5:    $mech->field( User_tmp => $credentials->{user} );
 6:    $mech->field( Password => $credentials->{pass} );
 7:    $mech->click({ xpath => q{//input[@type="submit"]}, sync => 1 });
 8:  } else {
 9:    print "Already logged in"
10:  };

Switch proxy back on

 1:  $mech->get('http://google.it');
 2:  if ($mech->title =~ /\bdevitalia\b/i) {
 3:    # We need to log in
 4:    print "Reauthenticating";
 5:    $mech->field( User_tmp => $credentials->{user} );
 6:    $mech->field( Password => $credentials->{pass} );
 7:    $mech->click({ xpath => q{//input[@type="submit"]}, sync => 1 });
 8:  } else {
 9:    print "Already logged in"
10:  };
11:
12:  # Switch on the SOCKS proxy
13:  $prefs->setIntPref('network.proxy.type',1);