Analisi dell'HTML in Bash

0
140

Ho un processo in cui ho bisogno di copiare tutte le immagini da un web pagina. Ero solito eseguire questo processo con xmllint, che elaborerà un file XML o HTML e stamperà le voci specificate. Ma quando il mio provider host del server ha aggiornato i propri sistemi, non includeva xmllint. Quindi ho dovuto trovare un altro modo per estrarre un elenco di immagini da una pagina HTML. Si scopre che puoi farlo in Bash.

La dichiarazione di lettura

Puoi non pensare che Bash possa analizzare i file di dati, ma può farlo con un pensiero intelligente. Bash, come altre shell UNIX prima di essa, può analizzare le righe una alla volta da un file tramite l'istruzione read incorporata.

Per impostazione predefinita, l'istruzione read esegue la scansione di una riga di dati e la suddivide in campi. Di solito, read divide i campi utilizzando spazi e tab, con nuove righe che terminano ogni riga, ma è possibile modificare questo comportamento impostando il valore del Separatore di campo interno (IFS) e il delimitatore di fine riga (-d).

< p>Per analizzare un file HTML utilizzando read , imposta IFS su un simbolo di maggiore di (>) e il delimitatore su un simbolo di minore di (<). Ogni volta che Bash esegue la scansione di una riga, analizza fino al successivo < (l'inizio di un tag HTML) quindi suddivide i dati in corrispondenza di ogni > (la fine di un tag HTML). Questo codice di esempio prende una riga di input e divide i dati nelle variabili TAG e VALUE:

local IFS='>' leggi -d '<' TAG VALUE

Esploriamo come funziona. Considera questo semplice file HTML:

<img src=”logo.png” alt=”Il mio logo” /> <p>del testo</p> Pubblicità

La prima volta che read analizza questo file, si ferma al primo < simbolo. Poiché < è il primo carattere di questo input di esempio, il che significa che Bash trova una stringa vuota. Anche le stringhe TAG e VALUE risultanti sono vuote. Ma va bene per il mio caso d'uso.

La prossima volta che Bash legge l'input, ottiene img src=”logo.png”↲alt=”My logo” />↲ con un newline subito prima di alt e si ferma prima di < simbolo sulla riga successiva. Quindi leggi divide la riga in > simbolo, che lascia TAG con img src=”logo.png”↲alt=”My logo”/e VALUE con una nuova riga vuota.

La terza volta che la lettura analizza il file HTML, ottiene p>del testo. Bash divide la stringa in > risultante in TAG contenente p e VALUE con del testo .

Un semplice parser

Ora che hai capito come usare read, è facile analizzare un file HTML più lungo con Bash. Inizia con una funzione Bash chiamata xmlgetnext per analizzare i dati usando read , poiché lo farai ancora e ancora nello script. Ho chiamato la mia funzione xmlgetnext per ricordarmi che questo è un sostituto del programma xmllint di Linux, ma avrei potuto chiamarlo altrettanto facilmente htmlgetnext .

xmlgetnext () { local IFS='>' leggi -d '<' TAG VALUE }

Ora chiama la funzione xmlgetnext per analizzare il file HTML. Questo è il mio script htmltag completo:

#!/bin/sh # stampa un elenco di tutti i tag html xmlgetnext () { local IFS='>' leggi -d '<' TAG VALORE } cat $1 | mentre xmlgetnext ; fai echo $TAG ; done

L'ultima riga è la chiave. Esegue il ciclo attraverso il file utilizzando xmlgetnext per analizzare l'HTML e stampa solo le voci TAG. E a causa del modo in cui echo opera con i separatori di campo standard, qualsiasi riga come img src=”logo.png”↲alt=”My logo”/che contiene una nuova riga viene stampata su una singola riga, come img src=”logo.png ” alt=”Il mio logo” /.

Parsing HTML in Bash

Advertisement

Per recuperare solo l'elenco delle immagini, eseguo l'output di questo script tramite grep per stampare solo le righe che hanno un tag img al inizio della linea.