web-dev-qa-db-ja.com

シェルスクリプトでhtmlテーブルからデータを抽出する方法は?

HTMLテーブルからデータを抽出するBASHスクリプトを作成しようとしています。以下は、データを抽出する必要があるテーブルの例です。

_<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>
_

そして、BASHスクリプトが次のように出力するようにします。

_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
_

どうやるか?

これまでsedを使ってみましたが、使い方がよくわかりません。テーブルのヘッダー(コンポーネント、ステータス、時間/エラー)_grep "<tr><td>_を使用してgrepで除外したため、次の解析(sed)では_<tr><td>_で始まる行のみが選択されます。これは私が使用したものです:sed 's@<\([^<>][^<>]*\)>\([^<>]*\)</\1>@\2@g'しかし、_<tr>_タグはまだ残っており、文字列を分離しません。言い換えると、このスクリプトの結果は次のとおりです。

_<tr>SAVE_DOCUMENTOK0.406 s</tr>
_

私が取り組んでいるスクリプトの完全なコマンドは次のとおりです。

_cat $FILENAME | grep "<tr><td>" | sed 's@<\([^<>][^<>]*\)>\([^<>]*\)</\1>@\2@g'
_
11
Marko

一緒に行く (g)awk、それは可能です:-)、ここに解決策があります、しかし注意してください:それはあなたが投稿した正確なhtmlテーブルフォーマットでのみ動作します。

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

ここで実際の動作を見ることができます: https://ideone.com/zGfLe

いくつかの説明:

  1. -F入力フィールドセパレータを正規表現(trまたはtdの開始タグまたは終了タグのいずれか)に設定します

  2. 次に、それらのタグと少なくとも2つのupercasseフィールドに一致する行でのみ機能します

  3. 次に、必要なフィールドを出力します。

HTH

14
Zsolt Botykai

Bash xpathXML :: XPath Perlモジュール)を使用して、そのタスクを非常に簡単に実行できます。

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

これを行うには多くの方法がありますが、ここに1つあります。

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

-e 's:^ ::'の代わりにもっとsed(1)cut -c2-)を使用して先頭のスペースを削除することもできますが、cut(1)は使用しませんそれに値する限り多くの愛を得る。また、バックスラッシュは書式設定のためだけにあります。バックスラッシュを削除して1つのライナーを取得するか、そのままにして、すぐに改行が続くことを確認できます。

基本的な戦略は、理解できない正規表現構文の1つの山で一度にすべてを実行しようとするのではなく、HTMLを1つずつゆっくりと引き離すことです。

シェルパイプラインを使用してHTMLを解析することは、これまでで最善のアイデアではありませんが、HTMLが非常に特殊な形式であることがわかっている場合は、それを行うことができます。バリエーションがある場合は、Perl、Ruby、Python、さらにはCの実際のHTMLパーサーを使用したほうがよいでしょう。

5
mu is too short

html2textコマンドを使用して、columnを介して列をフォーマットできます。例:

$ 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     

次に、そこからさらに解析します(例:cutawkex)。

最初に並べ替える場合は、exを使用できます。例を参照してください ここ または ここ

5
kenorb

マルチプラットフォームのWebスクレイピングCLIに基づくソリューションxidelおよびXQuery

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

サンプル入力を使用すると、次のようになります。

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

説明:

  • XQueryクエリfor $tr in //tr[position()>1] return join($tr/td, " ")は、ループ内の2番目の要素(position()>1、ヘッダー行をスキップする)から始まるtr要素を処理し、子td要素($tr/td)の値をと結合します。区切り文字としての単一のスペース。

  • -sxidelをサイレントにします(ステータス情報の出力を抑制します)。


html2text は抽出されたデータのdisplayに便利ですが、マシンで解析可能な出力を提供することは重要です、残念ながら:

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

Awkコマンドは、デフォルトで\bが出力する非表示のhtml2textベース(バックスペースベース)のシーケンスを削除し、|によって行をフィールドに解析してから、スペースをセパレーターとして出力します(スペースはAwkのデフォルトの出力フィールドセパレーターです。たとえば、タブに変更するには、-v OFS='\t'を使用します)。

注:ソースでバックスペースシーケンスを抑制するために-nobsを使用することは、notオプションです。これは、パディングに使用されるデフォルトで非表示の_インスタンスと実際の_文字を区別できないためです。データ。

注:html2textは常に|を列区切り文字として使用しているように見えるため、上記は、抽出されるdata|インスタンスがない場合にのみ堅牢に機能します

1
mklement0

Ex editor (Vimの一部)を使用して、HTMLタグを削除することでファイルを解析できます。例:

$ 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 

HTMLタグなしでファイル全体を印刷することによる短いバージョンは次のとおりです。

$ ex +'%s/<[^>]\+>/ /g|%p' -scq! table.html

説明:

  • %s/<[^>]\+>/ /g-[〜#〜] s [〜#〜]すべてのHTMLタグを空のスペースに置き換えます。
  • v/0/d-[〜#〜] d [〜#〜]0のないすべての行を削除します。
  • wq! /dev/stdout-[〜#〜] q [〜#〜]uitsエディターおよびwバッファを標準出力に書き込みます。
0
kenorb