Interagire con il web

Ci sono due moduli principali per leggere i dati dagli URL in Python: urllib e urllib2. In questo capitolo vedremo come utilizzare urllib2 in quanto è molto più completo, anche se urllib dispone di funzioni specifiche che non possono essere trovati in urllib2, quindi si vedrà di volata.

urllib
urllib è in grado di leggere dati da un URL utilizzando diversi protocolli come HTTP, HTTPS, FTP o Gopher.
La funzione urlopen viene utilizzata per creare un oggetto simile a file con cui leggere l’URL. Questo oggetto dispone di metodi come read, readline, readlines e close, che lavorano esattamente come gli oggetti di tipo file, ma in realtà stiamo lavorando con un wrapper che astrae un socket utilizzato al di sotto.
Il metodo read, come si è visto, permette di leggere il “file” completo o il numero di bytes specificato come parametro, readline per leggere una riga e readlines per leggere tutte le linee e restituire una lista con loro.
Possiamo contare anche con un paio di metodi: getURL, per ottenere l’URL da cui stiamo leggendo (che può essere utile per controllare se ci fosse un redirect); e info che restituisce un oggetto con le intestazioni di risposta dal server (che anche è possibile accedere utilizzando l’attributo headers).
		import urllib2
		try:
		    f = urllib2.urlopen("http://www.python.org")
		    print f.read()
		    f.close()
		except HTTPError, e:
		    print "Si è verificato un errore"
		    print e.code
		except URLError, e:
		    print "Si è verificato un errore"
		    print e.reason
Quando si lavora con urllib2 possiamo trovare, come vedremo, con errori di tipo URLError. Se lavoriamo con HTTP possiamo trovare anche errori della sottoclasse di URLError o HTTPError, che vengono lanciati quando il server restituisce un codice di errore HTTP, come per esempio error 404, quando non trova la risorsa. Possiamo anche incontrare errori lanciati dalla libreria urllib2 che utilizza al di sotto per i trasferimenti HTTP: httplib, o con eccezioni lanciate dal modulo dallo stesso socket.
La funzione urlopen conta con un parametro opzionale data con il quale inviare informazioni a indirizzi HTTP (e solo HTTP) utilizzando POST (i parametri vengono inviati nella stessa domanda), per esempio in risposta ad una form. Questo parametro è una stringa codificata correttamente, seguendo il formato utilizzato nelle URLs:
		‘password=complicata&utente=pippo’
Il modo più semplice per codificare la stringa è utilizzare il metodo urlencode di urllib, che accetta un dizionario o una lista di tuple (chiave, valore) e genera la stringa corrispondente codificata:
		import urllib, urllib2
		params = urllib.urlencode({"utente": "pippo",
   "password": "complicata"})
		f = urllib2.urlopen("http://esempio.com/login", params)
Se quello che vogliamo fare è scaricare il contenuto di un URL ad un file locale, possiamo usare la funzione urlretrieve di urllib al posto di leggere da un oggetto creato con urlopen e scrivere i dati letti.
La funzione urlretrieve prende come parametri l’URL da scaricare ed eventualmente un parametro filename con il percorso locale per salvare il file, un parametro data simile a urlopen e un parametro reporthook con una funzione da utilizzare per segnalare il progresso.
Fatta eccezione nelle volte quando si utilizza il parametro data, le connessioni vengono sempre realizzati utilizzando GET (i parametri che vengono passati nella URL). Per inviare i dati utilizzando GET basta concatenare la stringa risultante dal urlencode con l’URL utilizzando il simbolo ?.
		params = urllib.urlencode({"utente": "pippo",
		                           "password": "complicata"})
		
		f = urllib2.urlopen("http://esempio.com/login" + "?" + params)
Con urllib si utilizza anche la funzione urlopen per creare i nostri pseudo-file, ma a differenza della versione di urllib, la funzione urlopen di urllib2 può anche prendere come parametro un oggetto Request al posto dell’URL e i dati da inviare.
La classe Request definisce oggetti che incapsulano tutte le informazioni relative a una richiesta. Attraverso questo oggetto è possibile eseguire delle query o interrogazioni più complesse, aggiungendo i nostri propri header, come User-Agent.
Il più semplice costruttore per l’oggetto Request non prende che una stringa che indica l’URL a cui connettersi, quindi utilizzare questo oggetto come un parametro urlopen sarebbe equivalente a usare una stringa con l’URL direttamente.
Tuttavia il costruttore Request ha anche come parametri opzionali una stringa data per inviare i dati in modo POST e un dizionario headers con le intestazioni (più un paio di campi origin_req_host e unverifiable, che vanno al di là del proposito di questo capitolo, anche perché è poco utilizzato).
Vediamo come aggiungere i nostri header personalizzati utilizzando come esempio l’intestazione User-Agent. User-Agent è un’intestazione che identifica il browser e sistema operativo che stiamo utilizzando per connettersi a tale URL. Per impostazione predefinita urllib2 si identifica come “Python-urllib/2.5“; se vogliamo identificarci come un Linux girando sotto Konqueror, ad esempio, dovremmo utilizzare un codice simile al seguente:
		ua = "Mozilla/5.0 (compatible; Konqueror/3.5.8; Linux)"
		h = {"User-Agent": ua}
		r = urllib2.Request("http://www.python.org", headers=h)
		f = urllib2.urlopen(r)
		print f.read()
Per personalizzare il modo in cui funziona urllib2 possiamo installare un gruppo di gestori (handlers), raggruppati in un oggetto della classe OpenerDirector (opener o apritore), che sarà quello utilizzato da quel momento per chiamare a urlopen.
Per costruire un opener si utilizza la funzione build_opener al quale vengono passati i gestori che faranno parte dell’opener. L’opener sarà responsabile di concatenare l’esecuzione dei vari gestori nell’ordine indicato. È inoltre possibile utilizzare il costruttore OpenerDirector e aggiungere i gestori usando il suo metodo add_handler.
Para instalar el opener una vez creado se utiliza la función install_opener, que toma como parámetro el opener a instalar. También se podría, si sólo queremos abrir la URL con ese opener una sola vez, utilizar el método open del opener.
urllib2 conta con dei handlers che si occupano di gestire gli schemi disponibili (HTTP, HTTPS, FTP), gestire l’autenticazione, i reindirizzamenti, ecc.
Per aggiungere l’autenticazione dobbiamo installare un opener che includa come gestore HTTPBasicAuthHandler, ProxyBasicAuthHandler, HTTPDigestAuthHandler e/o ProxyDigestAuthHandler.
Per utilizzare l’autenticazione HTTP di base si userebbe, ad esempio:
		HTTPBasicAuthHandler:
		    aut_h = urllib2.HTTPBasicAuthHandler()
		    aut_h.add_password("realm", "host", "utente", "password")
		    opener = urllib2.build_opener(aut_h)
		    urllib2.install_opener(opener)
		
		f = urllib2.urlopen("http://www.python.org")
Se vogliamo specificare un proxy nel codice dovremmo usare un opener che contenesse un gestore ProxyHandler. Il gestore di default include un’istanza di ProxyHandler costruita chiamando all’inizializzatore senza parametri e che legge l’elenco dei proxies da utilizzare nella variabile di ambiente appropriata. Ma possiamo anche costruire un ProxyHandler passando come parametro all’inizializzatore un dizionario le cui chiavi sono i protocolli e i valori, l’URL del proxy da utilizzare per tale protocollo.
		proxy_h = urllib2.ProxyHandler({"http" : "http://mioproxy.net:123"})
		opener = urllib2.build_opener(proxy_h)
		urllib2.install_opener(opener)
		f = urllib2.urlopen("http://www.python.org")
Al fine di mantenere i cookies che invia HTTP utilizziamo il gestore HTTPCookieProcessor.
		cookie_h = urllib2.HTTPCookieProcessor()
		opener = urllib2.build_opener(cookie_h)
		urllib2.install_opener(opener)
		f = urllib2.urlopen("http://www.python.org")
Se vogliamo accedere a questi cookies o per poter inviare i propri cookies, è possibile passare come parametro all’inizializzatore HTTPCookieProcessor un oggetto di tipo CookieJar del modulo cookielib.
Per leggere i cookies inviati è sufficiente creare un oggetto iterable da CookieJar (potremmo anche cercare le intestazioni corrispondenti, ma questo sistema è più chiaro e semplice):
		import urllib2, cookielib
		cookie_j = cookielib.CookieJar()
		cookie_h = urllib2.HTTPCookieProcessor(cookie_j)
		opener = urllib2.build_opener(cookie_h)
		opener.open("http://www.python.org")
		for num, cookie in enumerate(cookie_j):
		    print num, cookie.name
		    print cookie.value
		    print
Nel caso improbabile di avere bisogno di aggiungere un cookie prima di effettuare la connessione, invece di connetterci per farla mandare dal sito, possiamo utilizzare il metodo di set_cookie di CookieJar, per passarli un oggetto di tipo Cookie. Il costruttore Cookie, tuttavia, è piuttosto complicato.


Similari
Overloading di metodi in Java
12% Java
Un metodo overload viene utilizzato per riutilizzare il nome di un metodo ma con argomenti diversi, opzionalmente con un differente tipo di ritorno. [expand title=”Regole per overload” startwrap=”” endwrap=”” excerpt=”⤽” s…
Modi di fare e di non fare in Python
11% Python
Questo documento può essere considerato un compagno del tutorial di Python. Viene illustrato come utilizzare Python, e quasi ancora più importante, come non usare Python. [expand title=”Costrutti del linguaggio che non dov…
redirect 301 usando mod_alias
9% Server
mod_alias è fondamentalmente la versione più semplice di mod_rewrite. Non può fare le cose che fa mod_rewrite, ad esempio modificare la stringa di query. Per eseguire reindirizzamenti nel server web Apache è possibile di u…
Installare Python e Django su Windows
8% Django
Quando ci riferiamo allo sviluppo web con Python, la prima cosa che viene in mente è usare un qualche framework. Il più famoso e utilizzato da tutti è il Django, ma non è l’unico. Ci sono Pylons, Grok, TurboGears e Zope: t…
Metodi magici e costanti predefinite in PHP
8% Php
PHP fornisce un insieme di costanti predefinite e metodi magici per i nostri programmi. A differenza delle normali costanti i quali si impostano con define(), il valore delle costanti predefinite o speciali dipendono da do…