Как разобрать сто файлов HTML исходного кода в оболочке?

23

У меня есть пара сотен файлов HTML исходного кода. Мне нужно извлечь содержимое определенного <div>элемента из каждого из этих файлов, поэтому я собираюсь написать скрипт для циклического прохождения каждого файла. Структура элемента выглядит следующим образом:

<div id='the_div_id'>
  <div id='some_other_div'>
  <h3>Some content</h3>
  </div>
</div>

Может кто-нибудь предложить метод, с помощью которого я могу извлечь div the_div_idи все дочерние элементы и контент из файла с помощью командной строки Linux?

conorgriffin
источник

Ответы:

27

Пакет html-xml-utils , доступный в большинстве основных дистрибутивов Linux, содержит ряд инструментов, которые полезны при работе с документами HTML и XML. Особенно полезным для вашего случая является то, hxselectчто читает со стандартного ввода и извлекает элементы на основе селекторов CSS. Ваш вариант использования будет выглядеть так:

hxselect '#the_div_id' <file

Вы можете получить жалобу на то, что входные данные плохо сформированы, в зависимости от того, что вы их кормите. Эта жалоба подается по стандартной ошибке и поэтому может быть легко подавлена ​​при необходимости. Альтернативой этому может быть использование пакета Perl HTML :: PARSER; однако, я оставлю это кому-то с навыками Perl менее ржавыми, чем мои собственные.

Стивен Д
источник
1
hxselectболее требователен к формату ввода, чем pup. Например, я получаю Input is not well-formed. (Maybe try normalize?)с, hxselect где pupпросто анализирую это.
AB
12

Попробуйте pup, инструмент командной строки для обработки HTML. Например:

pup '#the_div_id' < file.html
Тревор Диксон
источник
Terrrrrrfic!
CC
4

Вот непроверенный Perl-скрипт, который извлекает <div id="the_div_id">элементы и их содержимое с помощью HTML::TreeBuilder.

#!/usr/bin/env perl
use strict;
use warnings;
use HTML::TreeBuilder;
foreach my $file_name (@ARGV) {
    my $tree = HTML::TreeBuilder->new;
    $tree->parse_file($file_name);
    for my $subtree ($tree->look_down(_tag => "div", id => "the_div_id")) {
        my $html = $subtree->as_HTML;
        $html =~ s/(?<!\n)\z/\n/;
        print $html;
    }
    $tree = $tree->delete;
}

Если у вас аллергия на Perl, у Python есть HTMLParser.

PS Не пытайтесь использовать регулярные выражения. ,

Жиль "ТАК - перестань быть злым"
источник
1
Python имеет целый doc.scrapy.org/en/latest/intro/overview.html ;)
AB
1

Вот Ex one-liner для извлечения этой части из каждого файла:

ex -s +'bufdo!/<div.*id=.the_div_id/norm nvatdggdG"2p' +'bufdo!%p' -cqa! *.html

Чтобы сохранить / заменить на месте, перейдите -cqa!в-cxa%p раздел и удалите его . Для рекурсивности рассмотрите использование globbing ( **/*.html).

Это в основном для каждого буфера / файла ( bufdo), он выполняет следующие действия:

  • /pattern - найти образец
  • norm - начать симулировать нормальные нажатия клавиш Vi
    • n - перейти к следующему шаблону (требуется в режиме Ex)
    • vatd- удалить выбранный раздел внешнего тега (см. переход между HTML-тегами )
    • ggdG - удалить весь буфер (эквивалентно :%d )
    • "2p - повторно вставьте ранее удаленный текст

Может быть, не очень эффективный и не POSIX ( :bufdo), но он должен работать.

kenorb
источник
примечание: bufdo - это не POSIX. pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
Стивен Пенни,