¿Cómo analizar cien archivos de código fuente html en shell?

23

Tengo un par de cientos de archivos de código fuente HTML. Necesito extraer el contenido de un <div>elemento particular de cada uno de estos archivos, así que voy a escribir un script para recorrer cada archivo. La estructura del elemento es así:

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

¿Alguien puede sugerir un método mediante el cual pueda extraer el div the_div_idy todos los elementos secundarios y el contenido de un archivo utilizando la línea de comandos de Linux?

conorgriffin
fuente

Respuestas:

27

El paquete html-xml-utils , disponible en la mayoría de las principales distribuciones de Linux, tiene una serie de herramientas que son útiles cuando se trata de documentos HTML y XML. Particularmente útil para su caso es el hxselectque lee de la entrada estándar y extrae elementos basados ​​en selectores CSS. Su caso de uso se vería así:

hxselect '#the_div_id' <file

Es posible que reciba una queja sobre la entrada no está bien formada, dependiendo de lo que está alimentando. Esta queja se da sobre el error estándar y, por lo tanto, puede suprimirse fácilmente si es necesario. Una alternativa a esto sería usar el paquete HTML :: PARSER de Perl; sin embargo, se lo dejaré a alguien con habilidades de Perl menos oxidado que el mío.

Steven D
fuente
1
hxselectes más exigente con el formato de entrada que pup. Por ejemplo, estoy llegando Input is not well-formed. (Maybe try normalize?)a hxselect donde pupsolo lo analizo.
AB
12

Pruebe pup, una herramienta de línea de comandos para procesar HTML. Por ejemplo:

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

Aquí hay un script de Perl no probado que extrae <div id="the_div_id">elementos y sus contenidos 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;
}

Si eres alérgico a Perl, Python sí HTMLParser.

PD No intentes usar expresiones regulares. .

Gilles 'SO- deja de ser malvado'
fuente
1
Python tiene todo el doc.scrapy.org/en/latest/intro/overview.html ;)
AB
1

Aquí está Ex one-liner para extraer esa parte de cada archivo:

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

Para guardar / reemplazar en el lugar, el cambio -cqa!en -cxay quitar %psección. Para la recursividad, considere usar globbing ( **/*.html).

Básicamente, para cada búfer / archivo ( bufdo), realiza las siguientes acciones:

  • /pattern - encuentra el patrón
  • norm - Comience a simular pulsaciones de teclas normales de Vi
    • n - saltar al siguiente patrón (requerido en modo Ex)
    • vatd- eliminar la sección de etiqueta externa seleccionada (ver: saltar entre etiquetas html )
    • ggdG- eliminar todo el búfer (equivalente a :%d)
    • "2p - volver a pegar el texto eliminado anteriormente

Quizás no sea muy eficiente y no POSIX ( :bufdo), pero debería funcionar.

kenorb
fuente
note que bufdo no es POSIX pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
Steven Penny