Extraction d’images à partir de HTML avec Bash : une approche alternative
Dans le cadre d’un processus nécessitant la copie de toutes les images d’une page web, j’utilisais auparavant xmllint
, un outil permettant de traiter des fichiers XML ou HTML et d’afficher les données spécifiées. Cependant, suite à une mise à niveau des systèmes de mon hébergeur, xmllint
n’était plus inclus. J’ai donc dû trouver une autre méthode pour extraire la liste des images d’une page HTML. Il s’avère que cela peut être réalisé directement avec Bash.
Bien qu’il ne soit pas intuitif de penser que Bash puisse analyser des fichiers de données, il en est tout à fait capable avec un peu d’ingéniosité. Bash, comme d’autres shells UNIX avant lui, peut parcourir un fichier ligne par ligne grâce à la commande read
.
Par défaut, la commande read
lit une ligne de données et la divise en champs. Généralement, read
utilise les espaces et les tabulations comme séparateurs, avec un retour à la ligne marquant la fin de chaque ligne. Il est toutefois possible de modifier ce comportement en configurant le séparateur de champ interne (IFS
) et le délimiteur de fin de ligne (-d
).
Pour analyser un fichier HTML à l’aide de read
, on peut définir IFS
comme le symbole supérieur à (>
) et le délimiteur comme le symbole inférieur à (<
). Ainsi, à chaque lecture, Bash analyse jusqu’au prochain <
(début d’une balise HTML) puis divise les données en utilisant >
(fin d’une balise HTML) comme séparateur. L’exemple de code suivant illustre la division des données en variables TAG
et VALUE
:
local IFS='>' read -d '<' TAG VALUE
Analysons le fonctionnement de ce code. Considérons ce fragment HTML simple :
<img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png" alt="Mon logo" /> <p>du texte</p>
Lors de la première analyse, read
s’arrête au premier symbole <
. Puisque <
est le premier caractère de l’entrée, Bash trouve une chaîne vide. Par conséquent, les variables TAG
et VALUE
sont également vides. Néanmoins, cela convient parfaitement à mon cas d’utilisation.
La fois suivante, Bash lit l’entrée suivante: img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png"↲alt="Mon logo" />↲
avec un retour à la ligne juste avant « alt », et s’arrête avant le symbole <
de la ligne suivante. Puis, read
divise la ligne en utilisant >
comme séparateur, ce qui assigne à TAG
la valeur img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png"↲alt="Mon logo" /
et à VALUE
une nouvelle ligne vide.
Lors de la troisième lecture, read
récupère p>du texte
. Bash divise cette chaîne au niveau du symbole >
, attribuant ainsi p
à TAG
et du texte
à VALUE
.
Maintenant que le fonctionnement de read
est clair, il est aisé d’analyser un fichier HTML plus conséquent avec Bash. L’approche consiste à créer une fonction Bash nommée xmlgetnext
pour gérer l’analyse des données à l’aide de read
, étant donné qu’elle sera utilisée à plusieurs reprises dans le script. J’ai choisi le nom xmlgetnext
en clin d’œil au programme Linux xmllint
, mais j’aurais tout aussi bien pu l’appeler htmlgetnext
.
xmlgetnext () { local IFS='>' read -d '<' TAG VALUE }
Voici maintenant le script complet htmltags
qui utilise la fonction xmlgetnext
pour analyser le fichier HTML :
#!/bin/sh # Afficher une liste de toutes les balises HTML xmlgetnext () { local IFS='>' read -d '<' TAG VALUE } cat $1 | while xmlgetnext ; do echo $TAG ; done
La dernière ligne est essentielle. Elle utilise xmlgetnext
pour parcourir et analyser le fichier HTML, affichant uniquement les valeurs de TAG
. De plus, grâce au comportement d’echo
avec les séparateurs de champs, toutes les lignes telles que img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png"↲alt="Mon logo" /
(contenant un retour à la ligne) sont affichées sur une seule ligne : img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png" alt="Mon logo" /
.

Pour extraire uniquement la liste des images, on peut canaliser la sortie de ce script vers grep
afin de n’afficher que les lignes commençant par la balise img
.