スポンサーリンク

【VBA】Web APIを使って時間別天気予報を取得する(気象庁API)

VBAスクレイピング

こんにちは、blueです。

今回は気象庁のAPIを使って天気予報情報を取得します。

この気象庁のサイトは正式なWebAPIではないですが、天気予報情報がJSON形式で取得できるようになっています。

引用:気象庁の天気予報JSONファイルをWebAPI的に利用したサンプルアプリ

その為今回はここから時間別天気予報を取得しようと思います。

なおWeb APIやJSONの記事は以下の書籍を参考にしています。

pythonですが会話形式で非常にわかりやすく書かれている書籍です。webAPIやスクレイピングを一から理解できる内容になっています。

スポンサーリンク

今回のWeb API

今回のサイトは以下です。

天気予報 – 気象庁

このサイトではAPIの情報は見られませんが、JSONデータをもとにWebページが構成されているとのことです。

引用:新しい気象庁サイトからJSONデータが取得できる件

なお以下のURLをリクエストすれば明後日までの天気概況を取得できるようですのでやってみます。

https://www.jma.go.jp/bosai/forecast/data/overview_forecast/(地域コード).json

しかしながらコード中の「地域コード」の取得が少し厄介なので次で説明します。

ちなみにAPIサイトと違ってサイトに登録⇒APIキーを取得する必要はないので楽です。

地域コード取得

以下はやまと@yamato1413さんのサイトです。

緯度経度から気象庁の天気予報用地域コードを取得するWebAPI

天気予報情報はURLに地域コードを入力すれば取得できるようなのですが、この地域コード自体の取得方法が一般人にはわかりません。

そこでもっと簡単に取得できるよう、緯度経度から地域コードを取得するWebAPIを作ってくださっています。

以下のURLの{lat}を緯度に、{lon}を経度に置き換えてhttpリクエストを送ると、JSONを返してくれます。

https://revgeo-forecastcode.herokuapp.com/lat={lat}+lon={lon}

なお緯度経度はGoogleMapを使えば簡単に取得することができます。

以下の参考記事をご覧ください。

実際に東京駅の緯度経度を入力したURLを打ち込むと以下のレスポンスが得られます。

クリックすると拡大します

ここのforcastcode」をリクエストのURLに打ち込めば、天気予報情報が取得できます。

全コード

VBAのHTTPリクエストを使ったコードは以下になります。

Option Explicit

Public Sub 気象庁天気取得()


  '気象庁から情報を取得
    Call ForecastData
     
End Sub

Private Sub ForecastData()

 '@yamato1413さんのサイトからforcastcode取得
 '{"forecastcode":"130000","prefname":"東京都",}
    
   Const forecastcode As String = "130000"
   
   Dim http As MSXML2.XMLHTTP60
   Set http = New MSXML2.XMLHTTP60
   Dim WeatherDateTime As String
   Dim RainDateTime As String
   Dim i As Long
   Dim j As Long

   
    With http
        Call .Open("GET", "https://www.jma.go.jp/bosai/forecast/data/forecast/" & forecastcode & ".json")
        Call .send
        
        Do
            If .readyState = 4 Then Exit Do
            DoEvents
        Loop
        
        'JSONを一行で出力
        ThisWorkbook.Worksheets(1).Range("A1").Value = .responseText
        
        'JSONパース
        Dim jsonObj As Object
        Set jsonObj = JsonConverter.ParseJson(.responseText)
          
        '東京地方の天気情報取得
        '天気
        For i = 1 To jsonObj(1)("timeSeries")(1)("areas")(1)("weathers").Count
            WeatherDateTime = Left(jsonObj(1)("timeSeries")(1)("timeDefines")(i), 19)
            Debug.Print WeatherDateTime & vbCrLf & jsonObj(1)("timeSeries")(1)("areas")(1)("weathers")(i)
        Next i
        
        '降水確率
        For j = 1 To jsonObj(1)("timeSeries")(2)("areas")(1)("pops").Count
            RainDateTime = Left(jsonObj(1)("timeSeries")(2)("timeDefines")(i), 19) & "から6時間ごとの降水確率"
            Debug.Print RainDateTime & " " & jsonObj(1)("timeSeries")(2)("areas")(1)("pops")(i) & "%"
        Next j
        

    End With
End Sub


各コードの説明

HTTPリクエスト

HTTPリクエストについては以下の記事をご確認ください。

基本的にここまでのやり方は同じです。

JSONの解析

HTMLオブジェクト.responseTextで取得したJSONデータについて以下で整形します。

JSONきれい ~JSON整形ツール~

得られたデータは以下のようになります。

なおすべて記載すると長くなってしまうので必要なところまでで切っています

[
	{
		"publishingOffice": "気象庁",
		"reportDatetime": "2022-04-16T05:00:00+09:00",
		"timeSeries": [
			{
				"timeDefines": [
					"2022-04-16T05:00:00+09:00",
					"2022-04-17T00:00:00+09:00"
				],
				"areas": [
					{
						"area": {
							"name": "東京地方",
							"code": "130010"
						},
						"weatherCodes": [
							"211",
							"111"
						],
						"weathers": [
							"くもり 昼過ぎ から 晴れ 所により 朝 まで 雨",
							"晴れ 昼過ぎ から くもり 所により 夜 雨"
						],
						"winds": [
							"北の風 23区西部 では はじめ 北の風 やや強く",
							"北の風 後 南の風"
						],
						"waves": [
							"1メートル 後 0.5メートル",
							"0.5メートル"
						]
					},
					{
						"area": {
							"name": "伊豆諸島北部",
							"code": "130020"
						},
						"weatherCodes": [
							"200",
							"200"
						],
						"weathers": [
							"くもり 所により 昼前 まで 雨",
							"くもり 所により 夜 雨"
						],
						"winds": [
							"北の風 強く 後 北東の風 やや強く",
							"北東の風 やや強く 後 東の風"
						],
						"waves": [
							"4メートル うねり を伴う ただし 新島 では 5メートル 後 4メートル うねり を伴う",
							"3メートル 後 2メートル うねり を伴う"
						]
					},
					{
						"area": {
							"name": "伊豆諸島南部",
							"code": "130030"
						},
						"weatherCodes": [
							"200",
							"201"
						],
						"weathers": [
							"くもり 所により 夜のはじめ頃 まで 雨",
							"くもり 時々 晴れ"
						],
						"winds": [
							"北の風 強く 後 北東の風 やや強く",
							"北東の風 やや強く 後 東の風"
						],
						"waves": [
							"6メートル 後 5メートル うねり を伴う ただし 三宅島 では 5メートル うねり を伴う",
							"4メートル 後 2.5メートル うねり を伴う"
						]
					},
					{
						"area": {
							"name": "小笠原諸島",
							"code": "130040"
						},
						"weatherCodes": [
							"201",
							"201"
						],
						"weathers": [
							"くもり 時々 晴れ",
							"くもり 時々 晴れ"
						],
						"winds": [
							"西の風 強く 後 北の風",
							"北東の風 後 東の風"
						],
						"waves": [
							"6メートル 後 3メートル うねり を伴う",
							"3メートル 後 2.5メートル うねり を伴う"
						]
					}
				]
			},
			{
				"timeDefines": [
					"2022-04-16T06:00:00+09:00",
					"2022-04-16T12:00:00+09:00",
					"2022-04-16T18:00:00+09:00",
					"2022-04-17T00:00:00+09:00",
					"2022-04-17T06:00:00+09:00",
					"2022-04-17T12:00:00+09:00",
					"2022-04-17T18:00:00+09:00"
				],
				"areas": [
					{
						"area": {
							"name": "東京地方",
							"code": "130010"
						},
						"pops": [
							"20",
							"10",
							"10",
							"0",
							"0",
							"10",
							"20"

このJSONのデータ構成は以下のようになっています。

  • 最初のキーの”timeSeries”は各項目の日時のまとまりを表しています。日時の表記、数は項目(天気、降水確率、気温)によりバラバラなので値はオブジェクト型をまとめた配列としています(以下図緑)
  • キー”areas”は東京のコード内の地方を表しています。1は東京地方、2は伊豆諸島北部を表します
  • キー”weathers”は天気を表しています。値は配列であり、各日時の値を示しています(以下図青)
  • キー”pops”は降水確率を表しています。値は配列であり、各日時の値を示しています(以下図橙)

これらのことから気象庁のサイトは以下のように解釈することができます。

クリックすると拡大します

このようにしてJSONデータを読み解いた後で、データ取得を行っていきます。

なお日本語文字が含まれるデータに対してVBA-JSONでJSONパースする場合は、JsonConverterモジュール内のjson_Encode関数について以下のように書き換えます。
●書き換え前

Private Function json_Encode(ByVal json_Text As Variant) As String
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       Case 0 To 31, 127 To 65535
            ' Non-ascii characters -> convert to 4-digit hex
            json_Char = "\u" & VBA.Right$("0000" & VBA.Hex$(json_AscCode), 4)
        End Select 

●書き換え後

Private Function json_Encode(ByVal json_Text As Variant) As String
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       Case 0 To 31, 127 'To 65535を消去する
            ' Non-ascii characters -> convert to 4-digit hex
            json_Char = "\u" & VBA.Right$("0000" & VBA.Hex$(json_AscCode), 4)
        End Select 

この処理によってJSONパースした文字列もについても日本語で表示されるようになります。

参考:宇宙一わかりやすい?VBA-JSONを使ったJSONパースのしかた

データ取得

 '天気
        For i = 1 To jsonObj(1)("timeSeries")(1)("areas")(1)("weathers").Count
            WeatherDateTime = Left(jsonObj(1)("timeSeries")(1)("timeDefines")(i), 19)
            Debug.Print WeatherDateTime & vbCrLf & jsonObj(1)("timeSeries")(1)("areas")(1)("weathers")(i)
        Next i

キーが”weathers”にあたる部分の値を取得します。

しかしながらこの値(配列)の数は取得する時間帯によって異なります。

その為jsonObj(1)(“timeSeries”)(1)(“areas”)(1)(“weathers”).Countによって、連想配列の値の個数を取得し、ループをかけるようにしています。

また同時に該当する天気の日時も取得して、天気の前に表示するようにしています。

  '降水確率
        For j = 1 To jsonObj(1)("timeSeries")(2)("areas")(1)("pops").Count
            RainDateTime = Left(jsonObj(1)("timeSeries")(2)("timeDefines")(i), 19) & "から6時間ごとの降水確率"
            Debug.Print RainDateTime & " " & jsonObj(1)("timeSeries")(2)("areas")(1)("pops")(i) & "%"
        Next j

こちらはキーが”pops”にあたる部分の値を取得しています。

こちらも同じく値の数の変動を考慮して連想配列の値の個数分ループをかけています。

結果として得られるものは以下になります。

2022-04-16T17:00:00
晴れ 夜のはじめ頃 くもり
2022-04-17T00:00:00
晴れ 後 くもり 夜 雨
2022-04-18T00:00:00
くもり
2022-04-17T12:00:00から6時間ごとの降水確率 30%
2022-04-17T12:00:00から6時間ごとの降水確率 30%
2022-04-17T12:00:00から6時間ごとの降水確率 30%
2022-04-17T12:00:00から6時間ごとの降水確率 30%
2022-04-17T12:00:00から6時間ごとの降水確率 30%

このようにして気象庁のAPIからも天気予報情報を取得することができました。

今回のまとめ

今回は気象庁のAPIを使って天気予報情報を取得しました。

今回のサイトは正式なWebAPIではなかったですが、キーを変更すれば風や波、気温といった情報もとることができます。

このようにWeb APIを使えるとサイトの情報全体もとってくることができるようになるので活用していただければ幸いです。

pythonですが会話形式で非常にわかりやすく書かれている書籍です。webAPIやスクレイピングを一から理解できる内容になっています。

↓困ったときは以下が頼りになります。私も利用させてもらってます😊。

TVCMで話題のココナラ

VBAでのスクレイピング、Web APIの記事は以下をどうぞ

ChromeでのWebスレイピングをできる限りわかりやすく説明する1(Excel VBA)

【VBA】SeleniumBasicにおけるクラス、メソッド、プロパティ一覧(日本語版)
【VBA】Seleniumを用いたスクレイピングでテーブル情報を取得する1

【VBA】スクレイピングをするのに必要なHTMLについて説明します1

【VBA】起動済みのChromeを用いてSeleniumによるスクレイピングを行う

【VBA】Web APIを使ってデータを取得する(OpenWeatherMap)1

【VBA】Web APIを使ってデータを取得する(OpenWeatherMap)5 全コード

コメント

タイトルとURLをコピーしました