Wie extrahiert man Daten aus einer HTML-Tabelle im Shell-Skript?
Lesezeit: 8 Minuten
Markus
Ich versuche, ein BASH-Skript zu erstellen, das die Daten aus der HTML-Tabelle extrahieren würde. Unten ist das Beispiel einer Tabelle, aus der ich Daten extrahieren muss:
Und ich möchte, dass das BASH-Skript es so ausgibt:
SAVE_DOCUMENT OK 0.475 s
GET_DOCUMENT OK 0.345 s
DVK_SEND OK 0.002 s
DVK_RECEIVE OK 0.001 s
GET_USER_INFO OK 4.465 s
NOTIFICATIONS OK 0.001 s
ERROR_LOG OK 0.002 s
SUMMARY_STATUS OK 5.294 s
Wie es geht?
Bisher habe ich versucht, das sed zu verwenden, aber ich weiß nicht, wie ich es recht gut verwenden soll. Die Kopfzeile der Tabelle (Komponente, Status, Zeit/Fehler) habe ich mit grep ausgeschlossen grep "<tr><td>, also nur Zeilen, die mit beginnen <tr><td> wird für das nächste Parsing (sed) ausgewählt. Das habe ich verwendet: sed 's@<([^<>][^<>]*)>([^<>]*)</1>@2@g'
Aber dann <tr> Tags bleiben bestehen und es trennt die Zeichenfolgen nicht. Mit anderen Worten, das Ergebnis dieses Skripts ist:
<tr>SAVE_DOCUMENTOK0.406 s</tr>
Der vollständige Befehl des Skripts, an dem ich arbeite, lautet:
cat $FILENAME | grep "<tr><td>" | sed 's@<([^<>][^<>]*)>([^<>]*)</1>@2@g'
Muss es ein Bash-Skript sein? Wenn Sie unter Linux arbeiten, wäre vielleicht ein Perl-Skript eine einfachere Option. Die könntest du dann verwenden HTML::Parser Modul oder ähnliches.
– Mike
28. Juli 11 um 6:16 Uhr
Zsolt Botykai
Geh mit (g)awk, es ist fähig :-), hier ist eine Lösung, aber bitte beachten Sie: Es funktioniert nur mit dem genauen HTML-Tabellenformat, das Sie gepostet haben.
-F setzt das Eingabefeld-Trennzeichen auf einen regulären Ausdruck (beliebig tr‘s oder tddas öffnende oder schließende Tag von
funktioniert dann nur auf Zeilen, die mit diesen Tags UND mindestens zwei Feldern in Großbuchstaben übereinstimmen
druckt dann die erforderlichen Felder.
HTH
Super Erklärung! Vielen Dank!
– Markus
28. Juli 11 um 6:31 Uhr
Wie kann ich die Ausgabe weiter bearbeiten? Wenn ich zum Beispiel möchte, dass die Ausgabe so aussieht: SAVE_DOCUMENT=”OK 0.475 s” GET_DOCUMENT=”OK 0.345 s” DVK_SEND=”OK 0.002 s”
– Markus
28. Juli 11 um 7:53 Uhr
Ersetzen Sie einfach die {print $3, $5, $7 } Teil mit {print $3 "="" $5, $7 """ } HTH
– Zsolt Botykai
28. Juli 11 um 8:09 Uhr
Ja, es funktioniert! Noch eine Frage, wie man Leerzeichen und “s” hinter den Zahlen entfernt, damit die Ausgabe wäre: DVK_SEND=”OK 0.002″
– Markus
28. Juli 11 um 11:47 Uhr
Es ist ein sehr kleines bisschen kniffliger: verwenden {print $3 "="" $5, gensub(" *s$","","g",$7) """ } HTH
– Zsolt Botykai
28. Juli 11 um 20:32 Uhr
Sie können bash verwenden xpath (XML::XPath Perl-Modul), um diese Aufgabe sehr einfach zu erledigen:
Sie dürfen verwenden html2text Befehl und formatieren Sie die Spalten über column, z.B:
$ html2text table.html | column -ts'|'
Component Status Time / Error
SAVE_DOCUMENT OK 0.406 s
GET_DOCUMENT OK 0.332 s
DVK_SEND OK 0.001 s
DVK_RECEIVE OK 0.001 s
GET_USER_INFO OK 0.143 s
NOTIFICATIONS OK 0.001 s
ERROR_LOG OK 0.001 s
SUMMARY_STATUS OK 0.888 s
dann parsen Sie es von dort aus weiter (zB cut, awk, ex).
Falls Sie es zuerst sortieren möchten, können Sie verwenden ex, siehe Beispiel Hier oder Hier.
Bedauerlicherweise, html2text peppt seine Ausgabe standardmäßig mit Backspace-Zeichen auf, obwohl Ihre Ausgabe sieht aus OK, es ist voll versteckt b (Backspace)-Sequenzen. Sie sicher zu entfernen, erfordert mehr Arbeit (mithilfe von -nobs ist keine Option, weil es versteckt auftaucht _ Instanzen, die zum Auffüllen verwendet werden und dann schwer zu unterscheiden sind _ Instanzen in der Daten).
– melement0
11. Juli 17 um 19:46 Uhr
Es gibt viele Möglichkeiten, dies zu tun, aber hier ist eine:
Sie könnten mehr gebrauchen sed(1) (-e 's:^ ::') anstatt des cut -c2- um das führende Leerzeichen aber zu entfernen Schnitt(1) bekommt nicht so viel Liebe, wie es verdient. Und die umgekehrten Schrägstriche sind nur zum Formatieren da, Sie können sie entfernen, um einen Einzeiler zu erhalten, oder sie drin lassen und sicherstellen, dass ihnen sofort ein Zeilenumbruch folgt.
Die grundlegende Strategie besteht darin, den HTML-Code langsam Stück für Stück auseinanderzunehmen, anstatt zu versuchen, alles auf einmal mit einem einzigen unverständlichen Stapel von Regex-Syntax zu erledigen.
Das Analysieren von HTML mit einer Shell-Pipeline ist nicht die beste Idee, aber Sie können es tun, wenn das HTML bekanntermaßen in einem ganz bestimmten Format vorliegt. Wenn es Variationen geben wird, sollten Sie besser mit einem echten HTML-Parser in Perl, Ruby, Python oder sogar C arbeiten.
melement0
Eine Lösung, die auf einer plattformübergreifenden Web-Scraping-CLI basiert xidel und XQuery:
SAVE_DOCUMENT OK 0.406 s
GET_DOCUMENT OK 0.332 s
DVK_SEND OK 0.001 s
DVK_RECEIVE OK 0.001 s
GET_USER_INFO OK 0.143 s
NOTIFICATIONS OK 0.001 s
ERROR_LOG OK 0.001 s
SUMMARY_STATUS OK 0.888 s
Erläuterung:
XQuery-Abfrage for $tr in //tr[position()>1] return join($tr/td, " ") verarbeitet die tr Elemente beginnend mit dem 2. (position()>1, um die Kopfzeile zu überspringen) in einer Schleife und verbindet die Werte des untergeordneten Elements td Elemente ($tr/td) mit einem einzelnen Leerzeichen als Trennzeichen.
-s macht xidel silent (unterdrückt die Ausgabe von Statusinformationen).
Während html2text ist bequem für Anzeige der extrahierten Daten, Das Bereitstellen einer maschinenlesbaren Ausgabe ist nicht trivial, bedauerlicherweise:
Der Befehl Awk entfernt das Versteckte b-basierte (Backspace-basierte) Sequenzen, die html2text gibt standardmäßig aus und zerlegt die Zeilen in Felder von |, und gibt sie dann mit einem Leerzeichen als Trennzeichen aus (ein Leerzeichen ist das standardmäßige Ausgabefeldtrennzeichen von Awk; um es beispielsweise in einen Tabulator zu ändern, verwenden Sie -v OFS='t').
Hinweis: Verwendung von -nobs Backspace-Sequenzen an der Quelle zu unterdrücken ist nicht eine Option, da Sie dann nicht zwischen den standardmäßig ausgeblendeten unterscheiden können _ Instanzen, die zum Auffüllen und tatsächlich verwendet werden _ Zeichen in den Daten.
Hinweis: Angesichts dessen html2text scheinbar immer verwendet | als Spaltentrenner, Das obige funktioniert nur robust, wenn dies nicht der Fall ist | Instanzen in der Daten extrahiert wird.
kenorb
Sie können die Datei mit parsen Ex-Redakteur (Teil von Vim) durch Entfernen von HTML-Tags, z.
$ ex -s +'%s/<[^>]+>/ /g' +'v/0/d' +'wq! /dev/stdout' table.html
SAVE_DOCUMENT OK 0.406 s
GET_DOCUMENT OK 0.332 s
DVK_SEND OK 0.001 s
DVK_RECEIVE OK 0.001 s
GET_USER_INFO OK 0.143 s
NOTIFICATIONS OK 0.001 s
ERROR_LOG OK 0.001 s
SUMMARY_STATUS OK 0.888 s
Hier ist eine kürzere Version, indem die gesamte Datei ohne HTML-Tags gedruckt wird:
$ ex +'%s/<[^>]+>/ /g|%p' -scq! table.html
Erläuterung:
%s/<[^>]+>/ /g – SErsetzen Sie alle HTML-Tags ins Leere.
v/0/d – Dlöscht alle Zeilen ohne 0.
wq! /dev/stdout – Quits-Editor und wschreibt den Puffer auf die Standardausgabe.
.
6192700cookie-checkWie extrahiert man Daten aus einer HTML-Tabelle im Shell-Skript?yes
Muss es ein Bash-Skript sein? Wenn Sie unter Linux arbeiten, wäre vielleicht ein Perl-Skript eine einfachere Option. Die könntest du dann verwenden HTML::Parser Modul oder ähnliches.
– Mike
28. Juli 11 um 6:16 Uhr