Python | POI データを取得して、地点の天気を得る
https://github.com/daisuke-t-jp/overpass_weather
今回作成したプロジェクトは GitHub に置いた。
概要
OpenWeatherMap API を使うと、呼び出し頻度の制限はあるが、無料で天気情報を取得できる。
この取得する天気情報を、意味のある集まりにしたい。たとえば、全国の公共施設の天気、駅の天気などだ。
こういった地点の情報(POI)は、OSM から node として無料で取得できる。そして OSM のデータは Overpass という API でプログラマブルに取得できる。
https://wiki.openstreetmap.org/wiki/JA:Overpass_API
上記から今回は、以下の流れを試す。
Overpass API
Overpass API は、サーバにクエリをリクエストして、マッチした OSM データをレスポンスを受け取る使い方になる。
たとえば、世界の大聖堂(カテドラル)を抽出したい場合のクエリは以下。
[out:json]; node["building"="cathedral"]; out body;
日本全国の公共施設を抽出したい場合は以下。
[out:json]; area["name"~"日本"]; node(area)["amenity"="townhall"]; out body;
このクエリを簡単に試すには、以下のサイトを使うと良い。
Python から Overpass API を使用するには、以下の overpy ライブラリを使う。
https://pypi.org/project/overpy/
OpenWeatherMap
Overpass API で得た POI の緯度経度から、OpenWeatherMap API で得るには下の格好になる。
https://api.openweathermap.org/data/2.5/weather?appid=APP_KEY&lat=35.658316&lon=139.741423
API キーが必要になるため、事前に取得する。
ここで気をつけたいのが、無料アカウントでは、1分に60回までリクエストが制限されているので、リクエストごとに1秒のウェイトを挟むことで、制限を避ける。
実行例
上記を踏まえて作成した Python スクリプト(overpass_weather)を試してみる。
詳しくは README.md を参照することだが、流れを書くと
Git clone してきて
$ git clone https://github.com/daisuke-t-jp/overpass_weather
必要なパッケージをインストールする
$ pip3 install overpy $ pip3 install attrdict
overpass_weather を import して、こんなスクリプトを実行すると
#!/usr/bin/python # coding: UTF-8 import sys import logging import enum sys.path.append('../') import overpass_weahter def test_dump_weather(weather): osm = weather[overpass_weahter.KEY_OSM] openweathermap_weather = weather[overpass_weahter.KEY_OPENWEATHERMAP_CURRENT_WEATHER_DATA] logging.debug('osm_id[{0}] name[{1}] lat[{2}] lon[{3}] temp[{4}] pressure[{5}] humidity[{6}]'.format( osm[overpass_weahter.KEY_ID], osm[overpass_weahter.KEY_NAME], osm[overpass_weahter.KEY_LAT], osm[overpass_weahter.KEY_LON], openweathermap_weather['main']['temp'], openweathermap_weather['main']['pressure'], openweathermap_weather['main']['humidity'])) return def test_overpass_api(): try: weathers = overpass_weahter.weathers_with_overpass_api(""" [out:json]; node["building"="cathedral"]; out body; """, OPENWEATHERMAP_API_KEY, 0.1) for weather in weathers: test_dump_weather(weather) except Exception as exp: logging.error('exception[{0}]'.format(exp)) return
こんな風に POI と関連する天気を得られた。
2020-03-09 23:56:06,709 DEBUG test.py:27 - test_dump_weather() : osm_id[100090862] name[Dom St. Blasien] lat[47.7600646] lon[8.1300061] temp[280.04] pressure[1017] humidity[71] 2020-03-09 23:56:06,709 DEBUG test.py:27 - test_dump_weather() : osm_id[474375860] name[Собор Успения Пресвятой Богородицы] lat[50.9799235] lon[39.3167911] temp[286.99] pressure[1019] humidity[66] 2020-03-09 23:56:06,709 DEBUG test.py:27 - test_dump_weather() : osm_id[592838468] name[N/A] lat[4.8092301] lon[-74.3537103] temp[289.15] pressure[1030] humidity[67] ...
さらに、Overpass API はレスポンスに時間がかかる、また負荷によりエラーが発生しやすいため、事前に Overpass API のレスポンスを JSON ファイルにしたものでも実行できるようにした。
def test_overpass_file(): weathers = overpass_weahter.weathers_with_overpass_file('overpass_building_cathedral.json', OPENWEATHERMAP_API_KEY, 0.1)
テスト目的ならば、こちらがやりやすい。 また、この方法だとたまに Overpass API でローカルの JSON 更新して対応していくことで、安定して更新された POI から天気取得できそうだ。