3
3

More than 1 year has passed since last update.

環境省の花粉情報取得APIを使ってみた

Last updated at Posted at 2021-03-30

はじめに

(2022年1月23日追記:環境省が2022年からは花粉情報の観測・提供を停止することをアナウンスしておりました。https://www.env.go.jp/press/110339.html
そのため、下記記事のAPIは動作しないかもしれません。)

花粉症の方なら皆さんご存知のサイト「環境省花粉観測システム(愛称:はなこさん)」が2021年3月29日に新たなサイトにリニューアルされていました。

よくよく見ると、「環境省花粉観測システムのAPI」なるものが公開されていましたので、早速使ってみました。

追記:上記APIは2021年4月13日から障害を起こしているようで、503エラーを返すようになってしまいました。窓口にメールしてみたのですが、2021年4月18日現在、復旧されていません。他の取得方法についても追記しておきました。

APIの概要

実はAPIの説明ページは存在するのですが、JSONで取得できることと下記のパラメータ説明以外はあまり詳しい説明がありません。

パラメータ

パラメータ名称 URLに入力する名前 必須 値の例 備考
取得開始年月 Start_YM 202003
取得終了年月 End_YM 202005 指定しない場合は現在の年月
都道府県コード TDFKN_CD 03 01~47のいずれか
測定局コード SKT_CD 03201070,03201550 複数の場合はカンマで区切る

URLの例

「2020年3月」から「2020年6月」までの「東京都」に於けるデータを取得するURL例:

https://kafun.env.go.jp/hanako/api/data_search?Start_YM=202003&End_YM=202006&TDFKN_CD=13

都道府県コード

説明はありませんが、どうもこちらの数字のようです。行政関連ではよく使われるコードなのですかね。

測定局コード

一覧情報は見つかりませんでしたが、最新時報値の全局データ表のページで各測定局の当日の表をクリックすると別タブで表示される表のページのURLに含まれています。

例)https://kafun.env.go.jp/preview/table/50110100/today

APIレスポンス

JSON形式

APIを呼び出してみると確かにJSONっぽいものが返ってきます。

しかしこれが少々曲者で、下記のように形式になっています。

  • 文字コードが今どきSHIFT_JIS
  • key: valueのvalueの文字列がクォーテーションで囲まれていない

このままではJSON文字列としてパースできないので、少し加工が必要です。

データの種類

こちらも詳しい説明はありませんが、各観測所の表データと見比べてみると下記のようです。

key名 意味 value例
SKT_CD 測定局コード 52910100
AMeDAS_CD アメダスコード 64036
SKT_NNGP 年月日 20210301
SKT_HH 時刻 01
SKT_NM 測定局名 奈良県産業振興総合センター
SKT_TYPE 測定局のタイプ 1
TDFKN_CD 都道府県コード 29
TDFKN_NM 都道府県名 奈良県
SKCHSN_CD 市町村コード 29201
SKCHSN_NM 市町村名 奈良市
KFN_NUM 花粉数 45
AMeDAS_WD 風向 11
AMeDAS_WS 風速 1
AMeDAS_TP 気温 9.0
AMeDAS_PR 降水量 0
AMeDAS_RDPR レーダー降雨降雪の有無 0

花粉情報の取得処理例

Javaの処理例:

final DateFormat start_df = new SimpleDateFormat("yyyyMM");
final Date date = new Date(System.currentTimeMillis());
String startDateStr = start_df.format(date);

DefaultHttpClient httpClient = new DefaultHttpClient();
String url = "https://kafun.env.go.jp/hanako/api/data_search?Start_YM=" + startDateStr + "&End_YM=" + startDateStr + "&TDFKN_CD=29&SKT_CD=52910100";
HttpGet request = new HttpGet( url );
HttpResponse response = httpClient.execute(request);
if ( response.getStatusLine().getStatusCode() != HttpStatus.SC_OK ) {
    // エラー
}

BufferedReader br = new BufferedReader( new InputStreamReader(response.getEntity().getContent() ,"SHIFT_JIS") );
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
    sb.append(line);
}
String badJsonStr = sb.toString();
br.close();

response.getEntity().consumeContent();

String goodJsonStr = badJsonStr.replace("{", "{\"").replace(":", "\":\"").
        replace( ",", "\",\"").replace( "}", "\"}").replace( "}\",\"{", "},{");

JSONArray jarray = new JSONArray(goodJsonStr);
for (int i = 0; i < jarray.length(); i++ ) {
    JSONObject json = jarray.getJSONObject(i);
    String dataDate   = json.getString("SKT_NNGP");
    String hour   = json.getString("SKT_HH");
    String kafunNum   = json.getString("KFN_NUM");
    String fuusoku   = json.getString("AMeDAS_WS");
    String kion   = json.getString("AMeDAS_TP");
    String kousui   = json.getString("AMeDAS_PR");
}

Google App Scriptの処理例:

let todayDate = new Date();
let year = todayDate.getFullYear();
let month = todayDate.getMonth() + 1;
let startEndDate;

if ( month < 10 ) {
    startEndDate = "" + year + "0" + month;
} else {
    startEndDate = "" + year + month;
}
if ( day < 10 ) {
    todayDateStr = startEndDate + '0' + day;
} else {
    todayDateStr = startEndDate + day;
}

let url = "https://kafun.env.go.jp/hanako/api/data_search?Start_YM=" + startEndDate + "&End_YM=" + startEndDate + "&TDFKN_CD=29&SKT_CD=52910100";

var response = UrlFetchApp.fetch(url);

let badJsonStr = response.getContentText("shift-jis");
let goodJsonStr = '{ "data": ' + badJsonStr.replace( /{/g, '{"' ).replace( /:/g, '":"' ).replace( /,/g, '","' ).replace( /}/g, '"}' ).replace( /}","{/g, '},{' ) + ' }';

let kafunInfoJson = JSON.parse( goodJsonStr );

for (let i = 0; i < kafunInfoJson.data.length; i++ ) {
    let json = kafunInfoJson.data[i];
    let dataDate   = json.SKT_NNGP;
    Hour   = json.SKT_HH;
    KafunNum   = json.KFN_NUM;
    let fuusoku   = json.AMeDAS_WS;
    Kion   = json.AMeDAS_TP;
    let kousui   = json.AMeDAS_PR;
}

追加情報

「はじめに」に記載した通り、上記APIは2021年4月18日現在、障害のため、使えません。

他にデータ取得方法がないか調べたところ、下記のようなURLで花粉情報が取得できることがわかりました。

https://kafun.env.go.jp/data/sokutei/kafunTime/52910100/today.csv?_=1618720784260

「52910100」は測定局コード、末尾の数字は現在時刻のミリ秒で表した数字を入れればよいようです。

「today」で今日、「7day」にすると直近7日間、「season」にすると今年のシーズンのデータが取得できるようです。

呼び出すと、下記のようなCSV形式のデータがBOM無しUTF-8で返ってきます。

測定局コード,アメダス測定局コード,年月日,時,測定局名称,都道府県コード,都道府県名,市区町村コード,市区町村名,花粉飛散数,風向,風速,気温,降水量,レーダー降雨降雪の有無
52910100,64036,20210418,01,奈良県産業振興総合センター,29,奈良県,29201,奈良市,4,南西,2,13.0,0,無し
52910100,64036,20210418,02,奈良県産業振興総合センター,29,奈良県,29201,奈良市,20,西,3,12.8,0,無し

こちらもある種APIと呼んでよいかと思います。というか、こちらの方が今日のデータだけを取るだけならデータ量も小さくて使い勝手よいです。こちらはHPで表示に使われているからか、きちんとメンテされているようです。

所感

実は私は花粉量を通知する「花粉チェッカー」というAndroidアプリを開発してGoogle Playで公開しています。

2021年3月29日の10時からデータが更新されないなと思って、はなこさんのページを確認したところ、2021年3月29日の10時から新しいドメインの新しいサイトに移行された旨が記載されていました。

「聞いてないよー」と思いましたが対応策を調べてみたところ、APIが公開されていることがわかりました。取り急ぎ、それを使うように急ぎ改修しました。

以前は各観測所の当日のデータを取得するために表を表示するページからスクレイピング処理していました。その表はURLを直接叩いても取得できず、セッションcookieなどを上位のページで取得してからでないと表を取得することができず、処理が面倒でした。

今回、制約の無いAPIが無償で公開されたのは非常にありがたいです。環境省の皆様、ありがとうございます。

ただ、データ取得範囲指定を月単位だとデータ量が多くて通信に時間がかかるので、できれば日単位でも指定できるようにしていただけますと幸いです。

なお、はなこさんのページだと毎時40分ころに表が更新されるのですが、このAPIだと10-20分ぐらい早く取得できるようです。よりリアルタイムな値が取得できるのは嬉しいところです。

3
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3