Da quando sono diventato un pendolare (per lavoro), ho iniziato a (ri)frequentare assiduamente le stazioni ferroviarie e i treni di Trenitalia.
Dopo un paio di settimane passate sui treni, mi sono accorto di un servizio interessante: il sito Viaggiatreno: il sito contiene le informazioni sui treni (informazioni in tempo reale sullo stato di un treno come ritardo o anticipo, ora prevista di arrivo e fermate già effettuate).
Esigenza
Dopo aver provato il disagio di un treno soppresso (e quindi essermi svegliato un’ora prima per stare un’ora ad aspettare in stazione), mi sono reso conto di poter, perlomeno, arginare il problema se si fosse presentato in futuro; conoscere lo stato del treno direttamente sul telefonino mi permetterebbe, la mattina, di poter scegliere un mezzo alternativo senza recarmi in stazione nel caso in cui il treno sia in ritardo o soppresso. Oppure, se il treno è in anticipo, di accelerare i tempi.
Soluzioni esistenti
- Potrei controllare il sito Viaggiatreno accedendo il computer, connettendomi a Internet e andando sul sito Viaggiatreno. Contro: il tempo richiesto è troppo (~ 5 minuti. E la mattina anche 5 minuti sono preziosissimi).
- Potrei installare su iPhone l’applicazione ProntoTreno, un’applicazione che fornisce lo stato di tutti i treni in tempo reale. Contro: il mio access point WIFI non è sempre attivo; non ho a disposizione la connessione 3G. Inoltre, se dovessi cambiare telefono per passare ad un telefono senza WIFI/3G, questa soluzione non è più applicabile.
L’idea
Il mezzo da utilizzare è sicuramente il mobile. L’incognita era semplicemente trovare il modo per raggiungere i telefoni, ed è stato individuato negli SMS, supportati da tutti i telefoni.
L’altro fattore da tenere in considerazione è: come ottenere i dati da Viaggiatreno? Il sito utilizza Flash, ed estrarre informazioni testuali e puntuali da Flash penso sia infattibile. La soluzione è presto trovata: fortunatamente, Viaggiatreno offre anche una versione mobile, realizzata in (X)HTML, per la gioia dei parser.
La realizzazione
Per la realizzazione del servizio abbiamo bisogno di:
- Un server Linux attivo e connesso a Internet durante il lasso di tempo in cui vogliamo essere avvisati via SMS. Inoltre, il server Linux deve avere installato crontab, l’interprete python e alcuni pacchetti python che vedremo più avanti.
- Un servizio per mandare SMS gratuitamente: io mi appoggio a virgilio.it, che mi permette di ricevere via sms tutte le email ricevute all’indirizzo indirizzo@sms.tin.it [per i più impazienti: in questo modo per ricevere SMS è sufficiente mandare una mail]. Se invece non potete usare virgilio.it, vi raccomando di utilizzare MoioSMS per l’invio gratuito di SMS.
- Un account GMail da cui mandare la mail del punto sopra (se siete degli smanettoni, non avete bisogno di questo e potrete usare il vostro SMTP, a patto di sostituirlo nel codice).
- Un telefono mobile abilitato alla ricezione di SMS e attivo (ovviamente!)
- Il numero del treno di nostro interesse: per conoscere il numero del treno, è sufficiente andare su TreniItalia, immettere partenza e arrivo e annotarsi il numero del treno. Il numero del treno è unico e non cambia.
- Lo script python seguente, che ho scritto in Python utilizzando le librerie python-mechanize e python-beautifulsoup (installatele seguendo la guida per la vostra distribuzione. Per Ubuntu/Debian ho usato apt-get install python-mechanize python-beautifulsoup). Il codice è ancora immaturo, ma funziona (vedi screenshot):
“`
#! /usr/bin/pythonimport BeautifulSoup
import mechanize
import smtplib
import time
import datetime
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email import Encoders
import os
import sysgmail_user = "gmail username"
gmail_pwd = "gmail pass"def mail(to, subject, text):
msg = MIMEMultipart()msg['From'] = gmail_user
msg['To'] = to
msg['Subject'] = subjectmsg.attach(MIMEText(text))
mailServer = smtplib.SMTP("smtp.gmail.com", 587)
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(gmail_user, gmail_pwd)
mailServer.sendmail(gmail_user, to, msg.as_string())
mailServer.close()numtreno = sys.argv[1]
stazione = sys.argv[2]tobeparsed = mechanize.urlopen(str(str('https://mobile.viaggiatreno.it/viaggiatreno/mobile/scheda?numeroTreno=') + str(numtreno) + str('&tipoRicerca=numero&lang=IT')))
f = BeautifulSoup.BeautifulSoup(tobeparsed)
f = f.prettify()
f = f[f.find('<!– SITUAZIONE –>'):]
f = f[:f.find('</div>')]
s1 = f[f.find('<strong>')+len('<strong>'):f.find('<br />')]
s2 = f[f.rfind('–>')+len('–>'):f.find('</strong>')]
s1 = s1.replace(''',"'")
s1 = s1.split()
s2 = s2.split()
tobeparsed = mechanize.urlopen(str(str('https://mobile.viaggiatreno.it/viaggiatreno/mobile/scheda?dettaglio=visualizza&numeroTreno=') + str(numtreno) + str('&tipoRicerca=numero&lang=IT')))
f = BeautifulSoup.BeautifulSoup(tobeparsed)
f = f.prettify()
f = f[f.find(stazione):]
f = f[:f.find("</div>")]
arr1 = f[f.find('')+len('<p>'):f.find('<br />')]
or1 = f[f.find('<strong>')+len('<strong>'):f.find('</strong>')]
arr = f[f.rfind('<p>'):f.rfind('</p>')]
arr2 = arr[arr.find('<p>')+len('<p>'):arr.find('<br />')]
or2 = arr[arr.find('<strong>')+len('<strong>'):arr.find('</strong>')]
arr1 = arr1.split()
or1 = or1.split()
arr2 = arr2.split()
or2 = or2.split()
arr1.extend(or1)
arr2.extend(or2)L = [s1, s2, arr2]
for i in xrange(len(L)):
L[i] = ' '.join(L[i])
message = '\n'.join(L)mail("indirizzo@sms.tin.it",
sys.argv[1],
message,
)
“`Il codice estrae le informazioni di interesse da Viaggiatreno mobile (come detto, per fare il parsing occore usare il sito in versione mobile) come lo stato corrente del treno (posizione ed eventuali minuti di ritardo o anticipo) e l’orario di arrivo previsto e manda queste informazioni all’indirizzo mail “speciale” che gira il messaggio al mio numero di cellulare via SMS [per l’invio della mail il servizio usa GMail]. Come detto, potreste usare MoioSMS (via pipe o python import) semplicemente sostituiendo la parte di invio della mail.
Come si utilizza?
- Lo script accetta due parametri da command-line: il numero di treno a cui siete interessati e la stazione di cui volete conoscere l’orario di arrivo stimato (es. “LECCO MAGGIANICO”).
- Modificate, nello script le variabili gmail_user e gmail_password con le credenziali del vostro account GMail che useremo per spedire la mail verso l’indirizzo speciale che girerà le mail in SMS. Sempre nel codice, sostituite appunto indirizzo@sms.tin.it con il vostro indirizzo “speciale” che tramuta il messaggio e-mail in SMS.
- Usando crontab, inserite una entry del tipo:
08 07 * * 1-5 python /home/mbologna/parser.py 5033 “LECCO MAGGIANICO”
Per avere un aggiornamento via SMS alle 07:08 di tutti i giorni feriali del treno 5033 specificando che deve fornirci l’orario di arrivo previsto alla stazione di “LECCO MAGGIANICO”.
Risultati
La mattina, prima di recarmi in stazione, controllo sul mio telefono e automaticamente ricevo 3 SMS gratuiti diversi contenenti lo stato del treno man mano che si avvicina alla stazione in cui io salgo sul treno. In questo modo, ancora prima di uscire di casa, posso sapere se il treno è in ritardo o se è stato soppresso.
Qui accanto, la testimonianza di 2 degli SMS che ricevo quotidianamente.
Sviluppi futuri
- Miglioramento del codice di download/parsing
- Integrazione con MoioSMS
Curiosità
- Un servizio simile sarà implementato da Trenitalia a settembre 2010
- Tutti i link verso Trenitalia presenti in questo post sono nofollow.
Ciao Michele, basandomi sul tuo studio ho realizzato un’altra implementazione della funzione di web scraping da ViaggiaTreno: http://blog.andrearota.com/2011/03/web-scraping-con-python.html
Molto interessante; bravo!
Questa è davvero interessante!! Ma, giusto per capire, tu hai un pc a casa che fa da server e rimane sempre acceso?
Non a casa; amministro un server che uso a questo scopo.
Grazie per il post molto utile, se puo essere di aiuto
ho aggiunto anche una funzione trovata sulla rete che
permette l’ivio di sms struttando google calendar ed il suo reminder via sms.
Qundi ricevere sms sullo stato dei treni in forma gratuita a prescindere dal fornitore di servizi di telefonia.
https://support.google.com/calendar/answer/45351?hl=en
Grazie: un possibile ulteriore sviluppo potrebbe essere quello di integrare la mia soluzione per usare gli sms di Google Calendar
Fantastico!
Se sei sempre il migliore Michy!!!
Bravo! Mi piace!