こんにちは、blueです。
今回は気象庁のAPIを使って天気予報情報を取得します。
この気象庁のサイトは正式なWebAPIではないですが、天気予報情報がJSON形式で取得できるようになっています。
引用:気象庁の天気予報JSONファイルをWebAPI的に利用したサンプルアプリ
その為今回はここから時間別天気予報を取得しようと思います。
なおWeb APIやJSONの記事は以下の書籍を参考にしています。
pythonですが会話形式で非常にわかりやすく書かれている書籍です。webAPIやスクレイピングを一から理解できる内容になっています。
今回のWeb API
今回のサイトは以下です。
このサイトではAPIの情報は見られませんが、JSONデータをもとにWebページが構成されているとのことです。
なお以下の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データについて以下で整形します。
得られたデータは以下のようになります。
なおすべて記載すると長くなってしまうので必要なところまでで切っています
[
{
"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やスクレイピングを一から理解できる内容になっています。
↓困ったときは以下が頼りになります。私も利用させてもらってます😊。
Selenium-VBAでのWebスクレイピングに関する記事はこちらをどうぞ
【ExcelVBA‐Selenium】【永久保存版】スクレイピングに必要なSeleniumのインストール方法教えます
【Selenium-VBA】Yahooメールへのログイン方法をわかりやすく説明する
ChromeでのWebスレイピングをできる限りわかりやすく説明する(Excel VBA)
【ExcelVBA‐Selenium】Chrome driverのバージョンエラーが出た時の対処法(2021/10/7更新)
【Selenium-VBA】Seleniumを用いたスクレイピングでテーブル情報を取得する1
【Selenium-VBA】スクレイピングをするのに必要なHTMLについて説明します1
【Selenim-VBA】起動済みのChromeを用いてSeleniumによるスクレイピングを行う
【Selenium-VBA】JavaScriptを使ってスクレイピングをしてみる1
【VBA】SeleniumBasicにおけるクラス、メソッド、プロパティ一覧(日本語版)
Web-APIを用いたデータ取得に関する記事はこちらをどうぞ
【VBA】Web APIを使ってデータを取得する(OpenWeatherMap)1
【VBA】Web APIを使って時間別天気予報を取得する(気象庁API)
【VBA】Web APIを使ってLINE通知を行う(LINE Notify)1
コメント