Node.jsで河川の水位データをスクレイピングする


こんにちは、ソリューションの五十嵐です。

私は釣りが好きで、休日はよく釣りに出かけています。

その際に国土交通省が提供している河川の水位情報をチェックして釣りのポイント選びなどに役立てています。

http://www1.river.go.jp/

この水位情報をもっと手軽に確認できるようにしたいのでNode.jsでスクレイピングして水位データを提供するAPIを作成してみます。

Node.jsによるWebスクレイピング

まずNode.jsによるWebスクレイピングのライブラリとしてcheerioをインストールします。

$ npm i --save cheerio-httpcli

インストールしたcheerioで試しにYahooのトップページをスクレイピングしてみます。

var client = require('cheerio-httpcli');
client.fetch('http://yahoo.jp', function(err, $, res, body){
    console.log(body);
});
$ node index.js
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="content-style-type" content="text/css">
<meta http-equiv="content-script-type" content="text/javascript">
<meta name="description" content="日本最大級のポータルサイト。検索、オークション、ニュース、天気、スポーツ、メール、ショッピングなど多数のサービスを展開。あなたの生活をより豊かにする「課題解決エンジン」を目指していきます。">
<meta name="robots" content="noodp">
...

YahooのHTMLソースを取得することができました。

河川の水量データをWebスクレイピングしてみる

指定URLをスクレイピングできることが確認できましたので水位データのページも試してみます。

水位データのページはTopページと詳細ページに分かれており、目標のデータは詳細ページにあります。

しかし、詳細ページのURLとなるデータID?は随時更新されるため、Topページにアクセスし今のデータIDを取得する必要があります。

まずはTopページのスクレイピングを始めましょう。

var client = require('cheerio-httpcli');
// 国土交通省
const BASEURL = 'http://www1.river.go.jp/'
const CGIURL = 'cgi-bin/DspWaterData.exe?KIND=9&ID='
const URL = BASEURL+CGIURL+'304021284415014';
// 河川データページ表示
client.fetch(URL, function(err, $, res, body){
    console.log(body);
});
$ node index.js
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=EUC-JP">
<META http-equiv="Content-Style-Type" content="text/css">
<TITLE>リアルタイム10分水位一覧表</TITLE>
</HEAD>
<BODY bgcolor="#ffffff">
<CENTER>
<TABLE BORDER="1" CELLPADDING="2" CELLSPACING="1">  
    <TR>
      <TD NOWRAP BGCOLOR="#33FFFF" ALIGN="CENTER"><B><FONT SIZE=-1>観測所記号</FONT></B></TD>
      <TD NOWRAP BGCOLOR="#33FFFF" ALIGN="CENTER"><B><FONT SIZE=-1>観測所名</FONT></B></TD>
      <TD NOWRAP BGCOLOR="#33FFFF" ALIGN="CENTER"><B><FONT SIZE=-1>水系名</FONT></B></TD>
      <TD NOWRAP BGCOLOR="#33FFFF" ALIGN="CENTER"><B><FONT SIZE=-1>河川名</FONT></B></TD>
    </TR>
...

このページに詳細ページのデータIDが含まれていますのでスクレイピングした結果から抽出します。

データIDを抽出する

スクレイピングしたHTMLソースはjQueryのセレクタのような形で操作できますので以下のようにリンクのaタグにデータIDが含まれるかを判定します。

// 河川データページ表示
client.fetch(URL, function(err, $, res, body){
    // aタグから詳細データのURL取得
    $('a').each(function(idx){
        // 詳細データURLが取得できたら詳細データを表示
        if($(this).attr('href').match(/dat/)){
            console.log($(this).attr('href'));
        }
    });
});
$ node index1.js
/dat/dload/download/293040212844150142019041526153.dat

データIDの取得ができましたので詳細ページのスクレイピングを行います。

詳細ページのスクレイピング

取得したデータIDで再度スクレイピングを行います。

// 河川データページ表示
client.fetch(URL, function(err, $, res, body){
    // aタグから詳細データのURL取得
    $('a').each(function(idx){
        // 詳細データURLが取得できたら詳細データを表示
        if($(this).attr('href').match(/dat/)){
            const target = $(this).attr('href');
            client.fetch(BASEURL+target, function(err, $, res, body){
                console.log(body)
            });
        }
    });
});
$ node index1.js
...
2019/04/15,00:10,0.90,
2019/04/15,00:20,0.90,
2019/04/15,00:30,0.90,
2019/04/15,00:40,0.90,
2019/04/15,00:50,0.90,
...

無事水位データを取得することができました。

ちなみに水位データは日付,時刻,水位(m)のようです。

まとめ

取得したデータをカンマ区切りで整形し、最終的に以下のようなJSON形式のデータになるように修正しました。

$ node index.js
{ latest: '0.92',  // 最新
  latest_time: '2019/04/21 10:30', // 最終データの時刻
  day: 0.93,  // 日平均
  weekly: 0.94 } // 週平均

今回はデータの整形までを行いましたので次回はこのデータを提供するAPIと、それを利用するアプリケーションを作成したいと思います。


One response to “Node.jsで河川の水位データをスクレイピングする”

  1. カンマ区切りで整形し、最終的に以下のようなJSON形式のデータになるように修正したコードをもらえませんでしょうか?

Leave a Reply

Your email address will not be published. Required fields are marked *