L'autore di questo innovativo libro è davvero un personaggio particolare e un esperto informatico;
Mark Watson, infatti, ha pubblicato ben 16 libri, ma quello che impressiona è la poliedricità dei suoi testi: ha scritto molto sull'intelligenza artificiale, su C++, su
Java,
UML, sulla programmazione sotto
Windows, un libro su
Linux, e anche su
LISP.
Questo libro è innovativo perché tenta di presentare tecnologie che saranno sempre più importanti nei prossimi anni. Per una volta il target di lettori a cui è destinato il testo è circoscritto e chiaro, semplicemente
sviluppatori di software, anche con una certa esperienza. Dopo aver proposto alcune caratteristiche che probabilmente avrà il
Web 3.0, vengono velocemente visti i contenuti del libro, le motivazioni per l'adozione di
Ruby come linguaggio per gli esempi di codice, e le modalità per recuperare i sorgenti: oltre al classico link disponibile su sito
Apress, è prevista anche la possibilità di utilizzare una
AMI Amazon Machine Image, una macchina virtuale con tutto il software necessario installato, compresi gli esempi da lanciare; il tutto utilizzabile con un account su
Amazon Web Services, spendendo pochi centesimi di dollaro.
Il testo è diviso in 4 parti, più una quinta di appendice. La prima parte del libro, comprendente i primi 3 capitoli, vuole essere la proposizione di strumenti per l'elaborazione di testi, che poi verranno utilizzati nelle successive parti del libro. Il
primo capitolo è dedicato al
parsing di testo nei formati di documento più comuni. Si inizia subito con classi e codice
Ruby, in realtà un semplice abbozzo di classi. Si evince subito che il testo è indirizzato a esperti sviluppatori con un'ottima conoscenza di
Ruby, perché l'autore non accenna nemmeno a soffermarsi sulla spiegazione del codice, né su configurazioni varie. Vengono quindi proposti gli scheletri delle classi per estrarre testo da
HTML,
XHTML, file binari,
OpenDocument,
RSS, ATOM, mentre per PDF e DOC si propone la strada di convertitori per portarli in uno dei formati precedenti; infine un accenno all'uso di tool come
GNU libextractor e
FastTag (libreria open source dell'autore stesso).
Nel
secondo capitolo vengono presentate altre tecniche di lavorazione dei testi. Si comincia con la rimozione di tag da file
HTML, e si prosegue con l'estrazione di tutto il testo da un file
XML con utilizzo della libreria
Nokogiri o la libreria standard di
Ruby,
REXML. Si passa poi a esaminare il codice per segmentare del testo in frasi, tramite l'aggancio alla punteggiatura. Un accenno allo
stemming, il processo di semplificazione delle parole, con la rimozione di suffissi, utilizzando la libreria stemmer di
Matt Mower e
Ray Pereda. Utilizzando
GNU Aspell, viene introdotto lo
spell checking del testo e nonostante non esista una versione per
Ruby di questa libreria, l'autore propone un modo per richiamarla come programma esterno. Nell'ultimo paragrafo si esamina come rimuovere caratteri indesiderati da file binari e come eliminare le parole che non risultano appartenere a un dizionario di riferimento. Vi è anche una menzione a due tool di
data mining:
Weka, scritto in
Java, e
NLTK (Natural Language Toolkit) basato su
Python.
Il
terzo capitolo rappresenta un'introduzione alle tecniche di
NLP (Natural Language Processing) statistiche, per la segmentazione, la classificazione e il riassunto di testi. L'autore propone un metodo e il relativo codice per la categorizzazione automatica del testo, basato su un conteggio statistico delle parole usate. L'algoritmo illustrato prevede l'utilizzo di file di base, uno per ogni categoria, che servono per elaborare una statistica che verrà poi confrontata con il computo delle parole, fatto sul testo che si vuole elaborare. Dopo questo algoritmo statistico, ne viene presentato uno di classificazione di testo,
Naïve Bayes, basato sul teorema della probabilità di
Bayes. Mentre i primi due metodi di categorizzazione non colgono perfettamente la dipendenza tra le varie parole, con la
LSA (Latent Semantic Analysis), presentata successivamente, si tenta di cogliere proprio l'interdipendenza. L'algoritmo di questa tecnica, che si chiama
LSI (Latent Semantic Index), oltre a considerare la dipendenza tra parole, ha anche il vantaggio di calcolare l'effetto di una parola, nel determinare la categoria, nel caso di diversi significati della parola stessa. Ma dai test dell'autore, dal punto di vista della categorizzazione,
LSI produce risultati inferiori rispetto agli altri metodi, mentre funziona bene nell'attività di sunto automatico di un testo. La
LSI library fa parte della
classifier gem di
Ruby, ma si può utilizzare anche la
GSL (GNU Scientific Library) più performante, ma più difficile da installare su sistemi non Linux. Si prosegue con una classe per l'estrazione di entità, come nomi di luoghi, di persone o di prodotti dal testo. Vengono anche citati dei progetti per la definizione e l'aggiornamento di liste a supporto della
NLP e non solo: il
Moby project, l'interessante repository di
dataset Infochimps e il
Penn Treebank Project. Per questa classe di estrazione stranamente viene proposto tutto il codice sorgente, con qualche accenno di commento, anche se non è assolutamente la classica spiegazione passo passo del codice, del tutto assente in questi primi capitoli. Viene poi proposto un altro modo di estrarre le entità da un testo tramite l'utilizzo di
OpenCalais un Web Service internet, che concede un certo numero di interrogazioni free al giorno. Viene quindi mostrato parte del codice di un client che accede al web service sottoponendo un testo, l'autore presenta poi una classe combinazione di categorizzazione e riassunto, utilizzando il conteggio statistico delle parole, questo per una questione di efficienza dato che le due attività hanno alcuni passi in comune. Concludono il capitolo un esempio per la determinazione del
sentiment di un testo e un accenno alla
clusterizzazione dei documenti; infine l'autore propone un aggiornamento della classe
TextResource che egli ha iniziato a costruire dal primo capitolo, con alcune delle funzionalità appena introdotte.
Nella seconda parte del testo vengono presentate alcune tecniche di
Web semantico, sulle quali si sta puntando molto attualmente, e che secondo l'autore saranno fondamentali per le applicazioni che costituiranno il Web 3.0. Il
quarto capitolo è un'introduzione a
RDF (Resource Description Framework), la sua definizione e il suo utilizzo, insieme alla sue serializzazioni,
N-Triple e
N3, e la sua rappresentazione in grafi, per ottenere la quale, l'autore utilizza il tool
Graphviz. Si prosegue con un accenno a
RDFS (RDF Schema) e a
OWL (Web Ontology Language), seguito dalla citazione di alcuni servizi di conversione di formati disponibili sul Web, e poi dalla presentazione di un tool per la modellazione:
Protégé Ontology Editor. Prima di introdurre diversi esempi sulle query
SPARQL, l'autore spende un paragrafo per parlare della logica e delle deduzioni necessarie per poter operare. Seguono, a conclusione del capitolo, una serie di esempi pratici di composizione di query
SPARQL, utilizzando una libreria Ruby e alcuni database pubblici presenti in Rete.
Nel
quinto capitolo vengono presentati diversi
RDF data store, di cui si segue l'installazione, la configurazione e gli esempi di utilizzo. Il primo di questi è
Redland, affiancato da altri componenti,
Raptor RDF Syntax Library e
Rasqal RDF Query Library, insieme a database di back-end come
Oracle Berkley DB, per poter implementare un esempio di
RDF data store
embedded in un'applicazione. Segue un esempio di utilizzo di
Sesame RDF data store, scritto in
Java e che a differenza di
Redland prevede anche la possibilità di utilizzare l'
inference. Viene mostrato come installare
Sesame, il
JDK e
Apace Tomcat per poter configurare un
RDF data store accessibile via Web. L'autore poi propone anche un esempio di utilizzo lato client del data store, implementando una classe
Ruby, anche se chiaramente, il naturale linguaggio da usare con
Sesame dovrebbe essere
Java. In ogni caso, alla fine l'autore mostra una soluzione semicompleta di
RDF data store distribuito, con una web application
Sesame e la combinazione di questa con un client in grado di fare query
SPARQL. Le spiegazioni abbastanza dettagliate sulla configurazione mostreranno la relativa facilità con cui è possibile pubblicare dati
RDF, tramite l'interfaccia web di
Sesame, e successivamente come è possibile farlo, automaticamente, via client. Si prosegue mostrando la possibilità di usare
Sesame come data store
embedded, usando
JRuby, sia accedendo direttamente ai JAR, sia creando un
wrapper. Ultima proposta dell'autore è
AllegroGraph, soluzione commerciale che però prevede una versione limitata non a pagamento. Scritto in
Common LISP, esso offre librerie client anche per
Java,
Python e
Ruby. Si prosegue con un'interessante proposta di sperimentazione dei concetti esposti utilizzando alcuni database
RDF pubblici presenti su Internet:
rdf:about, che contiene dati del censimento statunitense e dati del
Congresso degli Stati Uniti;
DBpedia, che raccoglie informazioni strutturate estratte da
Wikipedia; e
RDFizing. Vengono proposti esempi di interazione con il sito
UMBEL e con
rdf:about.
Il
sesto capitolo si focalizza sugli aspetti pratici delle query
SPARQL e, dopo una sessione di definizioni formali di termini, vengono presentate le varie tipologie di query
SPARQL:
CONSTRUCT,
DESCRIBE e
ASK. Segue poi un approfondimento sul concetto di
Inference, che sta alla base delle tecnologie di
Web semantico. Nel
settimo capitolo viene proposto il codice per l'implementazione di un portale web per la gestione di
RDF, con un front-end, che utilizza
Sinatra e un back-end che utilizza
Sesame e
JRuby. Viene anche proposto un secondo back-end con
Redland e
Oracle Berkley DB, e un client per testare il tutto. Infine si integrano nel portale, l'aggiunta di
RDF in tempo reale e la generazione di diagrammi
Graphviz.
La terza parte si occupa del reperimento di informazioni e del loro salvataggio in database repository. Nell'
ottavo capitolo si esamina l'utilizzo di database relazionali e di
ORM (Object Relational Mapping). Si inizia con il framework
ORM Active Record con un veloce tutorial, proposto con codice
Ruby, che spazia dalla impostazione delle relazioni, alla gestione delle transazioni, dall'utilizzo delle
callback e degli
observer, alla modifica delle impostazioni di default. Il secondo framework
ORM esaminato è
DataMapper, di cui vengono approfonditi vari aspetti, tra cui il suo approccio più orientato a
Ruby.
Argomenti del
nono capitolo sono servizi e tool di ricerca e indicizzazione. Si parte da
Apache Lucene e la libreria
wrapper jruby-lucene, di cui si esaminano alcuni esempi per l'indicizzazione e la ricerca di testo; si prosegue esaminando lo specifico algoritmo
Geohash per ricerche spaziali e oltre a esaminarne l'utilizzo tramite la libreria
davetroy-geohash scritta in
Ruby, viene anche proposto un confronto prestazionale tra questo approccio e quello normale in SQL. Segue la breve presentazione di
Solr, un WS che fa da interfaccia a
Lucene, addizionando scalabilità ed estendendo le API. L'autore poi presenta un breve tutorial su
Nutch, una soluzione web che fornisce funzionalità di ricerca, indicizzazione di pagine tramite spider, e navigazione in profondità tramite visita dei siti. Viene esaminata la modalità di installazione e l'utilizzo da un client
Ruby. Il capitolo si conclude con una discussione e con esempi su delle tecniche efficienti di ricerca in database relazionali, sia
full-text native di
PostgreSQL e di
MySQL (che vengono integrate anche con
Active Record e richiamate dal client
Ruby), sia utilizzando un servizio esterno come
Sphinx che permette la massima efficienza.
Nel
decimo capitolo si esplora l'affascinante mondo del
web scraping, impostando innanzitutto
Firebug, noto plug-in di
Firefox, come analizzatore di pagine da sottoporre a
scraping. Per il primo esempio di sviluppo di un
web scraping viene utilizzata la libreria
scRUBYt!, quindi analizzato un sito e collezionate una serie di informazioni che in questo caso sono ricette, con ingredienti e con i relativi link; poi queste informazioni vengono memorizzate in un database per una successiva elaborazione, ricorrendo nuovamente ad
Active Record. Nello stesso database, tramite l'utilizzo di
Watir, un'altra libreria di
web scraping, si integrano informazioni prese da un altro sito. Vengono poi generate automaticamente relazioni
RDF tra le informazioni dei due siti e grafici con
Graphviz. Il capitolo si conclude con una riflessione sull'utilizzo per il Web di un
RDF data store invece di un database relazionale.
L'
undicesimo capitolo, che tratta di
Linked Data, inizia con la presentazione del sistema
D2R, un'interfaccia
SPARQL a un database relazionale, di cui si vede l'installazione e velocemente il suo utilizzo. Si esaminano poi tre diversi
Linked Data source, partendo con alcune query
SPARQL di esempio lanciate su
DBpedia, per ricercare, ad esempio, tutte le persone citate in
Wikipedia, che sono nate nel Maine e morte in California. La trattazione prosegue con
Freebase e alcune prove sia con
MQL (Metaweb Query Language), il linguaggio di query supportato dal sito, sia con l'utilizzo di codice
Ruby, tramite la libreria
wrapper Freebase API e terminando con
OpenCalais, di cui si estende il codice già utilizzato nel capitolo 3.
Il
dodicesimo capitolo è invece deputato ad analizzare una serie di strategie per la gestione di storage su larga scala. Si passano perciò in rassegna le modalità master/slave che è possibile configurare su
PostgreSQL e su
MySQL, e che prevedono un server principale di inserimento e aggiornamento, e tanti server replicati che si sincronizzano automaticamente e che vengono utilizzati in sola lettura. Sempre dei due DBMS, si esplora la possibilità di
database sharding, in cui si ripartisce la base dati in diverse istanze, secondo un criterio che poi permetta il recupero dei dati. Si prosegue esplorando il sistema di
caching distribuito —
memcached — e che viene utilizzato da siti come
Slashdot,
Twitter e
Facebook, e tramite la
gem Ruby MemCache, vengono proposti alcuni esempi di utilizzo. E' la volta poi delle funzionalità di
Apache CouchDB un database
document-oriented scritto in
Erlang e che utilizza JavaScript lato server. Gli esempi proposti mostrano come salvare sul DB e poi rileggere articoli da Wikipedia. Terminano il capitolo un esempio di utilizzo in
Ruby, grazie al gem
aws-s3, di
Amazon S3 e una breve panoramica sul servizio
Amazon EC2 Elastic Compute Cloud.
Nella quarta parte il tema principale è la pubblicazione delle informazioni raccolte e l'elaborazione su larga scala di queste, in supporto proprio alla pubblicazione. Il pratico e interessante
tredicesimo capitolo presenta l'implementazione di una
mash-up, che integra i dati dal proprio account
Twitter con
Google Maps, estraendo con una delle tecniche viste nella prima parte, le località dai post dei propri amici e visualizzando queste su una cartina. Vengono brevemente considerate le API dei due servizi, con l'immancabile
libreria wrapper per Twitter; e poi, volendo costituire l'applicazione in
Rails, vengono anche proposti il plug-in
YM4R/GM per
Google Maps, e il codice per il controller e la view.
Nel
quattordicesimo capitolo si illustra una soluzione di elaborazione di dati su larga scala. Dopo l'introduzione concettuale dell'algoritmo
Map/Reduce, che supporta la computazione distribuita su grandi quantità di dati in cluster, viene velocemente analizzata l'installazione di
Apache Hadoop, che è un'implementazione open source della tecnica. Qui sono esposti esempi di utilizzo di
Apache Hadoop per la creazione di
Inverted Word Index, sia in Ruby che in
Java, per la prima volta nel libro, perché essendo questo il linguaggio con cui è scritto
Apache Hadoop, permette il pieno accesso a tutte le API. Infine si esamina come eseguire l'esempio mostrato ricorrendo a
Amazon Elastic MapReduce.
Nel
quindicesimo capitolo, si conclude il testo con l'implementazione di due portali informativi, il primo per la ricerca locale di nomi presenti su Wikipedia e il secondo per un portale dei propri argomenti di interesse, che permette di inserire sia file che URL, il tutto riassunto e categorizzato. Questo secondo esempio è l'assemblamento di buona parte delle tecniche esposte nel libro.
Nell'
appendice A viene spiegato come poter utilizzare la AMI creata dall'autore, per provare il codice del libro nell'ambito dei servizi cloud di Amazon, che permettono di non installare nulla sulla propria macchina. Nell'
appendice B si esplora l'utilizzo dell'HTTP header per effettuare richieste precise dei formati restituiti e richiesti da client web. L'
appendice C, infine, è una breve introduzione al formato
RDFa.
Questo testo rappresenta davvero un ottimo trattato su un insieme di tecnologie interessanti e promettenti, e forse per una volta il titolo del libro, un po' anonimo, non rende giustizia all'insieme delle tematiche proposte. Si leggono spesso libri in cui si ha la netta sensazione che al di là di una buona idea di base, molte parti servano semplicemente ad
allungare il brodo. In questo testo invece è lampante sin da subito che l'autore ha davvero parecchio da dire, e tranne per due sporadici parti di codice in cui vi è un accenno di spiegazione, per il resto si lascia che parli il codice. Del resto, e questo è altrettanto chiaro, il testo è
rivolto a persone esperte di sviluppo in generale e di
Ruby in particolare, e l'intento è quello di presentare tecniche, tecnologie e una miriade di possibilità offerte da varie librerie. Senza dubbio l'autore, poi, rende un grande servigio a
Ruby, dimostrando l'estrema duttilità del linguaggio e la vasta disponibilità di librerie e tool.