Wie extrahiert man Daten aus einer HTML-Tabelle im Shell-Skript?

Lesezeit: 8 Minuten

Wie extrahiert man Daten aus einer HTML Tabelle im Shell Skript
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:

<table border=1>
<tr>
<td><b>Component</b></td>
<td><b>Status</b></td>
<td><b>Time / Error</b></td>
</tr>
<tr><td>SAVE_DOCUMENT</td><td>OK</td><td>0.406 s</td></tr>
<tr><td>GET_DOCUMENT</td><td>OK</td><td>0.332 s</td></tr>
<tr><td>DVK_SEND</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>DVK_RECEIVE</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>GET_USER_INFO</td><td>OK</td><td>0.143 s</td></tr>
<tr><td>NOTIFICATIONS</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>ERROR_LOG</td><td>OK</td><td>0.001 s</td></tr>
<tr><td>SUMMARY_STATUS</td><td>OK</td><td>0.888 s</td></tr>
</table>

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

1643034726 250 Wie extrahiert man Daten aus einer HTML Tabelle im Shell Skript
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.

 awk -F "</*td>|</*tr>" '/</*t[rd]>.*[A-Z][A-Z]/ {print $3, $5, $7 }' FILE

Hier können Sie es in Aktion sehen: https://ideone.com/zGfLe

Einige Erklärung:

  1. -F setzt das Eingabefeld-Trennzeichen auf einen regulären Ausdruck (beliebig tr‘s oder tddas öffnende oder schließende Tag von

  2. funktioniert dann nur auf Zeilen, die mit diesen Tags UND mindestens zwei Feldern in Großbuchstaben übereinstimmen

  3. 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:

xpath -e '//tr[position()>1]' test_input1.xml 2> /dev/null | sed -e 's/</*tr>//g' -e 's/<td>//g' -e 's/</td>/ /g'

1643034727 636 Wie extrahiert man Daten aus einer HTML Tabelle im Shell Skript
kenorb

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:

grep '^<tr><td>' < $FILENAME 
| sed 
    -e 's:<tr>::g'  
    -e 's:</tr>::g' 
    -e 's:</td>::g' 
    -e 's:<td>: :g' 
| cut -c2-

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.

Wie extrahiert man Daten aus einer HTML Tabelle im Shell Skript
melement0

Eine Lösung, die auf einer plattformübergreifenden Web-Scraping-CLI basiert xidel und XQuery:

xidel -s --xquery 'for $tr in //tr[position()>1] return join($tr/td, " ")' file

Mit der Beispieleingabe ergibt dies:

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:

html2text file | awk -F' *\|' 'NR>2 {gsub(/^||.b/, ""); $1=$1; print}'

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.

1643034727 636 Wie extrahiert man Daten aus einer HTML Tabelle im Shell Skript
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/<[^>]+>/ /gSErsetzen Sie alle HTML-Tags ins Leere.
  • v/0/dDlöscht alle Zeilen ohne 0.
  • wq! /dev/stdoutQuits-Editor und wschreibt den Puffer auf die Standardausgabe.

.

619270cookie-checkWie extrahiert man Daten aus einer HTML-Tabelle im Shell-Skript?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy