[Flug] Copiare l'archivio HTML della lista

Matteo Bini matteobin@tiepi.it
Ven 8 Nov 2024 20:45:53 CET


Buonasera,
in seguito al dibattito sul futuro della lista di qualche giorno fa [1],
ho provato a copiare gli archivi della suddetta con un semplice script.
Voglio condividere con voi il risultato dei miei tentativi.

Per il grosso del contenuto basta davvero un mero `wget -m
https://lists.linux.it/pipermail/flug/`. Tuttavia per fare un lavoro di fino
sono necessarie alcune opzioni aggiuntive.

$ wget --cut-dirs=2 -m -nH https://lists.linux.it/pipermail/flug/ -R robots.txt -X /images,/listinfo

In questo modo wget, oltre a effettuare la copia specchiata (-m, mirror)
degli archivi della lista del FLUG, non crea le cartelle pipermail e
flug (l'una dentro l'altra), bensì salva tutto nella cartella di lavoro
attuale, grazie a --cut-dirs=2 che dice di non creare i primi due
livelli di cartelle nel salvataggio e grazie a -nH wget non crea la
cartella col nome del dominio (lists.linux.it). Inoltre -R indica di non
scaricare i file chiamati robots.txt e -X d'ignorare i percorsi /images
e /listinfo, dove si trovano rispettivamente i loghi di Mailman e
l'elenco di tutte le liste ospitate su lists.linux.it.

Il comando di prima dovrebbe impiegare circa un quarto d'ora per
scaricare gli archivi della lista del FLUG, con una connessione medio
scarsa.

Potremmo fermarci qua, se non volessimo archiviare pure gli allegati,
che non vengono scaricati in questo modo, poiché sono elencati come
collegamenti nella pagina del messaggio singolo, che presenta il tag
meta robots con l'indicazione di non seguire i collegamenti nella
pagina. Potremmo dire a wget d'ignorare le direttive Robots, ma così
seguirebbe ricorsivamente ogni collegamento, finendo col scaricare tutte
le liste pubbliche ospitate su lists.linux.it. Potremmo inserire delle
discriminanti con le opzioni -A (lista con espressioni regolari degli
elementi da accettare per lo scaricamento), -I (lista delle cartelle da
includere nello scaricamento), -R (lista con espressioni regolari degli
elementi da non scaricare) e -X (lista delle cartelle da escludere dallo
scaricamento). Ho scartato quest'idea perché mi sembrava difficile
scrivere delle opzioni che tenessero conto dei possibili cambiamenti
degli indirizzi dell'archivio, o dell'aggiunta di nuove liste, per
quanto questa ipotesi appaia remota. In più il comando wget risultante
sarebbe diventato piuttosto indecifrabile a colpo d'occhio. Per fortuna
c'è grep!

$ ricerca="$(grep -ir '^URL: *<<a href=".*">.*</a>>$' "$PWD" | sort | uniq)"
$ printf "%s" "$ricerca" | sed 's/^.*:URL: *<<a href="\(.*\)">.*<\/a>>$/\1/i' | wget --cut-dirs=2 -i - -nH -N -x

grep cerca ricorsivamente (-r) nella cartella di lavoro attuale la
dicitura tipica di un allegato nei messaggi di posta della lista,
ignorando la differenza tra maiuscole e minuscole (-i). Dopodiché i
risultati vengono ordinati in ordine alfabetico con sort e scremati da
eventuali doppioni con uniq. Salviamo il risultato di questa ricerca in
una variabile. A questo punto sed estrae soltanto l'URL dall'HTML.
Infine wget scarica i file uno a uno, utilizzando come elenco il
risultato di sed (-i -). A wget sono state aggiunte le opzioni -N, per
applicare la data del file sul server al file scaricato, e -x per
obbligare la creazione delle cartelle indicate nell'URL durante lo
scaricamento, replicando così la struttura dei file dell'archivio della
lista.

Lo scaricamento degli allegati potrebbe impiegare tre quarti d'ora.

Adesso dobbiamo aggiornare l'HTML dell'archivio locale affinché i
collegamenti agli allegati non puntino più a lists.linux.it, ma alla
cartella relativa appena scaricata.

$ printf "%s" "$ricerca" | sed 's/^\(.*\):URL:.*$/\1/' | xargs -L 1 url-allegati-archivio-lista-flug

Passiamo i nomi dei file da modificare a uno script dedicato. -L 1 dice
a xargs di eseguire il comando seguente per ogni riga non vuota ricevuta
dall'operazione precedente, mettendo quella linea come argomento del
comando specificato. Nel nostro caso, xargs chiama
url-allegati-archivio-lista-flug per ogni file da modificare, col nome
del file come primo parametro.

#!/bin/sh

set -e

file="$1"

if [ -f "$file" ] && [ -r "$file" ]; then
	sed -i.bak 's/^\(URL: *<<a href="\)https\?:\/\/lists.linux.it\/pipermail\/flug\/\(.*\)\(">\)https\?:\/\/lists.linux.it\/pipermail\/flug\/\(.*<\/a>>\)$/\1..\/\2\3..\/\4/i' "$file"
	touch -r "${file}.bak" "$file"
	rm "${file}.bak"
fi

Questo script non fa altro che rimaneggiare l'URL dell'allegato e la sua
rappresentazione, sostituendo lists.linux.it/pipermail/flug con ../,
visto che la cartella degli allegati si trova sopra quella della
suddivisione in mesi che Pipermail adotta per smistare i messaggi.
Infine il tocco di classe, per non perdere la data originale del server,
sed fa una copia del file di partenza, aggiungendo al nome il suffisso
.bak (-i.bak), cosicché touch possa impostare la data del file nuovo
uguale all'originale (-r indica di utilizzare la data del file
specificato di seguito). Ovviamente la copia viene cancellata, espletato
il suo scopo.

Commenti? Suggerimenti? Vorrei provare questi script su NetBSD per
verificare che siano abbastanza Unix agnostici, dato che credo di aver
utilizzato delle estensioni di GNU di sed e forse anche di grep.
Tuttavia al momento sulla mia installazione di NetBSD non ho accesso a
Internet. In conclusione lo script assolve dignitosamente allo scopo
prefissato. Potrei mettere un cron sul serverone per copiare l'archivio
di questa lista in automatico ogni settimana.

In allegato a questo messaggio trovate entrambi gli script. Adesso
potete realizzare il vostro sogno segreto: avere una copia dell'archivio
HTML della lista del FLUG! Potete non ringraziarmi, però so che nel
profondo era ciò che desideravate con furore.

A buon rendere.


[1] https://lists.linux.it/pipermail/flug/2024-October/026877.html

-- 
Matteo Bini
-------------- parte successiva --------------
#!/bin/sh

set -e

wget --cut-dirs=2 -m -nH https://lists.linux.it/pipermail/flug/ -R robots.txt -X /images,/listinfo
ricerca="$(grep -ir '^URL: *<<a href=".*">.*</a>>$' "$PWD" | sort | uniq)"
printf "%s" "$ricerca" | sed 's/^.*:URL: *<<a href="\(.*\)">.*<\/a>>$/\1/i' | wget --cut-dirs=2 -i - -nH -N -x
printf "%s" "$ricerca" | sed 's/^\(.*\):URL:.*$/\1/' | xargs -L 1 url-allegati-archivio-lista-flug
-------------- parte successiva --------------
#!/bin/sh

set -e

file="$1"

if [ -f "$file" ] && [ -r "$file" ]; then
	sed -i.bak 's/^\(URL: *<<a href="\)https\?:\/\/lists.linux.it\/pipermail\/flug\/\(.*\)\(">\)https\?:\/\/lists.linux.it\/pipermail\/flug\/\(.*<\/a>>\)$/\1..\/\2\3..\/\4/i' "$file"
	touch -r "${file}.bak" "$file"
	rm "${file}.bak"
fi


Maggiori informazioni sulla lista flug