Analyser du HTML dans Bash – CloudSavvy IT
J’ai un processus où je dois copier toutes les images d’une page Web. J’avais l’habitude d’exécuter ce processus avec xmllint
, qui traitera un fichier XML ou HTML et imprimera les entrées que vous spécifiez. Mais lorsque mon fournisseur d’hébergement de serveur a mis à niveau ses systèmes, il n’a pas inclus xmllint
. J’ai donc dû trouver un autre moyen d’extraire une liste d’images d’une page HTML. Il s’avère que vous pouvez le faire dans Bash.
Vous ne pensez peut-être pas que Bash peut analyser des fichiers de données, mais il le peut avec une réflexion intelligente. Bash, comme les autres shells UNIX avant lui, peut analyser les lignes une par une à partir d’un fichier via le read
déclaration.
Par défaut, le read
L’instruction analyse une ligne de données et la divise en champs. D’habitude, read
divise les champs à l’aide d’espaces et de tabulations, avec des retours à la ligne se terminant chaque ligne, mais vous pouvez modifier ce comportement en définissant le séparateur de champs interne (IFS
) et le délimiteur de fin de ligne (-d
).
Pour analyser un fichier HTML en utilisant read
, met le IFS
à un symbole supérieur à (>
) et le délimiteur à un symbole inférieur à (<
). Chaque fois que Bash scanne une ligne, il analyse jusqu’à la suivante <
(le début d’une balise HTML) puis divise ces données à chaque >
(la fin d’une balise HTML). Cet exemple de code prend une ligne d’entrée et divise les données dans le TAG
et VALUE
variables :
local IFS='>' read -d '<' TAG VALUE
Explorons comment cela fonctionne. Considérez ce simple fichier HTML :
<img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png" alt="My logo" /> <p>some text</p>
La première fois read
analyse ce fichier, il s’arrête au premier <
symbole. Depuis <
est le premier caractère de cet exemple d’entrée, ce qui signifie que Bash trouve une chaîne vide. La résultante TAG
et VALUE
les chaînes sont également vides. Mais c’est bien pour mon cas d’utilisation.
La prochaine fois que Bash lit l’entrée, il obtient img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png"↲alt="My logo" />↲
avec une nouvelle ligne juste avant l’alt, et s’arrête avant le <
symbole sur la ligne suivante. Puis read
divise la ligne au >
symbole, qui laisse TAG
avec img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png"↲alt="My logo" /
et VALUE
avec une nouvelle ligne vide.
La troisième fois read
analyse le fichier HTML, il obtient p>some text
. Bash divise la chaîne au >
résultant en TAG
contenant p
et VALUE
avec some text
.
Maintenant que vous comprenez comment utiliser read
, il est facile d’analyser un fichier HTML plus long avec Bash. Commencez par une fonction Bash appelée xmlgetnext
pour analyser les données en utilisant read
, puisque vous le ferez encore et encore dans le script. j’ai nommé ma fonction xmlgetnext
pour me rappeler que c’est un remplacement pour Linux xmllint
programme, mais j’aurais pu tout aussi bien le nommer htmlgetnext
.
xmlgetnext () { local IFS='>' read -d '<' TAG VALUE }
Maintenant appelle ça xmlgetnext
fonction pour analyser le fichier HTML. C’est mon complet htmltags
scénario:
#!/bin/sh # print a list of all html tags xmlgetnext () { local IFS='>' read -d '<' TAG VALUE } cat $1 | while xmlgetnext ; do echo $TAG ; done
La dernière ligne est la clé. Il parcourt le fichier en utilisant xmlgetnext
pour analyser le HTML et n’imprime que le TAG
entrées. Et à cause de comment echo
fonctionne avec les séparateurs de champs standard, toutes les lignes comme img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png"↲alt="My logo" /
qui contiennent un saut de ligne sont imprimés sur une seule ligne, comme img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png" alt="My logo" /
.
Pour récupérer uniquement la liste des images, j’exécute la sortie de ce script via grep
pour n’imprimer que les lignes qui ont un img
balise au début de la ligne.