curlコマンドで官公庁の報道発表資料を取得する
BUW(Bash on Ubuntu on Windows)には「curl」というWebサーバーへのアクセスなどを行うコマンドが用意されている。例えば「curl http://news.mynavi.jp/dp/business」と実行すれば、対象となるHTMLファイルを標準出力で取得するというものだ。その利用シーンは多岐にわたるが、今回からはRSS/ATOMフィードを配信していないWebサイトの情報を取得するために、curlコマンドを使ったシェルスクリプトの作成にチャレンジする。
ターゲットにするのは総務省の報道資料一覧を配信するWebページ。取得したHTMLの内容を見ると文字コードはシフトJISを使っている。また、報道資料一覧はTDタグを使ったテーブルを用いているようだ。確認したところ、このページでは他にテーブルを用いていないため、TDタグを抽出すれば、必要な情報を取り出せる。
抽出方法はgrepコマンドを使用し、不要なHTMLタグの削除はsedコマンドを使用すればよい。ちなみにgrepはテキストファイルなどから文字列、正規表現に一致する行を検索するコマンド。sedはテキストデータを処理するコマンドである。この場合のコマンドラインは「curl -s -S http://www.soumu.go.jp/menu_news/s-news/ | grep "td" | sed 's/<[^>]*>//g'
」となり、実行結果は下図に示したように、1行目に日時、2行目にタイトル、3行目にカテゴリーが並ぶ結果となった。ちなみにsedコマンドで指定している「s」は正規表現で置換処理を行うためのコマンド。ここで指定した「<[^>]*>
」は「<
」「>
」で囲んだ文字列をすべて削除するというもの。末尾の「g」は1行中に複数マッチした文字列をすべて置換するために付加する。
このようにテキストのみ抽出するのであれば、コマンドライン1行で実現可能。ちなみにシフトJISの文字化けを回避するため、nkfコマンドを併用している(※インストールされていない場合は、sudo apt-get install nkfでインストールします) |
一見すると簡単に成功したように見えるものの、今回のシェルスクリプトは本稿担当編集者が「日々の情報収集を簡単にしたい」というリクエストに基づいているため、URLを削除してしまっては元も子もない。そこでHTMLタグすべてではなくTDタグのみ取り除く設定が必要である。そこで、sedコマンドのオプション「-e」を使用し、置換パターンを複数記述する方法を用いた。今回は「<td>
」「<td(に続く文字列)
」「</td>
」だけ取り除けば十分なので、「curl -s -S http://www.soumu.go.jp/menu_news/s-news/ | grep "<td" | sed -e 's/<td>//g' -e 's/<td.*">//g' -e 's/<\/td>//g'
」と実行する。
それでもこの状態ではリンクを張る「A」タグとタイトルが1行にまとまった状態だ。さらにsedコマンドを用いて置換する方法で対処しよう。まず「」を改行に置換。そしてタグを閉じる「」を削除しなければならない。その場合は「sed -e 's/<td>//g' -e 's/<td .*">//g' -e 's/<\/td>//g' -e 's/<a.*="//g' -e 's/<\/a>//g' -e 's/">/\n/g'
」となる。これで1行ごとに情報を分解したデータを取り出すことができた。
では今回のシェルスクリプトを紹介しよう。いつもどおりvimなどで下記の内容を作成し、chmodコマンドで実行権限を付加してほしい。
#!/bin/bash
URLBASE=http://www.soumu.go.jp
URL={$URLBASE}/menu_news/s-news/
I=0
Array=($(curl -s -S $URL | grep "<td" | sed -e 's/<td>//g' -e 's/<td .*">//g' -e 's/<\/td>//g' -e 's/<a.*="//g' -e 's/<\/a>//g' -e 's/">/\n/g'))
for Obj in ${Array[@]}; do
Num=`expr $I % 4`
case $Num in
0 )
StrDate=`echo ${Obj} | sed -e 's/[\r\n]\+//g'` ;;
1 )
StrURL=`echo ${Obj} | sed -e 's/[\r\n]\+//g'` ;;
2 )
StrTitle=`echo ${Obj} | sed -e 's/[\r\n]\+//g'` ;;
3 )
StrCat=`echo ${Obj} | sed -e 's/[\r\n]\+//g'`
echo $StrDate $StrCat | nkf
echo $StrTitle | nkf
echo $URLBASE$StrURL | nkf
echo -e "\n"
;;
esac
let I++
done
まず3~4行目で設定した変数は取得先となるWebサイトのURLだ。2つの変数に分けているのは、curlコマンドで取得するURLにドメインなどが含まれないため、上記のように記述した。7行目は先ほどまで実行していたcurlコマンドの内容を配列「Array」に格納させている。10行目は配列Arrayをすべて展開するためのfor文だ。少々内容が煩雑なので順番に解説しよう。
今回取得した総務省の報道資料一覧は4要素で構成されているため、この計算結果を基に、11行目で変数「I」の値を4で割り、その結果を変数「Num」に代入して、12行目からのcase文で分岐する仕組みだ。値から各変数に文字列を展開しているが、その際はsedコマンドを使用し、改行コードを取り除いている。
変数Numの値はゼロから3までの数値になるので、19行目からの分岐で表示処理を加えている。今回はcurlコマンドで取得した要素をパーツとして使用可能にするまでを中間地点としているため、出力形式に凝ることはしなかった。
上図のように日付とカテゴリーを1行にまとめて、2行目は発表内容のタイトル、3行目は加工したURLがまとめられている。次回はこのシェルスクリプトをベースに活用方法を考えてみよう。
阿久津良和(Cactus)