アシアル情報教育研究所・所長の岡本です。

先日、気象庁のWebサイトがリニューアルされました。
それに伴い、天気予報情報がJSON形式で取得できるようになりました。

正式な公開のWebAPIではなく、サイト内部で利用されているデータではありますが、
「政府標準利用規約に準拠してご利用いただける」
との情報が、気象庁の中の人から出ました。

詳細は窓の杜の記事が詳しいです。
「気象庁公式の天気予報API(?)が発見 ~Twitterの開発者界隈に喜びの声が満ちる」

なんにせよ、登録不要で気象予報のデータが利用できるのは有り難い。

そこで、『Monaca Education』用のサンプルアプリを作ってみることにしました。
なお、JSONデータの項目に対する解説などは無保証・岡本所長の独自解釈ですので、気象庁などに問い合わせることはしないでください。

サンプルアプリ

気象庁の天気予報WebAPI経由で表示(東京都の概要)、のサンプルアプリ
気象庁の天気予報をWebAPI経由で表示・東京都の詳細、のサンプルアプリ
※ Monaca Educationにログインしてからクリックするとダイレクトインポートできます

エンドポイントの確認

以下のURLにブラウザで直接アクセスすれば、JSONデータを確認できます。
JSONなので人間には少し読みにくいですが、気象予報の情報であることは、感じ取れると思います。

・東京都の天気予報の概要を取得する
https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json

・東京地方の今日・明日・明後日の天気予報を取得する
https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json

サンプル①:気象庁の天気予報WebAPI経由で表示(東京都の概要)の解説

こちらで利用するJSONには、気象庁の気象予測の概要(overview_forecast)が入っています。一次元の簡単なJSONデータなのでプログラミング入門者でも比較的容易に操作できるかと思います。

JSONデータのフォーマット

publishingOffice データ配信元。基本的に「気象庁」と入っている。
reportDatetime 報告日時。「+09:00」という部分はタイムゾーン
targetArea 対象の地域。130000.jsonは基本的に「東京都」。13が東京なのは、都道府県コードがそうなっているから。
headlineText ヘッドラインです
text 詳細な概要情報です。改行は「\n\n」なので、ブラウザなどに表示するときはbrタグに変更する必要がある。

JSONの取得方法

 JavaScriptでJSONを外部から取得する際にはfetch()命令が利用できます。今回は特別なパラメーターやヘッダーを送る必要も無いため、JSONがある場所のURLを第一引数に指定して利用します。また、取得に成功した際の処理を関数(このケースでは無名関数)で指定します。

 なぜfetchでは成功したときの処理を関数で指定するか、理由の一つは非同期処理だからです。非同期にしておくことでfetchの成否や完了に関わらず、次の処理に進めることができます。また、fetchによるJSONの取得が終わり次第、指定した関数が非同期的に処理されます。

取得結果をHTML側に反映する

 DOM技術を使って画面に天気予報の情報を書き出します。今回はHTML側をTABLEタグで構成しており、行単位でID名を振ってあります。そこで行のID名を元に、情報を反映したいセルを特定します。

例:「発表者(publishingOffice)」の行をgetElementById()で指定し、行の子要素であるセルから「最後の子要素」をlastElementChildとして探り当て、textContentプロパティに天気予報の値を代入してHTML側に反映する。


document.getElementById("publishingOffice").lastElementChild.textContent

HTML側(index.html)


<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: content: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script src="js/main.js" async></script>
</head>
<body>
    <h1>気象庁の天気予報WebAPI経由で表示<br>東京都の概要</h1>
    <table>
        <tr id="publishingOffice">
            <th>発表者</th>
            <td></td>
        </tr>
        <tr id="reportDatetime">
            <th>報告日時</th>
            <td></td>
        </tr>
        <tr id="targetArea">
            <th>対象地域</th>
            <td></td>
        </tr>
        <tr id="headlineText">
            <th>ヘッドライン</th>
            <td></td>
        </tr>
        <tr id="text">
            <th>詳細</th>
            <td></td>
        </tr>
    </table>
</body>
</html>

メインのコード(js/main.js)


// 東京(130000)の予報を取得
let url = "https://www.jma.go.jp/bosai/forecast/data/overview_forecast/130000.json";
 
fetch(url)
   .then(function(response) {
       return response.json();
   })
   .then(function(weather) {
       console.log(weather);
       // 画面に書き出す
       document.getElementById("publishingOffice").lastElementChild.textContent = weather.publishingOffice;
       document.getElementById("reportDatetime").lastElementChild.textContent = weather.reportDatetime;
       document.getElementById("targetArea").lastElementChild.textContent = weather.targetArea;
       document.getElementById("headlineText").lastElementChild.textContent = weather.headlineText;
       document.getElementById("text").lastElementChild.innerHTML = weather.text.replace(/\n\n/g, '<br>');
   });

サンプルアプリ②:気象庁の天気予報をWebAPI経由で表示・東京都の詳細の解説

 こちらのJSONは「概要」に比べると複数の地域の情報があり、また、今日・明日・明後日の3日分の天気予報情報がはいっているため、情報量が多く、階層も深くなっています。

weathers 天気の文字列。「くもり 時々 晴れ」や「くもり」など
weatherCodes 天気がコード化された情報。

HTML側(index.html)


<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <meta http-equiv="Content-Security-Policy" content="default-src * data: gap: content: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
    <script src="components/loader.js"></script>
    <link rel="stylesheet" href="components/loader.css">
    <link rel="stylesheet" href="css/style.css">
    <script src="js/main.js" async>
    </script>
</head>
<body>
    <h1>気象庁の天気予報WebAPI経由で表示<br>東京の詳細</h1>
  
    <table>
        <tr id="publishingOffice">
            <th>発表者</th>
            <td></td>
        </tr>
        <tr id="reportDatetime">
            <th>報告日時</th>
            <td></td>
        </tr>
        <tr id="targetArea">
            <th>対象地域</th>
            <td></td>
        </tr>
        <tr id="today">
            <th>今日の天気</th>
            <td></td>
        </tr>
        <tr id="tomorrow">
            <th>明日の天気</th>
            <td></td>
        </tr>
        <tr id="dayAfterTomorrow">
            <th>明後日の天気</th>
            <td></td>
        </tr>
    </table>
</body>
</html>

メインのコード(js/main.js)


// 東京(130000)の予報を取得
let url = "https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json";

fetch(url)
    .then(function(response) {
        return response.json();
    })
    .then(function(weather) {
        console.log(weather);
        // 特定の地域(今回は東京)だけ選択して変数に詰め直す
        let area = weather[0].timeSeries[0].areas[0];
        console.log(area); 
        // 発表者と報告日時の情報を画面に書き出す
        document.getElementById("publishingOffice").lastElementChild.textContent = weather[0].publishingOffice;
        document.getElementById("reportDatetime").lastElementChild.textContent = weather[0].reportDatetime;
        // 特定地域の情報を画面に書き出す
        document.getElementById("targetArea").lastElementChild.textContent = area.area.name;
        document.getElementById("today").lastElementChild.textContent = area.weathers[0];
        document.getElementById("tomorrow").lastElementChild.textContent = area.weathers[1];
        document.getElementById("dayAfterTomorrow").lastElementChild.textContent = area.weathers[2];
    });

まとめ

 都道府県別の今日・明日・明後日の天気予報は上記のようなプログラムで取得可能であることが分かりました。東京以外の地域で使いたい時には、「130000」の部分を別の都道府県コードに変えれば、取得できると思います。また、今回は利用していませんが、JSONの中には最低気温・最高気温、風速なども入っていそうです。