Accesso utente

Calendar

«  
  »
L M M G V S D
 
1
 
2
 
3
 
4
 
5
 
6
 
7
 
8
 
9
 
10
 
11
 
12
 
13
 
14
 
15
 
16
 
17
 
18
 
19
 
20
 
21
 
22
 
23
 
24
 
25
 
26
 
27
 
28
 
29
 
30
 
 
 
 
 
Add to calendar

Chi è on-line

Ci sono attualmente 0 utenti e 2 visitatori collegati.
Home | Forum | Associazione | Idee, spunti e riflessioni

Infoclick.pl - script recupero dati passaggio autobus

Ciao,
abbiamo realizzato questo breve script in perl per recuperare dal servizio infoclick di ANM gli orari di passaggio dei bus da una data fermata. Si è reso necessario l'utilizzo della libreria perl WWW::mechanize invece che curl o wget con metodi post o get perchè il form esposto dall'ANM (www.anm.it/default.aspx , in asp..) richiede dei parametri hidden che sono elaborati da un javascript client side, insomma un bordello. WWW::mechanize astrae un browser, il riempire form e cliccare pulsanti, e restituisce risultati.
Lo script deve essere lanciato inserendo come parametro il numero della fermata, che può essere recuperato o leggendo sulla fermata stessa o cercando su www.anm.it/default.aspx.
Un esempio vale più di mille parole:
gianfi@shadow ~ $ ./infoclick.pl 2048
NAPOLI-VIA-BIXIO NINO-FR. CIV. 6625/01/2011 ore: 07:07:56
Fermata 2048

Linea 181 19:34
Sulla fermata transitano: 181ATTENZIONE esistono eventi speciali per le Linee:181-

L'output va un pò ripulito però, insomma, si capisce quello che fa.
Ora, stavo pensando a scrivere una applet per avere le informazioni direttamente sul desktop; una applet per gnome, o qualcos'altro del genere. Idee?

Segue lo script. Grazie a vito e coky per il supporto morale e tecnico.

#!/usr/bin/perl
#Recupero Dati infoclick ANM
#parametri: numero palina
#

use HTTP::Cookies;
use WWW::Mechanize;
use CGI;
#numero fermata da command line
$numeropalina = $ARGV[0];
#$numeropalina = '2480';
$mech = WWW::Mechanize->new();

$url = 'http://www.anm.it/default.aspx';
$mech->get( $url );

$mech->submit_form(
form_name => 'form1',
button => 'BtnInviaDati',
fields => {
TxTNumeroPalina => $numeropalina
}
);

if ( $mech->content( format => 'text' ) =~ m/Previsioni/)
{
print 'Non ti è dato sapere';
} else {
$testo = $mech->content( format => 'text' );
@datifermata = split(/minuto/, $testo);
print "$datifermata[1]\n";
}

Comodo! E' possibile creare

Comodo! E' possibile creare qualche sezione del sito in cui organizzare il codice scritto dai "co-lugghi" ?

metterei script in sezione download

Credo che basti aprire un thread apposito nel forum, e linkare gli script nella sezione download.
Così eventuali commenti, migliorie, etc. si autodocumentano.
Mi sembra la soluzione con più elevato grado di sfaticataggine: il mio preferito Keep It Slack, Stupid.

/home/kiss

/home/giuseppe

YAPC (Yet Another Perl Class) ANM::Info

Salve a tutti,
mi sono iscritto da pochi giorni e, facendo parte della community Perl, ho trovato interessante questo script e la funzionalità proposta, per cui faccio i miei complimenti :) Una piccola nota: nello script originario sono inseriti HTTP::Cookies e CGI che non vengono però utilizzati :)

Intanto alcuni suggerimenti di best practices. Usare sempre:
use strict;
use warnings;

che ci renderà manutenibile il codice, aiutandoci nello scope delle variabili e non solo, rendendo anche possibile lo sviluppo di una classe, ad uso di altri sviluppatori ;)

Proprio questo è l'approccio che ho avuto per l'implementazione di una soluzione alternativa:

- astrazione dell'interrogazione dall'uso dei dati. La classe ANM::Info restituisce un array con i dati letti dal portale ANM

- Nello script 'anm_reader.pl' istanzio un oggetto della classe ANM::Info da cui attingo le informazioni che vado ad elaborare per l'esigenza specifica

Nella fattispecie, anziché implementare un'applet (come proposto) per la lettura dei dati dal desktop, ho preferito esportare in comodo formato RSS2.0 per accedervi con il reader RSS preferito.

- Altra variazione: implementazione dei threads per aprire in modalità asincrona numerose connessioni al portale ANM, in modo da poter leggere più rapidamente i dati di più paline.

La logica è:
. script anm_reader.pl crea tante istanze quante sono le paline che desidero controllare
. script anm_reader.pl associa un thread ad ogni istanza e le fa partire 'contemporaneamente'

I risultati di output sono ordinati e scritti nel file RSS.
L'aggiornamento continuo dei dati dell'RSS è fornito tramite la sub start in modalità ricorsiva.

Ho uploadato sul mio hosting il codice indentato perchè non sono riuscito a far digerire in modo semplice l'indentazione all'editor: lo trovate qui http://www.netlogica.it/anm/anm.txt

Di seguito il codice della classe e dello script che la implementa:


package ANM::Info;

use strict;
use warnings;
use WWW::Mechanize;

our $VERSION = '0.02';

# costruttore
sub new {
my $class = shift;
my $init = shift;
my $self={};

bless $self,$class;

$self->number($init->{number});
return $self
}

# attributi
sub number {
my $self=shift;
if (@_) {
$self->{number}=shift
}
return $self->{number}
}
# end attributi
# end costruttore

# metodi
sub get_info {
my $self=shift;
my $mech=WWW::Mechanize->new();

$mech->get('http://www.anm.it/default.aspx');
$mech->submit_form(
form_name => 'form1',
button => 'BtnInviaDati',
fields => {
TxTNumeroPalina => $self->number
}
);

my $textPage=$mech->text();
my @row=split(/\n/,$textPage);

my ($indirizzo,$orario_richiesta,$fermata,$bus);
if ($row[1]) {
if ($row[1] =~ $self->number) {
$fermata=$row[1];
$fermata =~ s/\n|\r//g;

$indirizzo=substr($row[0],0,-25);
$indirizzo =~ s/Clicca per Aggiornare i risultati -->//;

$orario_richiesta=substr($row[0],-25);
$orario_richiesta =~ s/\n|\r//g;

my $previsione_autobus=$row[3];

if ($previsione_autobus =~ /non disponibili/) {
my @previsione=split(/\./,$row[3]);
$bus=$previsione[0]."\n".$previsione[1]
} else {
#qui devo parsare ad oltranza
my $i=3;
while ($row[$i]) {
$bus.=$row[$i];
$i++
}
}
if ($bus =~ /ATTENZIONE/) {
$bus =~ s/ATTENZIONE/\nATTENZIONE/;
$bus=substr($bus,0,-2)
}
}
} else {
$indirizzo='non pervenuto';
$orario_richiesta=' ';
$fermata=$self->number;
$bus=' '
}
return ($indirizzo,$orario_richiesta,$fermata,$bus)

}
# end metodi

1;

Quindi il codice dello script:


use strict;
use warnings;

use ANM::Info;
use threads qw(yield);
use threads::shared;

#main
my @paline=(2048,2500,2501,2532,2541);
start(0,@paline);
exit;
#end

sub start {
my $counter=shift;
my @paline=@_;

print 'Iterazione '.++$counter."\n";

my @results=readData(@paline);
makeRSS(@results);

sleep(10);
start($counter,@paline)
}

sub readData{
my @paline_da_controllare=@_;
my @results:shared;
my @thr;

for (@paline_da_controllare) {
push @thr,threads->new(sub
{
my $numero_palina=shift;
my $palina=ANM::Info->new({number => $numero_palina});
lock(@results);
push(@results,join('|',$palina->get_info));
threads->yield()
},
$_
);
}
for (@thr) {
$_->join()
}

my @information=@results;
return @information
}

sub makeRSS{
my @results=@_;
open my $fh,'>','anm.rss' or die $_;
print $fh "<?xml version=\1.0\ encoding=\"ISO-8859-1\"?>\n";
print $fh "\n";
print $fh " \n";
print $fh " ANM Information\n";
print $fh " http://www.anm.it\n";
print $fh " Info orari bus ANM\n";
print $fh " 1\n";
print $fh " \n";

for (@results) {
my @datiPalina=split(/\|/,$_);
my $indirizzo=$datiPalina[0];
my $orario_richiesta=$datiPalina[1];
my $fermata=$datiPalina[2];
my $bus=$datiPalina[3];

print $fh " \n";
print $fh " $fermata $indirizzo - $orario_richiesta\n";
print $fh " \n";
print $fh " $bus\n";
print $fh " \n";
print $fh " \n"
}
print $fh "\n";
close $fh
}

Spero di poter essere dei vostri alla prossima riunione, lavoro permettendo :)
Saluti

Mario aka Anak
anak@cpan.org

YAPC (Yet Another Perl Class) ANM::Info (2)

Devo confessare che oggi non avevo davvero voglia di lavorare e questa cosa delle paline mi ha divertito non poco :)
Così mi ci sono rimesso su, soprattutto perchè volevo verificare una cosa, che avevo assunto per buona:

Cito gianfi:

"Si è reso necessario l'utilizzo della libreria perl (Perl ndr) WWW::mechanize invece che curl o wget con metodi post o get perchè il form esposto dall'ANM ... in asp) richiede dei parametri hidden che sono elaborati da un javascript client side, insomma un bordello"

Questa cosa oggi ho deciso di verificarla anche perchè, diciamocela tutta, una protezione client side a me fa
rabbrividire e la cosa preoccupante è che dovrebbe far rabbrividire l'ANM... ma su come vengono assegnati certi lavori ce ne sarebbe da dire... evitiamo ed andiamo avanti.

In realtà lo script server side, evidentemente con un algoritmo digest di qualche forma applicato al content della pagina, produce una coppia di hash che valorizzano:

- __VIEWSTATE
- __EVENTVALIDATION

Ebbene è sufficiente prendere nota di questi valori ed inviarli tramite POST al server HTTP il quale riterrà autentica la richiesta (sempre, dico SEMPRE controllare il referrer) e leggere i risultati: la cosa notevole è che evitiamo l'uso di WWW::Mechanize che ha diverse dipendenze e che, in ogni caso, PRELEVERA' il form di immissione PER POI valorizzarlo e QUINDI sottometterlo. Con LWP::useragent invece saltiamo i primi due passaggi, inviando direttamente la request al server.

Ho anche ottimizzato - molto - la modalità di pulizia dei dati, ora compatta ed efficiente.
Resta attivo l'uso dei threads per aprire più connessioni e leggere con maggiore rapidità i dati di più paline.

Questo post, con gli script INDENTATI lo trovate anche su http://www.netlogica.it/anm/anm2.txt

Saluti e... buoni trasporti pubblici :)

Anak
anak@cpan.org

#--------------------------------------
#CLASSE ANM::Info
#--------------------------------------

package ANM::Info;

use strict;
use warnings;
use LWP::UserAgent;

our $VERSION = '0.05';

# costruttore
sub new {
my $class = shift;
my $init = shift;
my $self={};

bless $self,$class;

$self->number($init->{number});
return $self
}

# attributi
sub number {
my $self=shift;
if (@_) {
$self->{number}=shift
}
return $self->{number}
}
# end attributi
# end costruttore

# metodi
sub get_info {
my $self=shift;

use constant VIEWSTATE_VALUE => '/wEPDwUJMjI2NjkyMDEyD2QWAgIDD2QWBAIDD2QWAgIGD2QWAmYPZBYCAgIPEGQQFR8VU0FOIEdJT1JHSU8gQSBDUkVNQU5PCkNBU0FMTlVPVk8OU0FOIFNFQkFTVElBTk8HUE9MTEVOQQhQT1paVU9MSQZuYXBvbGkKQ0FMVklaWkFOTwZNYXBvbGkHTkFQJ09MSQpWSUxMQVJJQ0NBB0NBU09SSUEGUVVBUlRPDk1BU1NBIERJIFNPTU1BB1BPUlRJQ0kIRXJjb2xhbm8GbkFQT0xJBk5hcG9saQdNVUdOQU5PCFBPTExFTkEgBk5BUE9MSQZNQVJBTk8IRVJDT0xBTk8PVE9SUkUgREVMIEdSRUNPB0NFUkNPTEEGQUNFUlJBEE1BUkFOTyBESSBOQVBPTEkHTXVnbmFubwlQSVNDSU5PTEEFVk9MTEEJR0lVR0xJQU5PB05BUE9MSSAVHxVTQU4gR0lPUkdJTyBBIENSRU1BTk8KQ0FTQUxOVU9WTw5TQU4gU0VCQVNUSUFOTwdQT0xMRU5BCFBPWlpVT0xJBm5hcG9saQpDQUxWSVpaQU5PBk1hcG9saQdOQVAnT0xJClZJTExBUklDQ0EHQ0FTT1JJQQZRVUFSVE8OTUFTU0EgREkgU09NTUEHUE9SVElDSQhFcmNvbGFubwZuQVBPTEkGTmFwb2xpB01VR05BTk8IUE9MTEVOQSAGTkFQT0xJBk1BUkFOTwhFUkNPTEFOTw9UT1JSRSBERUwgR1JFQ08HQ0VSQ09MQQZBQ0VSUkEQTUFSQU5PIERJIE5BUE9MSQdNdWduYW5vCVBJU0NJTk9MQQVWT0xMQQlHSVVHTElBTk8HTkFQT0xJIBQrAx9nZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZGQCBQ9kFgICAw8QZGQWAGRkL00LYOqMxPIMwOENDyUlaV+ONH8=';
use constant EVENTVALIDATION_VALUE => '/wEWJALc2qlrAqbxmsMEAvX0s7ELApaa4PYOApuWsecNApOw9JULAoiC84AGAp3EjMQPAu2Z4MUBAoTLjMQPAt+6y5gIAuT5ocsKAuSo8a4FAq2iv9QPAvKDhacPApWh1OQIAoO80fgBAp279uEJAv3NjMQPAqW4+soFApOw9PAMAr2j9uEJAoyf4vUEAqO3/tgLArL9h5MMAtzwg9oGAuPC4B4Cq8SFtwICxa6txwQC98qYxwIC5rKg1gUCj73Zxg0Cr5HatwkC0vb2xw8C59vUsAMCt7ie6Q6ifGixHc5xjurbI6TV9eGDhQl8bw==';
use constant SERVER_ANM => 'http://www.anm.it/default.aspx';

my $ua=LWP::UserAgent->new();
$ua->agent('Mozilla/5.0');
$ua->timeout(15);

my ($res,$counter);
do {
$res=$ua->post(
SERVER_ANM,
Content => {
__VIEWSTATE => VIEWSTATE_VALUE,
__EVENTVALIDATION => EVENTVALIDATION_VALUE,
TxTNumeroPalina => $self->number,
BtnInviaDati => 'Invia Dati'
}
);
$counter++
} until ($res->is_success or $counter==3);

my ($indirizzo,$prossimi_passaggi,$altre_linee);

if ($res->is_success) {
my $text;
($indirizzo,$text)=cleanData('LabInfoFermata">','<\/b>',$res->content);
($prossimi_passaggi,$text)=cleanData('TabellaPaline">','<\/textarea>',$text);
($altre_linee,$text)=cleanData('LabPassaggiSuPalina">','<\/span>',$text)
} else {
$indirizzo='non pervenuto';
$prossimi_passaggi=' ';
$altre_linee=' '
}

return ($self->number,$indirizzo,$prossimi_passaggi,$altre_linee)
}

# end metodi

# funzioni interne

sub cleanData {
my $pattern1=shift;
my $pattern2=shift;
my $text=shift;

my @htmlBuffer0=split(/$pattern1/,$text);
my @htmlBuffer1=split(/$pattern2/,$htmlBuffer0[1]);

my $result=$htmlBuffer1[0];
my $textRemain=$htmlBuffer1[1];

return ($result,$textRemain)
}

# end funzioni interne

1;

#--------------------------------------
#SCRIPT ANM_READER CHE USA ANM::Info
#--------------------------------------
use strict;
use warnings;

use ANM::Info;
use threads qw(yield);
use threads::shared;

#main
my @paline=(2048,2500,2501,2532,2541);
start(0,@paline);
exit;
#end

sub start {
my $counter=shift;
my @paline=@_;

print 'Iterazione '.++$counter."\n";

my @results=readData(@paline);
makeRSS(@results);

sleep(5);
start($counter,@paline)
}

sub readData{
my @paline_da_controllare=@_;
my @results:shared;
my @thr;
for (@paline_da_controllare) {
push @thr,threads->new(sub
{
my $numero_palina=shift;
my $palina=ANM::Info->new({number => $numero_palina});
lock(@results);
push(@results,join('|',$palina->get_info));
threads->yield()
},
$_
);
}
for (@thr) {
$_->join()
}
my @information=@results;
return @information
}

sub makeRSS{
my @results=@_;
open my $fh,'>','anm.rss' or die $_;
print $fh "<?xml version=\1.0\ encoding=\"ISO-8859-1\"?>\n";
print $fh "\n";
print $fh " \n";
print $fh " ANM Information\n";
print $fh "
http://www.anm.it\n";
print $fh " Info orari bus ANM\n";
print $fh " 1\n";
print $fh "
\n";

for (@results) {
my @datiPalina=split(/\|/,$_);
my $fermata=$datiPalina[0];
my $indirizzo=$datiPalina[1];
my $prossimi_passaggi=$datiPalina[2];
my $altre_linee=$datiPalina[3];

print $fh " \n";
print $fh " $fermata $indirizzo\n";
print $fh " \n";
print $fh " $prossimi_passaggi\n";
print $fh " $altre_linee\n";
print $fh "
\n";
print $fh "
\n"
}
print $fh "\n";
close $fh
}

Ciao, _alla faccia mia_!

Ciao,
_alla faccia mia_! Complimenti, e grazie per il contributo. Pubblico il tuo script nella sezione downloads e metto una news sul sito. Ci vediamo presto in riunione!

"I love deadlines. I love the whooshing noise they make as they pass" - Douglas Adams

Che dire...

Che dire.. fantastico :)

There are 10 kinds of people. Those who understand binary notation, and those who do not.

Aggiornato script per avere direttamente su console i dati

Ciao Roberto,
ti ringrazio :)

All'uri seguente ho uploadato lo script aggiornato per rendere i risultati direttamente su console (si aggiorneranno circa due volte al minuto). L'elenco delle paline da controllare lo si inserisce comodamente in start.bh, per il resto non occorre 'toccare' nulla.

www.netlogica.it/anm/ANM-Info-0.06.tar.gz

Spero possa essere maggiormente usabile :)

Saluti

Anak

Ciao, è già pubblicato anche

Ciao,
è già pubblicato anche nella sezione downloads del sito. Entro oggi pubblico una news per renderlo visibile in home page.
Gianfilippo

Uploadato aggiornamento ANM::Info :)

Salve a tutti,

il messaggio circa l'app per leggere gli orari dei bus, mi ha ricordato che non avevo ancora uploadato l'aggiornamento della classe ANM::Info che permette la lettura degli orari con il pinguino preferito (a groppa di cammello).

 

La precedente ha funzionato solo per un mesetto poichè ANM cambia le chiavi di protezione con una frequenza che adesso ancora non so dirvi... probabilmente ogni 30, 40 giorni.

 

La classe aggiornata prima di effettuare l'interrogazione, si "procura" le giuste chiavi.

Anche lo script è migliorato (anm.pl): i risultati degli orari vanno in output a video nello stesso ordine con cui sono chiamati.

 

Non è banale poiché utilizzando i threads per velocizzare le interrogazioni, una per ogni thread, rendiamo il tutto asincrono e quindi "disordinato" in uscita.

 

Per il download: http://www.netlogica.it/anm/ANM-Info-0.12.tar.gz

 

Non incollo il source della classe poiché il forum taglia l'indentatura, rendendo il codice davvero poco leggibile,

per cui consiglio di vederlo direttamente dall'esplosione del tar.gz :)

 

Saluti

 

Anak

 

Novità dal mondo Open Source

Nel vasto mondo del software è davvero difficile districarsi, in particolar modo se la nostra attenzione cade sul tipo di licenza che accompagna quel particolare prodotto.
Per i sostenitori, gli amanti e gli utilizzatori di software open source - ma anche e soprattutto per chi è in procinto di migrazione da sistemi operativi chiusi - abbiamo scovato in rete dei siti davvero interessanti che si propongono come motori di ricerca per trovare alternative open ai software proprietari. Tra questi OS Alt, che mette ben in evidenza in home page...

swirl
Promo sponsor NaLUG
Sponsor : Kelyon

Wiki & How-To

Tomcat è un'application server: il suo compito è quello di fungere da contenitore di applicazioni sviluppate attraverso il linguaggio di programmazione Java. Esso viene impiegato generalmente per i web services e questa sua attitudine, in caso di applicazioni critiche, deve essere...

swirl