Fondamenti di Programmazione

Web

In questa lezione dimostreremo come usare semplici funzioni Python per leggere dati dal Web. Questa lezione non sarà per nulla esaustiva, ma serve per dare degli esempi di cose semplici da fare in Python.

Errata: Per salvare le immagini, aprire il file in modalità 'wb'. Le note al seguito sono aggiornate.

Url

Sul Web, le risorse sono identificate da un URL, Uniform Resource Locator. Un esempio di URL è http://en.wikipedia.org/wiki/Uniform_resource_locator. Lo URL è simile al nome di un file ed è composto da tre parti: lo schema http://, il nome del dominio en.wikipedia.org e il nome della risorsa /wiki/Uniform_resource_locator. L'URL diventa più complicato per siti dove l'utente può interagire come Google, dove lo URL contiene anche i parametri i ricerca. Per il momento focalizziamoci su URL semplici.

Accedere a URL

In Python si può accedere a molte pagine web direttamente usando la libreria urilib2 della librearia standard. Ad esempio, per scaricare una pagina dal sito di Python e stampare l'HTML bast fare:

import urllib2
f = urllib2.urlopen('http://python.org/')
print f.read()

Per scaricare un'immagine e salvarla su disco basta fare:

f = urllib2.urlopen(urlimmagine)
with open('python-logo.png', 'wb') as w:
    w.write( f.read() )

Ad esempio, se si fa girare il codicie precedente con URL http://www.python.org/community/logos/python-logo.png, si può salvare l'immagine

Web Crawling

Per copiare interi siti Web, possiamo semplicemente seguire i link trovati su una pagina e copiare tutte le pagine a partire da una sorgente. Questo si chiama web crawling ed è fatto dai search engine per craersi una copia di Internet per eseguire la ricerca (come avevmo fatto sui libri). Ad esempio, un semplicissimo crawler inizia da una pagina scaricata con urllib2, ne legge l'HTML e lo memorizza usando le classi introdotte in precedenta, lista i link, e mette i link in una lista da scaricare. Con gli ingredienti che abbiamo dato nel corso, scrivere una crawler è semplicissimo.

Unicode

Una cosa da notare è che tutti i siti Web possono avere testo scritto in qualunque. L' ASCII supporta solo i caratteri per la lingua inglese (senza accenti). Per lavorare sul Web ci serve un modo per codificare i caratteri presenti in tutti le lingue del mondo.

In Python, il tipo unicode supporta la codica in qualunque lingua. VAriabili di tipo unicode supportano le stesse operazioni delle stringhe, quindi il codice non cambia in modo significativo. Quello invece che cambia è come accedere a testo unicode salvato in file (su disco o sul Web). Per salvare i caratteri dove accordarci su una codica, simile all'ASCII. Sfortunatamente, esistono tante varianti di unicode cosa che rende frustrante lavorare su file in lingue diverse. Quella più comune però è chiamata UTF8, simile all'ASCII. In Python, possiamo leggere un file in formato unicode e riscriverlo specificando in modo esplicito la codifica.

# legge da un file utf8, memorizza in una variabile unicode 
with open('filein.txt','r') as f:
    text = f.read().decode('utf8')
# scrive una variabile unicode, in un file utf8 
with open('fileout.txt','w') as f:
    f.write(text.encode('utf8'))

APIs

Mentre è possibile accedere a pagine e immagini statiche usando urllib2, molti siti moderni usano il Web solo come interfaccia per accedere a servizi. Esempi di questo tipo sono Google, Facebook o Twitter. Spesso questo compagnie offrono modo diretti per accedere ai dati dette API. API è in realtà un termine molto più generico – qui intendiamo specificatamente le API del Web. Ogni API è diversa e specifica al servizio a cui si riferisce.

Possiamo ad esempio accedere a Twitter usando la libreria twitter scaricabile da http://pypi.python.org/pypi/twitter o meglio installabile usando pip install twitter. Questa libreria dà accesso diretto ai dati di twitter e permette anche di mandare tweets da Python. Dopo aver installato la libreria e fatta l'autentizazione (come da instruzioni della libreria), possiamo vedere sia una porzione di tutti i tweet del mondo mandati in tempo reale, o leggere i tweet di una persona specifica, come Barack Obama. Qui di seguito facciamo vedere questi un esempio che visualizza lo stream dei dati twitter.

from twitter import TwitterStream, UserPassAuth, Twitter

# put a file twitter-pwd.txt with your 
# username and password in differnt lines
with open('twitter-pwd.txt','r') as f:
    lines = f.read().splitlines()
    username = lines[0].strip()
    password = lines[1].strip()

# open stream
twitter_stream = TwitterStream(auth=UserPassAuth(username,password))

# print stream
for tweet in twitter_stream.statuses.sample():
    if 'delete' in tweet: continue # skip deleted
    print tweet['user']['screen_name']
    print '    ', tweet['text']
    print ''

Ed infine un esempio che fa una ricerca su twitter for un determinato tag.

from twitter import Twitter

# perform a search
twitter_search = Twitter(domain="search.twitter.com")

# Search for the latest News on #berlusconi
search = twitter_search.search(q="#roma")
for tweet in search['results']:
    print tweet['text']
    print ''

Web Scraping

Le operazioni di prima di potevano fare anche usando l'interfaccia web. Quello che è interessante è fare analisis, anche semplici, dei dati usando programmi python. Per fare ciò possiamo usare l'utility twitter-log installata con la libreria per salvare su disco un archivio dei dati di un utente twitter. Usando il codice seguente si può convertire questi dati in JSON, un formato per lo scambio dei dati. Non faremo questa conversione a lezione.

#! /usr/bin/env python -B

import json

names = [ 'BarackObama', 'Corriereit', 'MittRomney', 'repubblicait' ]

def convert(name):
    def _blank(line):
        return not line or line.isspace()
    with open(name+'.log.txt','r') as f:
        lines = f.read().decode('utf8').splitlines()
    tweets = []
    while lines:
        while lines and _blank(lines[0]):
            lines = lines[1:]
        if not lines: break
        print lines[0]
        line, lines = lines[0], lines[1:]
        name, id = tuple(line.split())
        line, lines = lines[0], lines[1:]
        _, _, month, day, time, _, year = tuple(line.split())
        while lines and _blank(lines[0]):
            lines = lines[1:]
        text = ''
        while (lines and 
               not (_blank(lines[0]) and 
               _blank(lines[1]))):
            text += lines[0]
            lines = lines[1:]
        tweets += [ { 
            'name': name, 
            'id': id, 
            'time': time, 
            'date': day+'-'+month+'-'+year, 
            'text': text 
        } ]
    with open(name+'.json','w') as f:
        json.dump(tweets,f,indent=True)

for name in names:
    convert(name)

Dopo questo possiamo fare un programmino semplice per vedere le parole più usate da un twitter user con il semplice programma

import json, string

names = [ 'BarackObama', 'Corriereit', 'MittRomney', 'repubblicait' ]

for name in names:
    with open('twitter-log/'+name+'.json','r') as f:
        tweets = json.load(f)
    nlinks = 0
    words = {}
    for tweet in tweets:
        text = tweet['text']
        if 'http://' in text: nlinks += 1
        for c in string.punctuation+'""':
            text = text.replace(c,' ')
        twords = text.lower().split()
        for word in twords:
            if word in words: words[word] += 1
            else: words[word] = 1
    print name, len(tweets)
    print 'links:', nlinks
    for word, count in words.items():
        if count > 0.05 * len(tweets):
            print '    ', word, count