turtlechanのブログ

無知の私がLinuxをいじりながら書いていくブログ

【Python】Weather Hackから天気の取得

livedoorが提供してくださっている天気予報サービス「Wether Hacks」を利用して、Pythonで天気予報を取得してみます。

weather.livedoor.com

今回使わせていただくのは、「お天気Webサービス(REST)」。JSON形式で取得できるのでお手軽。ありがとうございます。

お天気Webサービス(REST)の仕様はこちらに書かれています。

作る

仕様のページを見ながら、pythonで作ります。
ライブラリは'requests'と'json'を使います。

リクエストパラメータ(URL)

はじめにアクセスするURLを決めようと思います。

仕様によるとベースになるURLは次のもの。
http://weather.livedoor.com/forecast/webservice/json/v1
で、その後ろにクエリがくるようだ。

パラメーター名は'city'、値は1次細分区のID。全国の地点定義表(RSS)のソースからcityタグのidを見てね。とのこと。
とりあえずブラウザでアクセスして見てみる。以下のようになっていた(東京のみ抜粋)。

~省略~
<pref title="東京都">
<warn title="警報・注意報" source="http://weather.livedoor.com/forecast/rss/warn/13.xml" /><city title="東京" id="130010" source="http://weather.livedoor.com/forecast/rss/area/130010.xml" />
<city title="大島" id="130020" source="http://weather.livedoor.com/forecast/rss/area/130020.xml" />
<city title="八丈島" id="130030" source="http://weather.livedoor.com/forecast/rss/area/130030.xml" />
<city title="父島" id="130040" source="http://weather.livedoor.com/forecast/rss/area/130040.xml" />
</pref>
~省略~

上記のソースから東京の1次細分区のidは'130010'だと言うことが分かる。

ベースURLにクエリ(?city=1次細分区のid)を付加すれば良いので、東京の天気情報取得URLは次のものになる。
http://weather.livedoor.com/forecast/webservice/json/v1?city=130010

天気情報(json)を取得してみる

URLが決まったのでpython2で取得して表示してみます。

test_weather.py
#! /usr/bin/env python
# coding: utf-8
import requests # インターネット接続のため import json # json形式を扱いやすくするため base_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' # ベースURL params = {'city': '130010'} # クエリの準備(地域を変えたい場合は値を変更) response = requests.get(base_url, params=params) # ベースURL + クエリでGET json_data = json.loads(response.content) # json_dataにレスポンスを辞書型で代入 # 読みやすくするためdumpsしたものをprint print('{0}'.format(json.dumps(json_data, indent=4, ensure_ascii=False).encode('utf-8')))

printの部分がグチャッとしてるけど、まあいいでしょう。python2は日本語不得意なのです。

実行すると以下のように表示された。

実行結果
~省略~
    "title": "東京都 東京 の天気", 
    "forecasts": [
        {
            "date": "2019-07-04", 
            "image": {
                "url": "http://weather.livedoor.com/img/icon/8.gif", 
                "width": 50, 
                "height": 31, 
                "title": "曇り"
            }, 
            "telop": "曇り", 
            "temperature": {
                "max": null, 
                "min": null
            }, 
            "dateLabel": "今日"
        }, 
~省略~

問題なく取得できているようです。

欲しい情報だけ表示する

無事JSON形式で天気情報を取得できました。が、なんせ読みにくい。
欲しい情報だけ表示するようにします。

仕様ページのレポンスフィールドを参考にします。jsonライブラリを使っていれば辞書型の扱いと同じなので簡単ですね。

仕様ページのレスポンスフィールド一部

例えば「1次細分区名」のデータを指定して取得する場合は次のようになる。

json_data['location']['city']

上記の方法で各々の値を取得する。

以下に表にまとめた。

共通

値(内容) データの指定(書式)
地方名 json_data['location']['area']
都道府県名 json_data['location']['pref']
1次細分区名 json_data['location']['city']
タイトル・見出し json_data['title']
リクエストされたデータの地域に該当するlivedoor天気情報のURL json_data['link']
予報の発表日時 json_data['publicTime']
天気概況文 json_data['description']['text']
天気概況文の発表時刻 json_data['description']['publicTime']
コピーライトの文言 json_data['copyright']['title']
livedoor天気情報のURL json_data['copyright']['link']
livedoor天気情報へのURL、アイコンなど json_data['copyright']['image']
livedoor天気情報で使用している気象データの配信元 json_data['copyright']['provider']

天気情報
配列になっていて'0'が今日、'1'が明日、'2'が明後日。

値(内容) データの指定(書式)
予報日(yyyy-mm-dd) json_data['forecasts'][0]['date']
予報日(今日) json_data['forecasts'][0]['dateLabel']
天気 json_data['forecasts'][0]['telop']
天気 json_data['forecasts'][0]['image']['title']
リクエストされたデータの地域に該当するlivedoor天気情報のURL json_data['forecasts'][0]['image']['link']
天気アイコンのURL json_data['forecasts'][0]['image']['url']
天気アイコンの幅 json_data['forecasts'][0]['image']['width']
天気アイコンの高さ json_data['forecasts'][0]['image']['height']
最高気温(摂氏) json_data['forecasts'][0]['temperature']['max']['celsius']
最高気温(華氏) json_data['forecasts'][0]['temperature']['max']['fahrenheit']
最低気温(摂氏) json_data['forecasts'][0]['temperature']['min']['celsius']
最高気温(華氏) json_data['forecasts'][0]['temperature']['min']['fahrenheit']

'pinpointLocation'ってのもあるけど省略。

3日間の天気・気温を表示

上記を踏まえてpython2で書くと次のようになった。

weather_hacks.py
#! /usr/bin/env python
# coding: utf-8
import requests # インターネット接続のため import json # json形式を扱いやすくするため base_url = 'http://weather.livedoor.com/forecast/webservice/json/v1' # ベースURL params = {'city': '130010'} # クエリの準備(地域を変えたい場合は値を変更) response = requests.get(base_url, params=params) # ベースURL + クエリでGET json_data = json.loads(response.content) # json_dataにレスポンスを辞書型で代入 # ここから画面表示の処理 print('{0}'.format(json_data['title'].encode('utf-8'))) # タイトルの表示 for forecast in json_data['forecasts']: # 'forecasts'内は配列になっているのでループ処理 date = forecast['date'] # 予報日(yyyy-mm-dd) dateLabel = forecast['dateLabel'].encode('utf-8') # 予報日 print('{0} ({1})'.format(date, dateLabel)) # 予報日の表示 telop = forecast['telop'].encode('utf-8') # 天気 t_max = forecast['temperature'].get('max') # 'max'の値がnullの場合があるのでgetメソッド t_min = forecast['temperature'].get('min') # 'min'の値がnullの場合があるのでgetメソッド if t_max is not None and t_min is not None: # 'max', 'min'の値がNoneじゃなかった場合の処理 t_max = '{0}℃'.format(t_max['celsius']) t_min = '{0}℃'.format(t_min['celsius']) print('天気: {0}\n最高気温: {1}\t最低気温: {2}'.format(telop, t_max, t_min)) # 天気・気温の表示

辞書型のキーを直接指定して値を取得しようとすると、気温の部分でエラーが発生する(値がnullの場合)ため一部get()で取得している。

ちなみに、上記スクリプトを実行すると以下の結果が得られる。

実行結果
東京都 東京 の天気
2019-07-04 (今日)
天気: 曇り
最高気温: None	最低気温: None
2019-07-05 (明日)
天気: 曇のち雨
最高気温: 26℃	最低気温: 20℃
2019-07-06 (明後日)
天気: 曇時々雨
最高気温: None	最低気温: None

おわりに

天気のAPIは他にもあるけど、livedoor社のWeather Hacksは登録もなしに気軽に使えるので嬉しいですね。livedoor社さんには本当に感謝です。