シェルスクリプトでスクレイピングするために`pup`を使う
はじめに
以前、シェルスクリプトからhtmlのスクレイピングをしたときの方法を共有します。
Go言語で作られたpupというツールを使いました。
検証環境
pup とは
コマンドラインの HTML 解析ツールです。
標準入力から情報を読み込み、標準出力に結果を出力します。
それだけだと cat
と同じなのですが、 HTML の要素をフィルタリングすることができます。フィルタリングのための HTML 要素指定方法として、一般的に利用されている CSS Selectors が利用できます。
pup ツール開発の背景
jq コマンドにインスパイアされたようです。
jq といえばコマンドライン上で JSON データを操作するためのツールですが、HTML データをターゲットとしたものとして開発されたようです。
pup インストール
別のエントリで、環境を汚さずにDockerを使ってpubを使うための方法を投稿しています。 Dockerが使い慣れている方はこちらもどうぞ。
以下のツールを利用します。
go get
コマンドを使ってインストールするため、事前に go
のインストールが必要です。
Goのインストール
以下のコマンドが正しく実行できていればGoのインストールは完了です。
pupのインストール
go get
コマンドでインストールします。
以下のコマンドが正しく実行できていればpupのインストールは完了です。
PATH="$PATH:$HOME/go/bin"
のように、パスを通しておくと使いやすいでしょう。
その他、インストールされていると便利なツール
curl
curl については必須ではないのですが、URL で指定されたページの HTML データを取得する方法として curl
を利用することが一般的となっている状況ですので、インストールしておくのが良いでしょう。
pup を使ってみる
スクレイピングの検証にサンプルhtmlを作成してスクレイピングしてみます。
li
タグ部分を抽出
li
タグのうち class="name"
の属性を持つもののみを抽出
class="age"
の属性を持つもののみを抽出
text情報のみを出力する機能
タグの構成は不要、text情報のみがほしいという場合は以下のように text{}
という命令を付与します。
属性情報のみを出力する機能
属性情報のみがほしいという場合は以下のように attr{}
という命令を付与します。
ここでは class
属性の情報がすべて同じなので有効性がわかりにくいですが、a
タグのhref
属性や、img
タグのsrc
属性を取得するときに便利ですね。
スクレイピングした要素のJSON変換機能
ちょっと変わった機能として、スクレイピングした要素をJSON変換する機能があります。json{}
という命令を付与します。
もう少し突っ込んだ使い方
curl を使えば、URL に該当するページの HTML データを取得できます。
( 標準出力に出力されます。 )
取得された HTML をパイプで繋いで、 pup
コマンドに渡してみます。
本来の使い方ではないのですが、 pup
に通すと HTML が整形されますので、 ちょっとしたフォーマッタとしても利用できます。
更に、 --color
オプションを付けるとフォーマットされた HTML のタグが色付けされて更に見やすくなります。
table
タグの中の table
タグの中の tr
タグの ... といったようにフィルタリングをして、 a
タグ要素のみを出力できます。
リンクの href
属性のみを表示します。
JSON 形式に変換もできます。( jq
での操作に慣れている場合はこちらが便利ですね。 )
pup
の引数を確認
pup
コマンドの引数は以下のようになります。
先の例で行くと a
タグの属性情報を表示するための attr{href}
や JSON フォーマットで出力するための json{}
が [display function]
に該当します。
更に突っ込んだ使い方
先程、少し使い方に触れましたが、更に例を追加して使い方を説明していきます。
以下のコマンドを実行し、フィルタを行う HTML ファイルをダウンロードしておきます。
タグでフィルタリング
HTML タグで絞り込みを行います。
id でフィルタリング
タグに付与されている id 属性 で絞り込みを行います。
id 属性は HTML 内で一意 (となっていることが期待されている) ので、タグ名を指定しなくても構いません。
属性情報でフィルタリング
属性情報で絞り込みを行います。
ちなみに、今回のサンプル HTML に限っていうと <th scope="row">
以外に scope="row"
の属性を持っている HTML 要素はないので、以下のようにタグ指定を省略しても同様の結果が得られます。
http://
で始まるリンクを表示。
https://
で始まるリンクを表示。
擬似クラスでフィルタリング
CSS Selectors で利用できる 擬似クラス 機能を使って絞り込みを行うこともできます。
アンカーテキストが空のリンクを表示。
タグの中に History と書かれているタグを表示。
action="edit" という属性を持つタグの親タグを表示。
+
、 >
, 、 ,
+
、 >
, 、 ,
は特殊な意味を持つ文字です。
複数のフィルタ条件を同時に指定することができます。
CSS Selector を連結(チェーン)する
スペース区切りで複数のセレクタが指定された場合、フィルタのチェーンとなります。
段階的に後続の条件でフィルタリングされていきます。
はじめに 1 つだけの条件で絞り込みます。
先程の条件での絞り込み後に span
で更に絞り込みしたい場合は、先程の条件の後ろにスペースを開けた後 span
と指定します。
pup
コマンドをパイプで繋いで処理することもできます。
出力制御
タグ内のテキストのみ表示 : text{}
text{}
関数(関数と呼ぶのでしょうか?)を使って、タグ内のテキストのみを表示させることができます.
タグ内の属性のみ表示 : attr{attrname}
属性を表示させる場合には attr{}
を使います。
attr{}
のカッコの中には属性名を指定します。
JSON形式で表示 : json{}
json{}
を指定して JSON形式で表示させることもできます。
ひとこと
JSON形式にしてしまえばあとはどうとでもなりそうですね。 jq
も使えますし。
ディスカッション
コメント一覧
まだ、コメントがありません