La biblioteca (digitale) di Oblivion

Dove l’autore, a causa della tremenda monotonia del suo lavoro, decide di cimentarsi in un esperimento di biblioteconomia digitale, allo scopo di imparare un po’ di programmazione e di poter godersi meglio un grande videogioco. Ha così creato un epub contente tutti i libri di The Elder Scrolls IV: Oblivion. Il file si può scaricare da qui. Quello che segue invece è il racconto di “come lo feci”.

 L'amichevole bibliotecario della Gilda dei Maghi di Skyrim
L’amichevole bibliotecario della Gilda dei Maghi di Skyrim

Il mondo di The Elder Scrolls

Il mondo della saga di The Elder Scrolls è bellissimo. Il giocatore, attraverso il suo personaggio, è catapultato in un universo vastissimo che può esplorare in totale libertà. Apparentamente disorientati da una certa mancanza di binari narrativi – le quest sono sempre facoltative e lo scorrere del tempo sembra non alterare di granché il rapporto con i personaggi non giocanti – si scopre piano piano un’ambientazione profondissima, ricca di storia e di tradizioni. Scopriamo che dietro ogni commento fra gli avventori di una locanda o le aule di un palazzo c’è una storia immensa che non viene raccontata direttamente, ma che esiste, presente, in attesa di essere svelata se il giocatore è abbastanza curioso. Il mondo di The Elder Scrolls (TES) è per certi versi simile a quello di Tolkien: la storia principale non è che la superificie di un’ambientazione ricca e complessa. Questo background affiora continuamente, con eleganza e discrezione, attraverso dei piccoli elementi che compaiono nel racconto, e che agiscono come delle finestre che dall’interno della narrazione principale si schiudono verso un mondo più ampio e profondo. Queste “finestre” nell’opera di Tolkien sono rappresentate dalle poesie e le canzoni che i personaggi scambiano durante il loro lungo viaggio, nelle brevi soste intorno al fuoco o al rifugio fra i palazzi di Rivendell. In TES invece sono i numerosi libri sparsi per il mondo, dagli scaffali delle gilde ai bauli nascosti nelle grotte, dalle case dei personaggi ai ripiani delle librerie, ciascuno dei quali può essere raccolto, rubato, comprato, ma soprattutto letto nella sua interezza dal giocatore.

In Oblivion, il quarto gioco della serie, uscito nel 2006, sono sparsi circa 200 libri: alcuni sono utili ai fini del gioco stesso, perché la loro lettura contiene indizi utili per l’avventura, o aumenta le statistiche del personaggio, rendendolo di fatto più forte. Altri hanno il solo scopo di arricchire e approfondire l’ambientazione. Paradossalmente questo comporta un problema di giocabilità, poiché per quanto lento sia il passo del gioco, raramente si ha voglia di fermarsi a leggere tutto quello che capita fra le mani del nostro avatar, che magari è immerso in problemi più urgenti (tipo fermare un pericoloso negromante o impedire l’apertura dei terribili cancelli di Oblivion). Insomma durante le centinaia di ore passate su Oblivion (così come su Skyrim) mi sono sempre chiesto chi cavolo fosse questo “Galerion il mistico”, o di che cosa parlasse il romanzo “La freccia nera”, senza avere mai il tempo di leggerli per intero.

Per ovviare a tutto ciò ho deciso di creare un ebook contenente tutti i testi dei libri di The Elder Scrolls – anzi in particolare quelli di Oblivion, che sto rigiocando proprio in questi giorni. In questo modo posso portare l’enorme background della serie al di fuori del videogioco in un ambiente più consono al suo approfondimento: il mio spazio di lettura quotidiano, il mio ebook reader.

Sean Bean - ehm, Martin legge
Sean Bean – ehm, Martin legge

L’idea

L’idea ovviamente non è originale. Esistono già diversi tentativi (disponibili su Tesnexus) ma nessuno mi sembra soddisfacente come qualità. In particolare nei tentativi presenti online mi mancano sempre gli indici: non solo io detesto i libri senza indice, ma una miscellanea del genere è semplicemente inutilizzabile senza un sommario dei contenuti.

La fonte di autorità rimane quel sito meraviglioso che è The Imperial Library: qui sono raccolti, formattati e categorizzati tutti i libri della serie. E’ da qui che sono partito per il mio progetto: ho deciso di fare uno scrape di tutto il sito, e da lì estrarre i contenuti da formattare in un singolo epub.

A spingermi è stato anche un momento di crisi nel mio lavoro. Di fatto da più di un anno non faccio nulla che sia attinente alle digital library. Il livello tecnologico delle mie attività è pari a zero, non sono impegnato in progetti innovativi o creativi, sto lentamente disimparando tutto, e mi sta passando la voglia di fare questo mestiere. Per evitare di finire come un dragon priest, avvizzito e pieno di livore, ho deciso di tenermi occupato con questo progettino per imparare qualcosa e mantenermi in esercizio.

Questo è un po’ il racconto di cosa ho fatto.

Il nuovo Arci-Mago nella sua biblioteca
Il nuovo Arci-Mago nella sua biblioteca

Il progetto

Ho aperto un progetto su Asana, e ho buttato giù i punti del mio lavoro: ho cercato di dividere il progetto in attività e sotto-attività, in modo da affrontare i problemi uno per volta. Ad es. la prima cosa che mi sono chiesta è “come si fa a fare lo scrape di un sito”, e poi “come formattare tutto il paciugo che mi arriva”, e infine “come trasformare il paciugo in un epub” (ho subito pensato a Pandoc). Ogni task ha richiesto di trovare delle risposte, le quali hanno poi sollevato ulteriori problemi, e così via. Ho cercato di risolverli uno per uno, documentando il processo, valutando cosa fosse nelle mie possibilità e cosa fosse irrealizzabile, e che cosa avrei dovuto imparare, quali linguaggi o standard, e quali tecnologie utilizzare.

Cattura

Per lo scrape ho usato wget. Avevo già usato questo comando in passato ma non me lo ricordavo. E’ stato sufficiente un’unica riga per tirarmi giù in locale l’intero sito di The Imperial Library.

wget --html-extension -r --save-headers http://www.imperial-library.info/books/oblivion/

In realtà ho commesso due errori, per fortuna privi di conseguenze. Il primo è che non sono riuscito a dare al comando i parametri di estrazione corretti: avevo dato un’occhiata al sito originale e avevo intravisto un’organizzazione molto lineare, nella quale avevo individuato la specifica directory che andava scaricata, ma in realtà non sono riuscito a isolarla, e ho finito per scaricare tutto il dominio. Il secondo errore è stato che non ho calcolato in anticipo quanto spazio servisse (domanda ingenua: wget permette di farlo?): per fortuna il sito è composto quasi esclusivamente da testo, quindi ha occupato appena 695 MB e il comando ha richiesto non più di 2 ore di esecuzione. Mi sono accorto però che lanciarlo così alla cieca avrebbe potuto creare dei problemi di carico non da poco.

Lo scrape è stato quindi semplice. A questo punto si trattava di fare ordine in quello che avevo scaricato, in modo da darlo in pasto a Pandoc. Mi sono rivolto a Beautiful Soup, e qui è iniziato il bello.

Jauffre legge
Jauffre legge

Elaborazione

Beautiful Soup è una libreria di Python adatta a manipolare file di markup. Quello che dovevo fare era ripulire tutte le pagine del sito in modo da estrarre dall’HTML solo i contenuti dei libri veri e propri, e preparare ciascun file in un formato che Pandoc fosse poi in grado di digerire bene.

The Imperial Library contiene tutti i libri in un’unica directory chiamata “content”. Esistono directory per ciascun gioco, che però servono a contenere solamente i diversi indici del sito. Per riconoscere solo i libri che mi interessavano ho dovuto quindi prima estrarre la lista dei libri di Oblivion.

soup = BeautifulSoup(open("by-title-oblivion.html")) 
ldir = []
for link in soup.find(id='content').find_all("a"):
    # print(link.get("href")) # test
    ldir.append(link.get("href"))

In questo modo ho poi potuto far correre lo script di trasformazione solo sui libri che mi interessavano (che alla fine erano circa 200 su oltre 6000!).

for book in ldir:
    zupparic(book)

Quanto alla elaborazione dei sorgenti, il lavoro è stato più facile del previsto perché la sorgente era estrememante pulita e ben formattata. Voglio dire, ogni libro stava in una pagina HTML distinta, aveva il suo <h1> come titolo, e ogni pagina aveva correttamente uno e un solo <h1>: non è commovente? Con un’origine così ben formattata, usare una funzione di BS per individuare i suoi elementi è stato un gioco da ragazzi. Questo prova come il mattone fondamentale per ogni operazione digitale di successo sia avere i dati puliti. Garbage in – garbage out: se i dati fanno schifo, il risultato farà schifo. Se i dati sono buoni, il risultato sarà buono.

Nel mio caso ho dovuto solo eliminare tutto ciò che “non è il libro”. Recuperare solo il <div> necessario era talmente semplice che ho fatto prima a ricorrere a SoupStrainer.

    main = SoupStrainer(id='main')

    # faccio la zuppa
    content = BeautifulSoup(source, "html.parser", parse_only=main) #devo specificare il parser perché html5 non funziona con SoupStrainer

    # ripulisco con decompose le robe che non mi servono
    content.find("div", id="main").unwrap() #strippo via il tag contenitore, perché il capitolo epub deve incomnciare con h1

Ho deciso di eliminare anche alcuni link contenenti di fatto i metadati del libro (relativi a autore e categorie) per un motivo che vedremo dopo. Poiché la loro presenza nei file era irregolare (leggi: a volte c’erano a volte no) ho dovuto gestire la cosa con una serie di eccezioni:

try:
    content.find("div", class_="breadcrumb").decompose()
except AttributeError:
    pass
try:
    content.find("div", class_="node-submitted").decompose()
except AttributeError:
    pass
try:
    content.find("div", class_="field-field-comment").decompose()
except AttributeError:
    pass
try:
    content.find("div", class_="book-navigation").decompose()
except AttributeError:
    pass
try:
    content.find("div", class_="terms terms-inline").decompose()
except AttributeError:
    pass
try:
    content.find("img").decompose()
except AttributeError:
    pass

Ho dovuto fare un po’ di scelte e semplificazioni. Volevo creare un prodotto immediatamente fruibile, quindi ho rimandato a una ipotetica versione 2.0 i problemi più ostici, e mi sono limitato “alle cose semplici”. Ad esempio non ho voluto importare immagini e fonts (da qui una delle eccezioni di cui sopra) anche se avrei potuto.

Ho deciso di tralasciare la maggior parte dei diari e i vari scritti “sciolti” che si trovano in giro per il mondo: appunti, note, biglietti, ecc. perché non ritenevo che fosse interessante averli al di fuori del gioco. Viceversa, i libri e le note composti solo da immagini (l’Antica Pergamena rubata dalla Biblioteca Imperiale, o il Mysterium Xarxes) sarebbero stati inutilmente illeggibili.

Per fare quest’opera di selezione ho  dovuto comunque ripercorrere a mano i file una votla ripuliti. Avrei potuto manipolare la lista dei titoli da includere eliminando quelli elencati come “notes and journals”, ma ho preferito avere un controllo diretto su cosa scartare e cosa no. Ad es. alcuni diari sono secondo me molto belli (ad es. il diario di Lord Lovidicus che sta alla base della storia del Principe Grigio) e ho voluto tenerli.

Questo è stato l’unico lavoro manuale dell’intera operazione. Il motivo per cui ho voluto ricorrere a degli script è che volevo esercitarmi a creare qualcosa di scalabile, di riutilizzabile anche in altri contesti e da ripetere più volte con piccole correzioni. La selezione e formattazione manuale invece va fatta da capo ogni volta, e alla lunga diventa impraticabile (io ho dovuto ricorrervi due volte per via di un mio errore). Insomma ho voluto farne un esercizio anche di metodo e non solo di programmazione.

Elder Library
La Elder Library del Palazzo Imperiale. Come molte biblioteche istituzionali, accedervi è difficilissimo.

Creazione

Una volta ripuliti tutti i file, mi è bastato lanciare un comando di Pandoc per creare l’epub. Il comando percorre un’intera cartella, raccoglie tutti i file html che trova e li unisce in un unico file epub, creando automaticamente l’indice. E’ bastato aggiungere un semplice file di testo (in YAML) per i metadati (in Dublin Core), una copertina raffazzonata con Photoshop, e il gioco è fatto!

pandoc  -S -o oblivion-books.epub --epub-metadata=title.txt --epub-cover-image=images/ob-cover.jpg content/*.html

Mi sono accorto poi rivedendo il lavoro che alcuni libri erano a loro volta contenuti in altri libri: ad es. libri come The ransom of Zarek o Seed erano in realtà volumi della serie Ancient Tales of the Dwemer, semplicemente contraddistinti da un header <h2> all’interno del libro principale. Su The Imperial Library ciascun libro ha una pagina a sé, ma l’indice del sito, a partire dal quale ho costruito la lista da elaborare, li riuniva in un libro unico, facendomeli quindi scomparire dall’indice dell’epub. Ho rimediato modificando il comando di Pandoc con un paio di variabili in più:

pandoc  -S -o oblivion-books.epub --epub-metadata=title.txt --epub-cover-image=images/ob-cover.jpg  --epub-chapter-level=2 content/*.html -f html-native_divs

Ammetto che la parte finale è stata un po’ tirata via. Per creare un epub come si deve avrei dovuto prima studiarmi bene tutte le specifiche dello standard, mentre mi sono limitato ad affidarmi ciecamente a Pandoc. Ora io non so se Pandoc abbia più impostazioni di quelle indicate nella documentazione, o se esistono strumenti più idonei per creare un epub in maniera automatizzata, ma il risultato finale è stato tanto rapido quanto essenziale.

Leggendo oltre le spalle di un assassino argoniano
Leggendo oltre le spalle di un assassino argoniano

Cose da fare, volendo

Al di là del risultato finale, questo lavoro è stato un pretesto per cimentarmi principalmente con Beautiful Soup e imparare a maneggiare le elaborazioni di file. Il passo successivo sarebbe buttarmi nel mondo di epub e imparare bene tutte le specifiche, per creare un libro veramente bello e ben formattato (magari con Sigil), e non soltanto funzionante. Alcune cose da fare, che rimando a imprese future, sono:

  • Creare una copertina decente. Pandoc ha creato una grezza copertina con il file che gli ho indicato (e che ho creato al volo con Photoshop senza stare a pensare a una grafica degna di questo nome). Ma sarebbe stato utile mettere un svg wrapper per consentire all’immagine di adeguarsi ai formati dei diversi lettori. Però aprendo l’epub, modificando il sorgente e richiudendo tutto sono sorti una serie di problemi, per cui mi sono detto “rimetti! a posto! la! candela!” e ho fatto finta di niente.
  • Indici. Ho deliberatamente escluso da ogni libro tutti i rimandi intertestuali alle categorie usate da The Imperial Library. Sarebbe bello mantenerle renderle interattive, in modo da creare diversi indici e poter così consultare i libri per categoria o per autore. Importando in un unico epub i libri di tutti i giochi di TES, si potrebbero anche ordinare per episodio (Morrowind, Skyrim, TES Online, ecc.). Ma Pandoc a quanto pare rinomina arbitrariamente i capitoli del libro, per cui andarli a puntare con dei rimandi ipertestuali interni era un po’ dura.
  • Immagini, font, e stile. Non ho provato a cimentarmi con il css dell’epub, ma sarebbe bello giocare con la formattazione per fare un libro più carino. Si potrebbero ad es. importare i font utilizzati nel gioco, per dare ai testi una veste più elegante.

Il file è ora scaricabile da Nexus Mods, o direttamente dal link: http://www.nexusmods.com/oblivion/download/1000012231. Il file non è perfetto: tutti gli errori sono da imputare a Pandoc. A parte gli scherzi, in futuro proverò a formattarlo in maniera più controllata e approfondita. Io l’ho provato su iBooks, Calibre e sul mio Kobo Aura. Nel frattempo se avete dei suggerimenti o dei commenti siete i benvenuti!

Buy a goddam book!
Buy a goddam book!

P.S.: ho caricato il codice originale del mio piccolo scrip su GitHub.

La biblioteca (digitale) di Oblivion

Un pensiero su “La biblioteca (digitale) di Oblivion

I commenti sono chiusi.