Wie man hundert HTML-Quellcodedateien in der Shell parst?

23

Ich habe ein paar hundert HTML-Quellcode-Dateien. Ich muss den Inhalt eines bestimmten <div>Elements aus jeder dieser Dateien extrahieren, damit ich ein Skript schreiben kann, das die einzelnen Dateien durchläuft. Die Elementstruktur ist wie folgt:

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

Kann jemand eine Methode vorschlagen, mit der ich das div the_div_idund alle untergeordneten Elemente und Inhalte aus einer Datei mit der Linux-Befehlszeile extrahieren kann ?

conorgriffin
quelle

Antworten:

27

Das Paket html-xml-utils , das in den meisten großen Linux-Distributionen verfügbar ist, enthält eine Reihe von Tools, die für den Umgang mit HTML- und XML-Dokumenten hilfreich sind. Besonders nützlich für Ihren Fall ist hxselectdas Lesen von Standardeingaben und Extrahieren von Elementen basierend auf CSS-Selektoren. Ihr Anwendungsfall würde folgendermaßen aussehen:

hxselect '#the_div_id' <file

Es kann vorkommen, dass Sie eine Beschwerde erhalten, dass der Eingang nicht richtig geformt ist, je nachdem, was Sie ihm zuführen. Diese Reklamation wird über Standardfehler ausgegeben und kann somit bei Bedarf einfach unterdrückt werden. Eine Alternative dazu wäre die Verwendung des HTML :: PARSER-Pakets von Perl. Ich überlasse dies jedoch jemandem mit Perl-Kenntnissen, der weniger rostig ist als ich.

Steven D
quelle
1
hxselectist wählerischer in Bezug auf das Eingabeformat als pup. Zum Beispiel komme ich Input is not well-formed. (Maybe try normalize?)mit hxselect dem pupParsen klar.
AB
12

Versuchen Sie pup, ein Befehlszeilenprogramm zum Verarbeiten von HTML. Beispielsweise:

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

Hier ist ein ungetestetes Perl-Skript, mit dem <div id="the_div_id">Elemente und deren Inhalte extrahiert werdenHTML::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;
}

Wenn Sie allergisch gegen Perl sind, hat Python HTMLParser .

PS Versuchen Sie nicht, reguläre Ausdrücke zu verwenden. .

Gilles 'SO - hör auf böse zu sein'
quelle
1

Hier ist ein Ex-Einzeiler, um diesen Teil aus jeder Datei zu extrahieren:

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

Zum Speichern / Ersetzen wechseln Sie -cqa!in -cxaden %pAbschnitt und entfernen ihn . Erwägen Sie aus Gründen der Rekursivität die Verwendung von globbing ( **/*.html).

Grundsätzlich werden für jeden Puffer / jede Datei ( bufdo) die folgenden Aktionen ausgeführt:

  • /pattern - Finde das Muster
  • norm - Starten Sie die Simulation normaler Vi-Tastenanschläge
    • n - zum nächsten Muster springen (im Ex-Modus erforderlich)
    • vatd- Entferne den ausgewählten äußeren Tag-Bereich (siehe: Springen zwischen HTML-Tags )
    • ggdG- den gesamten Puffer entfernen (entspricht :%d)
    • "2p - zuvor gelöschten Text erneut einfügen

Vielleicht nicht sehr effizient und nicht POSIX ( :bufdo), aber es sollte funktionieren.

Kenorb
quelle
note bufdo ist nicht POSIX pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html
Steven Penny