Linux bash: estrarre tutti i link da un sito web

link Esistono molti tool sulla rete per estrarre i link da una pagina web, ma non ne ho trovati altrettanti in grado di scansionare ricorsivamente tutte le pagine di un sito web e fornire in output una lista senza duplicati dei links presenti.

Questo script bash si  può rivelare particolarmente utile quando sia necessario compilare una serie di redirect, per non perdere le indicizzazioni sui motori di ricerca di un sito che sia stato rinnovato. Un altro esempio di utilizzo è per controllare eventuali links interrotti, a questo scopo si può intergrare con il programma PHP che ho pubblicato qui: PHP cURL: una classe per controllare link interrotti, status code e nxdomain in parallelo

Lo script necessita che sia installato lynx che è un browser testuale. Questo programma, oltre naturalmente a permettere la navigazione del web su terminali ad interfaccia di comando, mette a disposizione anche una serie di opzioni allettanti per setacciare le pagine web. Nel caso abbiate una distribuzione Linux Ubuntu, l’installazione è molto semplice: sudo apt-get install lynx. Altrettanto semplice l’installazione su CentOS: sudo yum install lynx. Per tutte le ditribuzioni Linux (e anche per Windows!) comunque è disponibile il download dei pacchetti universali qui: http://lynx.invisible-island.net/lynx2.8.8/index.html

Lo script ha i seguenti 3 parametri:

  1. -u= (–url=) La URL del sito da processare. Esempio: -u=miosito.com
  2. -l= (–links=) Il tipo di links da estrarre internal: estrae solo in link interni, external: solo quelli esterni, se viene omesso vengono estratti tutti i links. Esempio -l=external
  3. -o= (–output=) Il nome del file di output, se viene omesso il default è: ‘extractlinks.out’. Esempio: -o=lista.txt

Premetto che non sono un bravo programmatore bash, dunque la scrittura del codice non è particolarmente raffinata, comunque visto che l’utilizzo sarà saltuario, come puro strumento di lavoro. Il codice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/bin/bash
#First check if lynx is installed...
type lynx >/dev/null 2>&1 || { echo >&2 "I require lynx but it's not installed.  Aborting."; exit 1; }
for i in "$@"
do
	case $i in
		-u=*|--url=*)
		URL="${i#*=}"
		shift
		;;
		-o=*|--output=*)
		OUT="${i#*=}"
		shift
		;;
		-l=*|--links=*)
		LINKS="${i#*=}"
		shift
		;;
	esac
done
if [ -z "$OUT" ] ; then
	OUT="extractlinks.out"
fi
if [[ $URL == *[\/'!'@#\$%^\&*()_+:]* ]] ; then
	echo "Invalid url! It must contain only letters, numbers and dots" >&2
	exit 1
fi
DOTS=$(grep -o "\." <<< "$URL" | wc -l)
if [[ "$DOTS" < 1 ]] ; then
	echo "Invalid url!" >&2
	exit 1
fi
if [ ! -e "$OUT" ] ; then
    touch "${OUT}"
else 
	> "${OUT}"    
fi
ESCAPEDURL=${URL//./\\.}
KEYURL=${ESCAPEDURL%\\*}
for i in $(lynx -dump -listonly 'http://'${URL}'/' | awk '/http/{print $2}' | grep http\:\/\/${KEYURL})
do
	echo -ne "\r\033[KParsing: ${i}"
	if [[ "$LINKS" == "external" ]] ; then
		lynx -dump -listonly $i | awk '/http/{print $2}' | grep '^http' | grep -v http\:\/\/"${KEYURL}" >> "${OUT}"
	elif [[ "$LINKS" == "internal" ]] ; then
		lynx -dump -listonly $i | awk '/http/{print $2}' | grep "^http\:\/\/${KEYURL}" >> "${OUT}"
	else
		lynx -dump -listonly $i | awk '/http/{print $2}' | grep '^http' >> "${OUT}"
	fi
done
echo -ne "\r\033[KSorting and removing duplicates..."
sort "${OUT}" | uniq >> tmp.txt
mv tmp.txt "${OUT}"
printf "\ndone!\n"

Un esempio di utilizzo:

$./extractlinks.sh -u=elzevira.com -l=internal -o=links.txt

Il risultato viene ordinato alfabeticamente e vengono anche eliminati i duplicati:

http://elzevira.com/
http://elzevira.com/articoli-categorie-pagine-chiariamo-la-loro-differenza-in-wordpress/
http://elzevira.com/articoli-categorie-pagine-chiariamo-la-loro-differenza-in-wordpress/#comments
http://elzevira.com/articolo21-powered-by-elzevira/
http://elzevira.com/articolo21-powered-by-elzevira/#comments
http://elzevira.com/author/admin/
http://elzevira.com/author/spadamar/
http://elzevira.com/blog/
http://elzevira.com/category/news/
http://elzevira.com/category/programmazione-web/
http://elzevira.com/category/wordpress/
http://elzevira.com/chi-siamo/
http://elzevira.com/come-inserire-un-video-youtube-in-una-pagina-web-in-modalita-responsive-e-leggera/
http://elzevira.com/come-inserire-un-video-youtube-in-una-pagina-web-in-modalita-responsive-e-leggera/#comments
http://elzevira.com/comments/feed/
http://elzevira.com/contatti/
http://elzevira.com/dove-siamo/
http://elzevira.com/editoria/
http://elzevira.com/editoria/feed/
http://elzevira.com/elzevira-e-anche-su-facebook/
http://elzevira.com/elzevira-e-anche-su-facebook/#comments
http://elzevira.com/feed/
http://elzevira.com/grafica/
http://elzevira.com/grafica/feed/
http://elzevira.com/limpatto-di-internet-in-italia/
http://elzevira.com/limpatto-di-internet-in-italia/#comments
http://elzevira.com/nel-2015-7-apparecchi-connessi-a-testa/
http://elzevira.com/nel-2015-7-apparecchi-connessi-a-testa/#comments
http://elzevira.com/perche-affidarsi-a-noi/
http://elzevira.com/portfolio/
http://elzevira.com/realizzazione-siti-internet/
http://elzevira.com/realizzazione-siti-internet/feed/
http://elzevira.com/web-marketing-e-posizionamento/
http://elzevira.com/web-marketing-e-posizionamento/feed/
http://elzevira.com/wordpress-cosa-e-un-tema-figlio-child-theme-e-perche-utilizzarlo/
http://elzevira.com/wordpress-cosa-e-un-tema-figlio-child-theme-e-perche-utilizzarlo/#comments
http://elzevira.com/wp-content/uploads/2012/04/articolo21_orig.jpg
http://elzevira.com/wp-content/uploads/2012/12/wordpress-logo-stacked-rgb.png
http://elzevira.com/wp-content/uploads/2015/10/temafiglio.png
http://elzevira.com/wp-content/uploads/2015/11/YouTube_logo_2015.jpg

Suggerisco di fare attenzione a non utilizzarlo con siti web particolarmente grandi perché potrebbe impiegare molto tempo per fare il parsing di tutte le pagine e di tutti i link contenuti. Inoltre potrebbero esserci dei problemi con i siti che limitano l’accesso alle loro pagine in base al tempo e allo user agent utilizzato, lo script potrebbe essere riconosciuto come un bot e l’IP da dove viene eseguito potrebbe essere bannato.

Volendo è possibile modificare lo script per aggiungere dei parametri al lancio di lynx per modificare lo user agent, aggiungere un timeout o anche per introdurre dei ritardi nelle chiamate alle singole pagine. Qui c’è l’elenco completo dei parametri di lynx: http://linux.die.net/man/1/lynx

Riferimenti:
LYNX – The Text Web-Browser
Bash Reference Manual
Programmazione/LinguaggioBash – Wiki di ubuntu-it