10 maggio, 2007

Baby e ybab: uno script python per usare i dizionari babylon

E' da tanto che non scrivo? Lo so ma fra qualche giorno se tutto procede come previsto dovrei laurearmi quindi il tempo da dedicare al blog è praticamente inesistente. Appena tutto sarà finito tornerò a sviluppare cGmail e a postarvi gli studi su python e tutto il resto. Per ora, per non lasciarvi proprio a bocca asciutta, vi propongo un piccolo "bocconcino" che ho sviluppato qualche tempo fa e che potrebbe risultare utile (o quantomeno potrebbe essere uno spunto) a qualcuno di voi. Si tratta di un semplice script (indovinate in che linguaggio? . . . Bravi :) ) che interroga il database dei dizionari babylon, si presenta come Firefox 2 e poi interpreta l'html per tirare fuori le informazioni sul lemma ricercato.

Il codice python


#! /usr/bin/env python
import urllib2
import re
import sys
from sgmllib import SGMLParser

red='\033[0;31m'
RED='\033[1;31m'
blue='\033[0;34m'
BLUE='\033[1;34m'
cyan='\033[0;36m'
CYAN='\033[1;36m'
NC='\033[0m'

ROWLEN = 60

class Parser(SGMLParser):
def __init__(self):
SGMLParser.__init__(self)
self.must_print = False

def reset(self):
SGMLParser.reset(self)

def write(self, data):
sys.stdout.write(data)
sys.stdout.flush()

def start_div(self, attrs):
for attr, value in attrs:
if attr == "class":
if value == "term":
self.write(RED + '\n')
self.must_print = True
if value == "definition":
self.must_print = True

def end_div(self):
self.must_print = False
self.write(NC)

def handle_data(self, data):
if not self.must_print: return
if data.strip() == "": return
tmp = data.strip()
tmp = data.replace('\n', '')
count = len(tmp)
if count > ROWLEN:
pieces = count / ROWLEN
for i in range(pieces):
l = ROWLEN * i
u = ROWLEN * (i + 1)
self.write(tmp[l:u] + '\n')
else:
self.write(tmp + '\n')



def http_req(url, data):
req = urllib2.Request(url, data)
req.add_header('User-Agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.4) Gecko/20061201 Firefox/2.0.0.4 (Ubuntu-feisty)')
req.add_header('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7')
req.add_header('Accept', 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5')
stream = urllib2.urlopen(req)
out = stream.read()
stream.close()
return out


def usage():
print "Usage: baby parola\n";

def search(word, lang):

out = http_req('http://info.babylon.com/onlinebox.cgi',
'rt=ol&tid=pop&uil=EN&cid=CD1&term='+word+'&tl='+lang)
return out


if __name__ == "__main__":
import os
args = sys.argv[1:]
if args[0] == None:
usage()
sys.exit(1)
word = args[0]
out = ""
appname = os.path.basename(sys.argv[0])
print appname
if appname == "baby":
out = search(word, "EN")
elif appname == "ybab":
out = search(word, "IT")
p = Parser()
p.feed(out)
p.close()

Come lo installo?
Copiate ed incollate il codice in un file che chiamerete baby (Attenzione: il nome è importante). Date i permessi di esecuzione al file e copiatelo in una directory inclusa nel vostro path (ad esempio /usr/local/bin). A questo punto create un link simbolico al file con nome ybab. Esempio di tutti i passaggi (supponiamo che avete salvato lo script di cui sopra su un file di nome baby sul vostro desktop):

sudo cp ~/Desktop/baby /usr/local/bin
sudo chmod +x /usr/local/bin/baby
sudo ln -s /usr/local/bin/baby /usr/local/bin/ybab

Come si usa?
L'uso è semplicissimo. Invocando baby [lemma_da_cerare] verrà considerata come lingua target l'inglese, invocando invece ybab [lemma_da_cercare] verrà considerato come target l'italiano.

Esempio:

$ ybab glad
ybab

glad
agg.
felice, contento, lieto; gioioso
s.
gladiolo (fiore)

GLAD
CONTENTO. LIETO. FELICE. ALLIETARE. RALLEGRARE. GLADIOL
Purtroppo per alcuni lemmi l'output non è così pulito (ci sarebbe da migliorare il parser, suggerimenti sono ben accetti. Io non mi ci sono dedicato più di tanto)

Come funziona
Le informazioni che seguono sono piuttosto tecniche. Se vi interessa solo il programmino e non sapere come funziona potete tranquillamente evitare di proseguire nella lettura.

Lo script utilizza la urllib2 di python per fare una semplice richiesta al sito di babylon. Per conoscere l'esatto URL da interrogare e i parametri da passargli è necessario studiarsi un po il sito, conoscere un minimo di programmazione web, sapere come funzionano le form ed avere un po di pazienza. Una volta noto il meccanismo di interrogazione utilizzato dal sito in questione, il resto è "semplice". In questo caso l'output della richiesta http, viene "parsato" (passatemi il termine) dall'apposito parser che utilizza la libreria sgmllib. Un aspetto interessante dello script è il modo che utilizza per cambiare la sua funzionalità (in questo caso la lingua target). Ricordiamo che il primo parametro passato ad un programma è sempre il suo nome. Quindi distinguendo il nome del primo parametro è possibile effettuare operazioni diverse
. In questo caso se il programma viene invocato come baby viene utilizzata la lingua inglese, mentre invocato come ybab quella italiana.

4 commenti:

  1. Hao..

    Grande questo script, ho usato la tua base e implementato un interfaccia grafica utilizzando glade, è venuto abbastanza bene :), però devo perfezionare alcune cosette..

    Cmq ancora grazie per questi script succulenti che dai...

    RispondiElimina
  2. Se ottieni qualcosa di interessante perché non lo pubblichi?

    Fammi sapere ;)

    RispondiElimina
  3. Io lo farei pure ma nn sono mai stato bravo in queste cose di pubblicazione..
    Cmq un modo lo trovo, magari lo piazzo sul mio sito o blog...
    in fondo sono 2 file :)

    RispondiElimina
  4. complimenti adesso provo il tuo script su ubuntu !! e' proprio quello che cercavo, dato che non riesco a trovare una sorgente per il dizionario incluso in ubuntu ch efaccia italiano-spagnolo....

    RispondiElimina