GIS奮闘記

現役GISエンジニアの技術紹介ブログ。主にPythonを使用。

スポンサーリンク

Python と気象庁の天気予報 JSON を使って全国の天気予報を取得してみる

さて、本日は気象庁の天気予報 JSON で遊んでみようと思います。気象庁のデータに関しては以下のエントリーでも扱いましたが、この時はスクレイピングを行いました。今回は公開されている JSON を活用して天気情報を取得してみたいと思います。

www.gis-py.com

気象庁天気予報 JSON とは

気象庁のWebサイトのリニューアルに伴い、天気予報情報がJSON形式で取得できるようになりました。正式公開の WebAPI ではないのですが、「政府標準利用規約に準拠して利用可能」なようです。

気象庁天気予報 JSON の種類

  1. エリアコード
  2. コンテンツ種別
  3. 各地の気象情報

今回は「3.各地の気象情報」を利用します。以下のようなURLにリクエストを投げるとエリアコードに応じた結果が取得できます。

# 東京の場合はhttps://www.jma.go.jp/bosai/forecast/data/forecast/130000.json
https://www.jma.go.jp/bosai/forecast/data/forecast/エリアコード.json 

東京のエリアコードでリクエストを投げると以下のような結果になります。東京の各エリアに関して三日間(以下の場合3/30,3/30,4/1)の天気情報を取得することができます。

[{'publishingOffice': '気象庁',
  'reportDatetime': '2022-03-30T17:00:00+09:00',
  'timeSeries': [{'timeDefines': ['2022-03-30T17:00:00+09:00',
     '2022-03-31T00:00:00+09:00',
     '2022-04-01T00:00:00+09:00'],
    'areas': [{'area': {'name': '東京地方', 'code': '130010'},
      'weatherCodes': ['201', '212', '201'],
      'weathers': ['くもり\u3000夜のはじめ頃\u3000晴れ',
       'くもり\u3000夜\u3000雨',
       'くもり\u3000時々\u3000晴れ'],
      'winds': ['南の風\u300023区西部\u3000では\u3000南の風\u3000やや強く',
       '南の風\u3000後\u3000北東の風\u300023区西部\u3000では\u3000後\u3000北東の風\u3000やや強く',
       '北の風'],
      'waves': ['1メートル\u3000後\u30000.5メートル',
       '0.5メートル\u3000後\u30001メートル',
       '1メートル']},
     {'area': {'name': '伊豆諸島北部', 'code': '130020'},
      'weatherCodes': ['200', '212', '313'],
      'weathers': ['くもり\u3000所により\u3000雨',
       'くもり\u3000夜遅く\u3000雨',
       '雨\u3000後\u3000くもり'],
      'winds': ['南の風\u3000後\u3000南西の風',
       '南西の風\u3000後\u3000やや強く',
       '北東の風\u3000やや強く'],
      'waves': ['2メートル', '2メートル', '2.5メートル']},
     {'area': {'name': '伊豆諸島南部', 'code': '130030'},
      'weatherCodes': ['200', '212', '313'],
      'weathers': ['くもり\u3000所により\u3000雨',
       'くもり\u3000夜遅く\u3000雨',
       '雨\u3000後\u3000くもり'],
      'winds': ['南の風', '西の風\u3000後\u3000やや強く', '北東の風\u3000やや強く'],
      'waves': ['2.5メートル\u3000ただし\u3000三宅島\u3000では\u30002メートル',
       '2メートル',
       '2.5メートル\u3000後\u30004メートル\u3000ただし\u3000三宅島\u3000では\u30002.5メートル\u3000後\u30003メートル']},
--- 省略 ---

今回のゴール

全国の気象庁天気予報 JSON の中から「天気」、「風」、「波」の情報を CSVとして出力(降水確率や気温などは今回は対象外としています)

実行環境

macOS 11.3.1
Python 3.9.6

サンプルコード

# -*- coding: utf-8 -*-
import requests
import json
import csv

# エリアコード
area_dic = {'北海道/釧路':'014100',
            '北海道/旭川':'012000',
            '北海道/札幌':'016000',
            '青森県':'020000',
            '岩手県':'030000',
            '宮城県':'040000',
            '秋田県':'050000',
            '山形県':'060000',
            '福島県':'070000',
            '茨城県':'080000',
            '栃木県':'090000',
            '群馬県':'100000',
            '埼玉県':'110000',
            '千葉県':'120000',
            '東京都':'130000',
            '神奈川県':'140000',
            '新潟県':'150000',
            '富山県':'160000',
            '石川県':'170000',
            '福井県':'180000',
            '山梨県':'190000',
            '長野県':'200000',
            '岐阜県':'210000',
            '静岡県':'220000',
            '愛知県':'230000',
            '三重県':'240000',
            '滋賀県':'250000',
            '京都府':'260000',
            '大阪府':'270000',
            '兵庫県':'280000',
            '奈良県':'290000',
            '和歌山県':'300000',
            '鳥取県':'310000',
            '島根県':'320000',
            '岡山県':'330000',
            '広島県':'340000',
            '山口県':'350000',
            '徳島県':'360000',
            '香川県':'370000',
            '愛媛県':'380000',
            '高知県':'390000',
            '福岡県':'400000',
            '佐賀県':'410000',
            '長崎県':'420000',
            '熊本県':'430000',
            '大分県':'440000',
            '宮崎県':'450000',
            '鹿児島県':'460100',
            '沖縄県/那覇':'471000',
            '沖縄県/石垣':'474000'
            }

# CSV出力先
output_file = "weather_report.csv"

# CSVヘッダー
header = ["都道府県","データ配信元","報告日時",
          "地方名","予報日時","天気","風","波"]

def main():
    make_csv()

def make_csv():
    with open(output_file, 'w', encoding='utf-8') as f:
        writer = csv.writer(f, lineterminator="\n")
        writer.writerow(header)

        # JSONから情報を取得
        write_lists = get_info()

        # CSV書き込み
        writer.writerows(write_lists)

def get_info():
    write_lists = []
    base_url = "https://www.jma.go.jp/bosai/forecast/data/forecast/"
    for k, v in area_dic.items():

        if k.find("/"):
            prefecture = k[0:k.find("/")]
        else:
            prefecture = k

        url = base_url + v + ".json"

        res = requests.get(url).json()

        for re in res:
            publishingOffice = re["publishingOffice"]
            reportDatetime = re["reportDatetime"]

            timeSeries = re["timeSeries"]

            for time in timeSeries:
                #降水確率など今回のターゲット以外は除外する
                if 'pops' in time["areas"][0]:
                    pass
                elif 'temps' in time["areas"][0]:
                    pass
                elif 'tempsMax' in time["areas"][0]:
                    pass
                else:
                    for i in range(len(time["areas"])):

                        local_name = time["areas"][i]["area"]["name"]

                        for j in range(len(timeSeries[0]["timeDefines"])):

                            if 'weathers' not in time["areas"][i]:
                                weather = ""
                            else:
                                weather = time["areas"][i]["weathers"][j]

                            if 'winds' not in time["areas"][i]:
                                wind = ""
                            else:
                                wind = time["areas"][i]["winds"][j]

                            if 'waves' not in time["areas"][i]:
                                wave = ""
                            else:
                                wave = time["areas"][i]["waves"][j]

                            timeDefine = time["timeDefines"][j]

                            # 各情報をリストに格納
                            write_list = []
                            write_list.append(prefecture)
                            write_list.append(publishingOffice)
                            write_list.append(reportDatetime)
                            write_list.append(local_name)
                            write_list.append(timeDefine)
                            write_list.append(weather)
                            write_list.append(wind)
                            write_list.append(wave)

                            write_lists.append(write_list)
    return write_lists

if __name__ == '__main__':
    main()

結果は以下のようになりました。今回のゴールである「天気」、「風」、「波」の情報の取得に成功しました。 f:id:sanvarie:20220331152133p:plain

さいごに

このJSONを使えば簡単に天気予報情報を取得できることがわかりました。今回は省略しましたが、気温や降水確率なども取得できるので興味のある方はぜひチャレンジしてみてください。本日は以上です。