Articoli Manifesto Tools Links Canali Libri Contatti ?
Linguaggi / Perl

Perl web automation (seconda parte)

Abstract
Grazie ad alcuni moduli Perl vedremo come sia semplice creare (registrare) degli script per automatizzare l'accesso a risorse on-line. Le applicazioni sono molteplici, dal controllo periodico della vostra casella di web-mail, mandare sms on-line, fino alla registrazione di una serie di macro per il testing di una web application e molto altro.
Data di stesura: 20/02/2005
Data di pubblicazione: 18/03/2005
Ultima modifica: 04/04/2006
di Marco Lamberto Discuti sul forum   Stampa

Web testing

Nella parte precedente[4] abbiamo visto come realizzare degli script per simulare e quindi automatizzare l'interazione con un sito web. In questa seconda parte vedremo come ridurre al minimo l'intervento di natura programmativa per generare gli script stessi.

È indubbio che operare realmente su un sito da testare, visitare la nostra web-mail, etc. sono tutte azioni più comode e veloci da realizzare con un mouse che non scrivendo il codice.

Quando tuttavia un'operazione particolare diventa ripetitiva, magari con una frequenza costante o comunque elevata, può diventare utile semplificarsi la vita e trovare qualcuno che lo faccia per noi. In alternativa alla persona fisica c'è sempre il nostro calcolatore che è decisamente adatto a fare operazioni in maniera iterativa e soprattutto non si stanca (al massimo scalda un po' più del solito!).

Registrare

Premessa la volontà di non realizzare manualmente tutte le righe di codice perché l'agente LWP::UserAgent o WWW::Mechanize facciano le operazioni volute, la sola strada percorribile è intercettare e registrare l'attività di un utente reale sull'interfaccia web voluta.

Successivamente sarà possibile la modifica e la parametrizzazione di alcune parti dell'elenco di operazioni ottenuto.

HTTP::Proxy

Intercettare, interporsi, sono compiti che un proxy fa per definizione! Il primo modulo modulo che useremo sarà proprio un oggetto che ci permette di realizzare dei proxy. La sintassi è semplice e sono una manciata i metodi che interessano per il nostro scopo.

L'esempio successivo mostra un piccolo script per creare un proxy HTTP che risponda alla porta 9876.

  1. use HTTP::Proxy; 
  2.  
  3. my $proxy = HTTP::Proxy->new; 
  4. $proxy->port(9876); 
  5. $proxy->start; 
Sintesi estrema, il tutto potrebbe essere condensato ad un comando impartibile da un prompt di shell:
perl -MHTTP::Proxy -e 'HTTP::Proxy->new(port => 9876)->start'
Il proxy è pronto, ma così com'è ci serve ben poco, raccoglie le richieste dei client, le inoltra autonomamente, ritorna i dati e nulla più.
[Figura 1]

Figura 1

HTTP::Proxy opera le richieste tramite una propria istanza di LWP::UserAgent, è possibile sostituirla tramite il metodo agent di HTTP::Proxy con un altro oggetto, la cui classe sia derivata da LWP::UserAgent.

HTTP::Recorder

Un'istanza di HTTP::Recorder può essere utilizzata allo scopo. Il modulo in questione marca il documento HTML ritornato da una richiesta in modo da potersi accorgere quali links vengano seguiti o quali forms inviati.

Di default registra le azioni in codice Perl adatto all'esecuzione con WWW::Mechanize, nel particolare presuppone l'esistenza di un'istanza con nome $agent.

HTTP::Recorder permette di specificare un file di destinazione in cui salvare gli eventi registrati (n.b. lo script viene aperto in modalità "append", se esiste già non viene sovrascritto ma le nuove righe verranno aggiunte in coda).

Bastano poche righe ed il proxy per registrare è pronto:

  1. #!/usr/bin/perl -w 
  2.  
  3. use strict; 
  4. use HTTP::Proxy; 
  5. use HTTP::Recorder; 
  6.  
  7.  
  8. my $proxy = HTTP::Proxy->new; 
  9. my $agent = HTTP::Recorder->new; 
  10.  
  11. $agent->file('session.pl'); 
  12.  
  13. $proxy->port(8080); 
  14. $proxy->agent($agent); 
  15. $proxy->start; 
Per provarlo ho eseguito il browser testuale lynx e registrato una ricerca con Google.
$ ./recorder0.pl &
$ export http_proxy=http://localhost:8080
$ lynx http://www.google.com
Quello che segue è il file session.pl generato:
  1.  
  2. $agent->get("http://www.google.com/"); 
  3.  
  4. $agent->get("http://www.google.it/cxfer?c=PREF%3D:TM%3D1109256170:S%3D861XClBC

    3FksuGrw&prev=/"); 
  5.  
  6. $agent->get("http://www.google.it/"); 
  7. $agent->form_name("f"); 
  8. $agent->field("hl", "it"); 
  9. $agent->field("ie", "ISO-8859-1"); 
  10. $agent->field("q", "ginko biloba"); 
  11. $agent->submit_form(form_name => "f"); 

Nel file una linea vuota separa tutti gli eventi relativi ad una specifica pagina dai precedenti.

A questo punto il file ottenuto può essere epurato dalle operazione spurie ed eventualmente parametrizzato, in questo esempio si potrebbe sostituire l'argomento della query "ginko biloba" con una variabile.

Nota: suggerisco vivamente l'uso della versione di sviluppo di HTTP::Recorder, che al momento è la 0.03_01. La versione stabile è invero afflitta da alcuni bugs sui forms e non supporta l'uso di SSL.

Riproduzione e testing

Con qualche riga in più del programma precedente possiamo scrivere un semplice esecutore di sequenze:
  1. #!/usr/bin/perl -w 
  2.  
  3. use strict; 
  4. use WWW::Mechanize; 
  5.  
  6.  
  7. unless ($#ARGV == 0) { 
  8.   print STDERR <<"EOT"; 
  9. usage: $0 [sessionfile] [...] 
  10. EOT 
  11.   exit 1; 
  12.  
  13.  
  14. my $agent = WWW::Mechanize->new( 
  15.   keep_alive  => 1, 
  16.   agent       => 'SIBot/1.2', 
  17.   autocheck   => 1, 
  18. ); 
  19.  
  20. $agent->env_proxy; 
  21.  
  22.  
  23. print "starting\n"; 
  24. local *IS; 
  25. local $\ = undef; 
  26. foreach (@ARGV) { 
  27.   print "  $_ ... "; 
  28.   open(IS, "< $_") or die $!; 
  29.   eval <IS>; 
  30.   close IS; 
  31.   print $@ ? 'error' : 'passed'; 
  32.   print "\n"; 
  33. print "all done\n"; 
L'esempio è piuttosto semplice, prende come argomenti dei file generati con HTTP::Recorder e li esegue sequenzialmente dopo aver istanziato WWW::Mechanize. Il contenuto degli script viene eseguito tramite la funzione di eval, in caso di errore viene mostrato un messaggio di test non passato, come in una sorta di HTTP-unit "povero".
$ ./player0.pl session.pl 
starting
  session.pl ... passed
all done

Conclusioni

Certamente il modulo HTTP::Recorder non sarà la soluzione completa per tutti resta tuttavia indubbia di questo strumento che in una manciata di righe permette di risparmiare gran parte del tempo normalmente dedicato alla generazione manuale di sequenze di test.

Perl è ormai disponibile su moltissime piattaforme e, come abbiamo potuto vedere in questi primi articoli, non fa solo CGI e manipolazione di testi!

Informazioni sull'autore

Marco Lamberto, laureato in Informatica presso la Statale di Milano, con diversi anni di esperienza sistemistica, di sicurezza e sviluppo prevalentemente in ambienti UNIX (Linux in primis) con linguaggi come C, Java, Perl, PHP, XML, HTML, ...

È possibile consultare l'elenco degli articoli scritti da Marco Lamberto.

Altri articoli sul tema Linguaggi / Perl.

Discuti sul forum   Stampa

Cosa ne pensi di questo articolo?

Discussioni

Questo articolo o l'argomento ti ha interessato? Parliamone.