シェルスクリプトでスクレイピングするために`pup`を使う

Bash

はじめに

以前、シェルスクリプトからhtmlのスクレイピングをしたときの方法を共有します。

Go言語で作られたpupというツールを使いました。

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux
$ bash -version
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

インストール

以下のツールを利用します。

go get コマンドを使ってインストールするため、事前に go のインストールが必要です。

Goのインストール

# 何はともあれパッケージをアップデート
$ sudo yum update -y
# epelリポジトリを追加して、Goをインストールできるようにする
$ sudo yum install epel-release -y
$ sudo yum install golang -y

以下のコマンドが正しく実行できていればGoのインストールは完了です。

$ go version
go version go1.11.5 linux/amd64

pupのインストール

go get コマンドでインストールします。

$ go get github.com/ericchiang/pup

以下のコマンドが正しく実行できていればpupのインストールは完了です。

# コマンドは以下のディレクトリにインストールされている
$ ~/go/bin/pup --version
0.4.0

PATH="$PATH:$HOME/go/bin"のように、パスを通しておくと使いやすいでしょう。

使ってみる

スクレイピングの検証にサンプルhtmlを作成してスクレイピングしてみます。

cat <<'EOF' > index.html
<html>
  <body>
    <div>
      <h1>テストページ</h1>
      <h2>子どもたち</h2>
      <ul>
        <li class="name">ゆう
        <span class="age">10</span></li>
        <li class="name">れん
        <span class="age">7</span></li>
        <li class="name">ひろ
        <span>4</span></li>
        <li>そう
        <span class="age">1</span></li>
      </ul>
    </div>
  </body>
</html>
EOF

li タグ部分を抽出

$ cat index.html | $HOME/go/bin/pup 'ul > li'
<li class="name">
 ゆう
 <span class="age">
  10
 </span>
</li>
<li class="name">
 れん
 <span class="age">
  7
 </span>
</li>
<li class="name">
 ひろ
 <span>
  4
 </span>
</li>
<li>
 そう
 <span class="age">
  1
 </span>
</li>

li タグのうち class="name" の属性を持つもののみを抽出

$ cat index.html | $HOME/go/bin/pup 'ul > li[class="name"]'
<li class="name">
 ゆう
 <span class="age">
  10
 </span>
</li>
<li class="name">
 れん
 <span class="age">
  7
 </span>
</li>
<li class="name">
 ひろ
 <span>
  4
 </span>
</li>

class="age" の属性を持つもののみを抽出

$ cat index.html | $HOME/go/bin/pup '[class="age"]'
<span class="age">
 10
</span>
<span class="age">
 7
</span>
<span class="age">
 1
</span>

text情報のみを出力する機能

タグの構成は不要、text情報のみがほしいという場合は以下のように text{} という命令を付与します。

$ cat index.html | $HOME/go/bin/pup '[class="age"] text{}'
10
7
1

属性情報のみを出力する機能

属性情報のみがほしいという場合は以下のように attr{} という命令を付与します。

$ cat index.html | $HOME/go/bin/pup 'ul > li attr{class}'
name
name
name

ここでは class 属性の情報がすべて同じなので有効性がわかりにくいですが、
aタグのhref属性や、imgタグのsrc属性を取得するときに便利ですね。

スクレイピングした要素のJSON変換機能

ちょっと変わった機能として、スクレイピングした要素をJSON変換する機能があります。
json{}という命令を付与します。

$ cat index.html | $HOME/go/bin/pup 'ul > li json{}'
[
 {
  "children": [
   {
    "class": "age",
    "tag": "span",
    "text": "10"
   }
  ],
  "class": "name",
  "tag": "li",
  "text": "ゆう"
 },
 {
  "children": [
   {
    "class": "age",
    "tag": "span",
    "text": "7"
   }
  ],
  "class": "name",
  "tag": "li",
  "text": "れん"
 },
 {
  "children": [
   {
    "tag": "span",
    "text": "4"
   }
  ],
  "class": "name",
  "tag": "li",
  "text": "ひろ"
 },
 {
  "children": [
   {
    "class": "age",
    "tag": "span",
    "text": "1"
   }
  ],
  "tag": "li",
  "text": "そう"
 }
]

ひとこと

JSON形式にしてしまえばあとはどうとでもなりそうですね。 jq も使えますし。

Bash

Posted by genzouw