Поиск по сайту:

Парсинг HTML в Bash


У меня есть процесс, в котором мне нужно скопировать все изображения с веб-страницы. Раньше я запускал этот процесс с помощью xmllint, который будет обрабатывать файл XML или HTML и распечатывать указанные вами записи. Но когда мой хост-провайдер обновил свои системы, они не включили xmlint. Поэтому мне пришлось найти другой способ извлечь список изображений из HTML-страницы. Оказывается, вы можете сделать это в Bash.

Вы можете не думать, что Bash может анализировать файлы данных, но это возможно, если подумать. Bash, как и другие оболочки UNIX до него, может анализировать строки из файла по одной за раз с помощью встроенного оператора read.

По умолчанию оператор read сканирует строку данных и разбивает ее на поля. Обычно read разбивает поля с помощью пробелов и табуляции, при этом каждая строка заканчивается новой строкой, но вы можете изменить это поведение, установив значение внутреннего разделителя полей (IFS) и конец- межстрочный разделитель (-d).

Чтобы проанализировать файл HTML с помощью read , установите для IFS символ «больше» (>), а в качестве разделителя — символ «меньше». (<). Каждый раз, когда Bash сканирует строку, он выполняет синтаксический анализ до следующего < (начало HTML-тега), а затем разбивает эти данные на каждый > (конец HTML-тега). ). Этот пример кода принимает строку ввода и разбивает данные на переменные TAG и VALUE:

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

Давайте посмотрим, как это работает. Рассмотрим этот простой файл HTML:

<img src="logo.png"
alt="My logo" />
<p>some text</p>

При первом анализе read этого файла он останавливается на первом символе <. Поскольку < является первым символом этого примера ввода, это означает, что Bash находит пустую строку. Результирующие строки TAG и VALUE также пусты. Но это нормально для моего варианта использования.

В следующий раз, когда Bash читает ввод, он получает img src=\logo.png\↲alt=\Мой логотип\ />↲ с новой строкой прямо перед alt и останавливается перед символ < на следующей строке. Затем read разделяет строку по символу >, оставляя TAG с img src=\logo.png\↲alt =\Мой логотип\ / и VALUE с пустой новой строкой.

В третий раз, когда read анализирует файл HTML, он получает p>какой-то текст. Bash разбивает строку на >, в результате чего TAG содержит p и VALUE с некоторым текстом .

Теперь, когда вы понимаете, как использовать read, легко проанализировать более длинный HTML-файл с помощью Bash. Начните с функции Bash с именем xmlgetnext для анализа данных с помощью read, так как вы будете делать это снова и снова в скрипте. Я назвал свою функцию xmlgetnext, чтобы напомнить себе, что это замена программе Linux xmllint, но я мог бы так же легко назвать ее htmlgetnext.

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

Теперь вызовите эту функцию xmlgetnext для анализа HTML-файла. Это мой полный скрипт htmltags:

#!/bin/sh
# print a list of all html tags

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

cat $1 | while xmlgetnext ; do echo $TAG ; done

Последняя строка является ключевой. Он перебирает файл с помощью xmlgetnext для анализа HTML и выводит только записи TAG. И из-за того, как echo работает со стандартными разделителями полей, любые строки, такие как img src=\logo.png\↲alt=\My logo\ /, которые содержать новую строку, которая будет напечатана в одной строке, как img src=\logo.png\ alt=\My logo\ /.

Чтобы получить только список изображений, я запускаю выходные данные этого скрипта через grep и печатаю только те строки, которые имеют тег img в начале строки.