MBWC – Minimal Bash Web Crawler

L’ANNO scorso, per un esame, ho presentato un piccolo progetto basato su uno script in bash con funzioni di crawler. Molti di voi avranno subito pensato: a questo scopo, se proprio vuoi usare bash, esiste già wget e funziona benissimo con un sacco di funzioni, eh lo so anche io, ma lo scopo di questo script è proprio non utilizzare wget con le funzioni ricorsive che già implementa. Ovvero wget è presente ma scarica solo una pagina alla volta, e viene richiamato enne volte (con enne uguale al numero di pagine che vogliamo scaricare).

Wget è scritto in C invece in questo script la parte che si occupa del trovare i link e filtrarli è tutta scritta in bash, è proprio questa a mio parere la parte più interessante grazie alla quale c’è maggiore possibiltà di personalizzazione. Questo script nel progetto era corredato del, forse altrettanto interessante, script sempre in bash per calcolare delle statistiche (riccorrenze di parole, ecc ecc) sulle pagine salvate, ovvero la vera funzione di un crawler. Per ora questo script non lo pubblico anche perchè avendolo fatto come ultima parte del progetto gli ho dedicato meno tempo e non ne sono per niente soddisfatto. Quando avrò tempo di sistemarlo pubblicherò anche quello.

Colgo l’occasione per segnalare un altro Crawler questa volta scritto in PHP creato da due miei colleghi si tratta di OpenCrawler, molto interessante e da provare, avrò modo prossimamente di scriverci un articolo al riguardo.

Introduzione

MBWC è uno script bash che visita un URL e identifica tutti gli hyperlink presenti nel documento aggiungendoli alla lista di URL da visitare. L’URL di partenza viene definito dall’utente. Ogni pagina HTML visitata viene salvata. Il numero di documenti da salvare è definibile dall’utente altrimenti di default è 100.

Istruzioni

Per utilizzare questo script è sufficente aprire una finestra del terminale, posizionarsi
nella cartella in cui è presente lo script e lanciare il seguente comando:

./mbwc [URL_di_partenza] [numero_pagine_da_scaricare]

Dove:

  • URL_di_partenza è l’url della pagina web da cui deve partire lo script, campo obbligatorio;
  • numero_pagine_da_scaricare è il numero di pagine da scaricare, questo campo è facoltativo di default assume il valore 100;

Lo script salverà nella cartella denominata “pagine” le pagine richieste rinominandole con un numero e l’estensione .html e produrrà i seguenti file di log:

  • link.log conterrà l’elenco degli URL visitati e scaricati, ogni riga corrisponde al file con nome numero_della_riga-1;
  • err.log conterrà l’elenco degli URL che lo script ha cercato di visitare ma non ha scaricato per errori riscontrati da WGET per esempio nel caso il server abbia restituito gli errori: 400 e 404 (pagina non trovata), 505 (errore del server), tempo di attesa troppo elevato ecc ecc;
  • wgetlog.log conterrà l’output di wget dell’ultimo URL con cui è stato lanciato, in runtime è utile per capire il motivo per il quale potrebbe essersi bloccato lo script.

In standard output lo script stampa varie informazioni utili per seguire l’esecuzione dello script.

Esempio:

./mbwc repubblica.it 1000

STD Output:

Creata directory di output: pagine
ho scaricato: 0.html ->  repubblica.it 191358 byte
PARZIALE: counter= 1 errori= 0
Link trovati: 526
ora ricavo i link da: repubblica.it -> 0.html
link_trovato: http://www.repubblica.it/
link_trovato: http://m.repubblica.it/
link_trovato: http://quotidiano.repubblica.it/home
link_trovato: http://www.repubblica.it/servizi/mobile/index.html
link_trovato: http://www.facebook.com/Repubblica
link_trovato: http://www.repubblica.it/servizi/rss/index.html
...
Link validi trovati: 354
ho scaricato: 1.html ->  http://www.repubblica.it/ 191358 byte
ho scaricato: 2.html ->  http://m.repubblica.it/ 10840 byte
ho scaricato: 3.html ->  http://quotidiano.repubblica.it/home 5858 byte
ho scaricato: 4.html ->  http://www.repubblica.it/servizi/mobile/index.html 5929 byte
ho scaricato: 5.html ->  http://www.facebook.com/Repubblica 11019 byte
ho scaricato: 6.html ->  http://www.repubblica.it/servizi/rss/index.html 18509 byte
...
...
----------------------------------
Totale size: 384701 byte Time: 45 sec

Funzionamento

Lo script è composto principalmente da due funzioni: ricava_link e scarica_pagine.
Una volta lanciato, dopo alcuni controlli sul numero di pagine da scaricare (d’ora in poi chiamato target) e sulla cartella di destinazione parte scaricando la pagina presente al link passato come primo parametro e la salva nel file 0.html, sucessivamente la funzione ricava_link analizza questa pagina e ne ricava tutti i link presenti salvandoli in un array.

Questa array viene passata a scarica_pagine che ne scarica tutti gli URL. Dopo di chè lo script passa la pagina 1.html a ricava_link e il funzionamento procede in modo ricorsivo finchè non viene raggiunto il target.

Codice del ciclo principale dello script

while test $COUNTER -lt $TARGET #finchè COUNTER non raggiunge il TARGET
do
 if test $COUNTER -ne 0 ;then #se non è il primo ciclo
 ricava_link
 fi
 scarica_pagine
done

ricava_link

Questa funzione ricava tutti i link presenti nella pagina che ha per nome il valore della variabile FLAG_NEXT_PAGE,
inizialmente ricava in un array temporanea i contenuti di tutti i parametri href presenti nel sorgente html della pagina.
e stampa a video il numero di link trovati. Poi passa ad analizzare questi link uno ad uno salvando quelli che superano i controlli
nell’array denominata ARRAY_LINK. Ogni link deve corrispondere a questi criteri:

  • Non deve terminare con le seguenti estensioni: css, jpg, ico, gif, png, swf, doc, ppt, xml, pdf, c, txt, gz, zip, deb, jsp;
  • Non deve inziare con: mailto, ftp, #;
  • Se non inizia con http e nemmeno con / viene modificato aggiungendogli davanti l’indirizzo della pagina da cui proviene (relative-link);
  • Se inizia con / gli viene aggiunto davanti solo il dominio della pagina da cui è stato ricavato (root-relative-link)
  • Non deve essere presente nel log delle pagine già scaricate;
  • Non deve essere presente nel log delle pagina non scaricate a causa di un errore restituito da wget;

Una volta analizzata tutta l’array temporanea viene stampato a video il numero dei link VALIDI trovati

Linee di codice rilevanti (anche se ogni linea di codice è rilevante)

grep -i 'href="' "$DIR_PATH$FLAG_NEXT_PAGE".html | sed 's/^.*href="//I' | sed 's/".*$//'

scarica_pagine

Questa funzione scorre l’array denominata ARRAY_LINK e passa ogni link a wget, se la pagina viene scaricata correttamente viene aggiunto il link al log delle pagine scaricate altrimenti viene aggiunto al log degli errori.

Linee di codice rilevanti (anche se ogni linea di codice è rilevante)

wget -O "$DIR_PATH$COUNTER".html -t 3 ${ARRAY_LINK[$indice]} -o "$LOG_WGET"

Comando WGET a cui si passa in input il link con indice $indice dell’array ARRAY_LINK, salva la pagina scaricata nel file “$DIR_PATH$COUNTER”.html e indirizza lo standard output nel log file “$LOG_WGET”, wget tenterà di scaricare la pagina solamente 3 volte.

TODO

Come ogni progetto ha innumerevoli possibilità di miglioramento. Le prossime che volevo applicare sono:

  • Invece di specificare il numero di pagine da scaricare possibilità di specificare la profondità dell’albero delle visite.
  • Nomi delle pagine scaricate più user friendly

3 thoughts on “MBWC – Minimal Bash Web Crawler

  1. Pingback: Tweets that mention MBWC – Minimal Bash Web Crawler | gianlucacrema.com -- Topsy.com

  2. Molti di noi hanno invece pensato…ma che cazzo è bash??Poi se esiste già quell’altro programma, perché non usi quello?

    Poi hanno pensato…molti?? Ma chi??E cosa pensi di fare, scimmiottare Manzoni?

    Comunque articolo molto interessante, peccato solo peccato solo che tutte quelle parole inglesi che voi italianizzate non si possono proprio sentire!!

    Che brutto vizio che avete…però toglimi una curiosità, ma a cosa serve sta cosa? Per avere un elenco infinito di tutte le pagine che si possono raggiungere da una pagina?? Vuoi avere tutto internet sotto controllo??non si può controllare Internet e non ci fermerai!!! Vai a vendere le tue tecnologie in Iran!! Servo del potere!!

Leave a Reply to BiGAlex Cancel reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>