Como analisar centenas de arquivos de código-fonte html no shell?

23

Eu tenho algumas centenas de arquivos de código-fonte html. Eu preciso extrair o conteúdo de um <div>elemento específico de cada um desses arquivos, então eu vou escrever um script para percorrer cada arquivo. A estrutura do elemento é assim:

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

Alguém pode sugerir um método pelo qual eu possa extrair a div the_div_ide todos os elementos filho e conteúdo de um arquivo usando a linha de comando do linux?

Conorgriffin
fonte

Respostas:

27

O pacote html-xml-utils , disponível na maioria das principais distribuições Linux, possui várias ferramentas úteis ao lidar com documentos HTML e XML. Particularmente útil para o seu caso é o hxselectque lê da entrada padrão e extrai elementos com base nos seletores CSS. Seu caso de uso seria semelhante a:

hxselect '#the_div_id' <file

Você pode receber uma reclamação sobre a entrada não ser bem formada, dependendo do que você está alimentando. Essa reclamação é apresentada por erro padrão e, portanto, pode ser facilmente suprimida, se necessário. Uma alternativa para isso seria usar o pacote HTML :: PARSER do Perl; no entanto, deixarei isso para alguém com habilidades em Perl menos enferrujado que as minhas.

Steven D
fonte
1
hxselecté mais exigente quanto ao formato de entrada do que pup. Por exemplo, eu estou ficando Input is not well-formed. (Maybe try normalize?)com hxselect onde pupapenas analisá-lo.
AB
12

Experimente pup, uma ferramenta de linha de comando para processar HTML. Por exemplo:

pup '#the_div_id' < file.html
Trevor Dixon
fonte
Terrrrrrrific!
CC
4

Aqui está um script Perl não testado que extrai <div id="the_div_id">elementos e seu conteúdo usando 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;
}

Se você é alérgico ao Perl, o Python possui HTMLParser.

PS Não tente usar expressões regulares. .

Gilles 'SO- parar de ser mau'
fonte
1
O Python possui toda a documentação doc.scrapy.org/en/latest/intro/overview.html ;)
AB
1

Aqui está o Ex one-liner para extrair essa parte de cada arquivo:

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

Para salvar / substituir no local, mude -cqa!para -cxae remova a %pseção. Para recursividade, considere usar globbing ( **/*.html).

Basicamente, para cada buffer / arquivo ( bufdo), ele executa as seguintes ações:

  • /pattern - encontre o padrão
  • norm - comece a simular pressionamentos de tecla Vi normais
    • n - pule para o próximo padrão (necessário no modo Ex)
    • vatd- remova a seção de tag externa selecionada (consulte: saltando entre tags html )
    • ggdG- remova todo o buffer (equivalente a :%d)
    • "2p - cole novamente o texto excluído anteriormente

Talvez não seja muito eficiente e não POSIX ( :bufdo), mas deve funcionar.

kenorb
fonte
nota bufdo não é POSIX pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
Steven Penny