【JavaScript】気象庁から天気予報を取得してみる

気象庁が公開している天気予報のデータを利用して、JavaScriptをで天気情報を取得・表示します。
下のプログラムを試してください、3日分の天気と風の情報が表示されます。このコードをもとにして解説していきます。

天気予報(気象庁データ)


<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>天気予報(気象庁データ)</title>
  <style>
    body {
      margin: 0;
      padding: 0;
      background: linear-gradient(135deg, #a8edea, #fed6e3);
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      align-items: center;
      color: #333;
    }
    
    .container {
      width: 90%;
      max-width: 1200px;
      background-color: rgba(255,255,255,0.9);
      border-radius: 8px;
      padding: 20px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.1);
      margin: 30px 0;
    }
    
    .controls {
      display: flex;
      flex-wrap: wrap;
      justify-content: center;
      margin-bottom: 20px;
    }
    
    select {
      margin: 10px;
      padding: 10px 15px;
      font-size: 16px;
      border: 1px solid #ccc;
      border-radius: 4px;
      outline: none;
      transition: all 0.3s ease;
    }
    
    select:focus {
      border-color: #007BFF;
      box-shadow: 0 0 5px rgba(0,123,255,0.5);
    }
   
    table {
      width: 100%;
      border-collapse: collapse;
      margin: 20px 0;
    }
    
    th, td {
      padding: 12px;
      text-align: center;
      border-bottom: 1px solid #ddd;
    }
    
    th {
      background-color: #f8f8f8;
      font-weight: bold;
    }
    
    tr:hover {
      background-color: #f1f1f1;
    }
    
    @media (max-width: 600px) {
      th, td {
        padding: 8px;
      }
      select {
        width: 100%;
        margin: 5px 0;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    天気予報(気象庁データ)
    <div class="controls">
      <select id="areaSelect">
        <option value="">都道府県を選択</option>
      </select>
    </div>
    <div id="weatherInfo"></div>
  </div>

  <script>
    let areaData = null;

    document.getElementById('areaSelect').addEventListener('change', searchWeather);

    // エリアデータ取得
    async function loadAreaData() {
      try {
        const response = await fetch('https://www.jma.go.jp/bosai/common/const/area.json');
        areaData = await response.json();
        populateAreaSelect();
      } catch (error) {
        console.error('エリアデータ取得エラー:', error);
      }
    }
    loadAreaData();

    // セレクトに都道府県を追加
    function populateAreaSelect() {
      const select = document.getElementById('areaSelect');
      for (const code in areaData.offices) {
        const name = areaData.offices[code].name;
        const option = document.createElement('option');
        option.value = code;
        option.textContent = name;
        select.appendChild(option);
      }
    }

    // 天気予報データの取得と表示
    async function searchWeather() {
      const select = document.getElementById('areaSelect');
      const officeCode = select.value;
      const officeName = select.options[select.selectedIndex].text;

      if (!officeCode) {
        document.getElementById('weatherInfo').innerHTML = '<p>都道府県を選択してください。</p>';
        return;
      }
      
      const url = `https://www.jma.go.jp/bosai/forecast/data/forecast/${officeCode}.json`;
      try {
        const response = await fetch(url);
        const data = await response.json();
        const forecastHTML = displayForecast(data, officeName);
        document.getElementById('weatherInfo').innerHTML = forecastHTML;
      } catch (error) {
        console.error(`${officeName} の天気予報取得エラー:`, error);
        document.getElementById('weatherInfo').innerHTML = `<p>${officeName} の天気予報を取得できませんでした。</p>`;
      }
    }

    // 予報データの日時をフォーマット
    function formatForecastDate(dateStr) {
      const date = new Date(dateStr);
      const options = { month: 'numeric', day: 'numeric', weekday: 'short' };
      return date.toLocaleDateString('ja-JP', options);
    }

    // 取得した天気予報データをテーブル形式に組み立てて表示
    function displayForecast(data, officeName) {
      if (!Array.isArray(data) || data.length === 0) {
        return `<p>${officeName} の天気予報データがありません。</p>`;
      }

    const forecastObj = data[0];
    const timeSeries = forecastObj.timeSeries;
    // 天気情報のタイムシリーズ
    const weatherSeries = timeSeries[0];
    const timeDefines = weatherSeries.timeDefines; // 予報日時の配列

    let forecastHTML = `<b>${officeName} の天気予報<br></b>`;
  
    // 複数エリアの場合に対応
    for (const area of weatherSeries.areas) {
      const areaName = area.area.name;
      const weathers = area.weathers || [];
      const winds = area.winds || [];
    
      forecastHTML += `<b>${areaName}</b>`;
      forecastHTML += `<table>
        <tr>
          <th width="100px;">日付</th>
          <th width="40%;">天気</th>
          <th width="40%;">風向・風速</th>
        </tr>`;
    
      const numDays = Math.min(weathers.length, timeDefines.length);  // 配列長の不一致に対応
    
      for (let i = 0; i < numDays; i++) {
        const formattedDate = formatForecastDate(timeDefines[i]);
        const weatherText = weathers[i] || "-";
        const wind = winds[i] || "-";
      
        forecastHTML += `
        <tr>
          <td>${formattedDate}</td>
          <td>${weatherText}</td>
          <td>${wind}</td>
        </tr>`;
        }
    
        forecastHTML += `</table>`;
      }
      return forecastHTML;
    }
  </script>

</body>
</html>

1. 天気予報の取得方法

まず、気象庁では、天気予報の情報を毎日5時・11時・17時の1日3回発表しているようです。
https://www.data.jma.go.jp/suishin/cgi-bin/catalogue/make_product_page.cgi?id=Jikeiret

その、天気予報はjson形式で取得が可能です。

https://www.jma.go.jp/bosai/forecast/data/forecast/{コード}.json

{コード} にエリアコードを入れて、アクセスすると取得できます。
(例:東京  https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json

また、エリアコード情報は、https://www.jma.go.jp/bosai/common/const/area.json から取得できます。

2. JavaScriptによる実装ポイント

JavaScript部分では、APIからデータを取得し、DOMに情報を動的に反映させる実装がされています。このセクションでは、コードの各機能を詳細に解説していきます。

2.1 非同期通信と async/await の活用

Webアプリケーションでは、サーバーと通信してデータを非同期で取得する必要があります。fetch APIとasync/await構文を用いることで、読みやすく直感的な非同期処理を実現しています。

  • 非同期関数 loadAreaData() この関数は気象庁提供のエリアデータ(地域情報)を取得するために動作します。

async function loadAreaData() {
  try {
    const response = await fetch('https://www.jma.go.jp/bosai/common/const/area.json');
    areaData = await response.json();
    populateAreaSelect();
  } catch (error) {
    console.error('エリアデータ取得エラー:', error);
  }
}

こでは、 await を使用して fetch のレスポンスが返ってくるのを待ち、その後JSONパースし、さらに populateAreaSelect() 関数を呼び出すことで、取得したデータから都道府県の選択肢を自動生成しています。 このような実装により、非同期通信の動作がシンプルに記述でき、エラーハンドリング(try/catch)でネットワークエラーやデータ形式の問題にも対処できるようにしています。

エリアデータ(area.json)

https://www.jma.go.jp/bosai/common/const/area.json は、気象庁が提供するJSONデータで、日本全国の地域情報に関するデータを格納しています。

内容の概要

このJSONファイルには、気象情報を取得する際に使用する「エリアコード」や「地名」などの情報が含まれています。
主に以下のようなデータ構造になっています。

  • centers(気象庁の管轄する地域センター情報)
  • offices(気象台・測候所の情報)
  • class10s(市区町村を含む細かい地域情報)
  • class15s(さらに細かい地域)
  • class20s(詳細な地域)

各エリアには「コード」や「名称(日本語・英語)」などの情報が含まれ、気象データのAPIを利用する際に、このエリア情報を使って地域を指定できます。

用途

  • 気象データ取得: 気象庁APIを使用する際に、どの地域の天気予報や警報情報を取得するかを指定するためのリストとして活用できます。
  • 地域ごとの気象解析: 例えば、天気予報や警報・注意報などを市区町村単位で取得する際に、このJSONデータを利用してエリアコードを参照できます。

活用法

ある県の天気を取得したい場合、

  1. area.json から対象の県のコードを探す
  2. そのコードを使って気象庁のAPI( https://www.jma.go.jp/bosai/forecast/data/forecast/{コード}.json)にアクセス

このようにして、特定の地域の天気予報をjson形式で取得できます。

https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json にアクセスすると、東京都の天気予報データが取得できます。

  • 都道府県選択後の処理 searchWeather() ユーザーが都道府県を選択した際に呼び出され、選択された地域の天気予報データを取得、表示する処理を記述しています。
async function searchWeather() {
  const select = document.getElementById('areaSelect');
  const officeCode = select.value;
  const officeName = select.options[select.selectedIndex].text;

  if (!officeCode) {
    document.getElementById('weatherInfo').innerHTML = '<p>都道府県を選択してください。</p>';
    return;
  }
  
  const url = `https://www.jma.go.jp/bosai/forecast/data/forecast/${officeCode}.json`;
  try {
    const response = await fetch(url);
    const data = await response.json();
    const forecastHTML = displayForecast(data, officeName);
    document.getElementById('weatherInfo').innerHTML = forecastHTML;
  } catch (error) {
    console.error(`${officeName} の天気予報取得エラー:`, error);
    document.getElementById('weatherInfo').innerHTML = `<p>${officeName} の天気予報を取得できませんでした。</p>`;
  }
}

ここでは、まず select 要素から選択された値(気象庁のエリアコード)と、表示用の地域名を取得しています。もし値が空であれば、ユーザーに適切なメッセージを表示し、処理を終了します。 その後、テンプレートリテラルを利用してURLを組み立て、該当する天気予報データのJSONを取得。取得したデータは displayForecast() 関数へ渡され、結果としてHTMLが生成され、DOMに挿入される仕組みになっています。

2.2 JSONデータの理解と予報データの構造

気象庁が提供する天気予報データは、複数の階層からなるJSON形式になっています。このサンプルでは、特に次の要素が重要です。

  • timeSeries:予報情報が時系列に沿って記録されている配列です。この中には、天気、降水確率、風向や風速など、さまざまな要素が含まれる可能性があります。
  • timeDefines:予報日時が配列として格納されており、これをもとに各日の天気や風情報が対応付けられています。
  • areas:1つのタイムシリーズ内で、複数の地域(エリア)毎に天気情報が分かれている場合があります。ここでは、各地域の名前や、対応する天気予報のテキスト、さらに風向・風速の情報が配列として格納されており、コード内ではこれらの情報をループで処理してテーブルを生成しています。

天気予報データ(コード.json)

https://www.jma.go.jp/bosai/forecast/data/forecast/${officeCode}.json は、気象庁が提供する天気予報API の一部で、特定の地域(管区気象台)ごとの天気予報データを取得するためのエンドポイントです。

使い方

${officeCode} の部分に 気象庁のオフィスコード(気象台・測候所の識別コード)を入れると、その地域の天気予報データを取得できます。
このオフィスコードは、次のJSONから取得できます: 🔗 https://www.jma.go.jp/bosai/common/const/area.json

例えば:

  • 130000(東京都)
  • 270000(大阪府)
  • 400000(福岡県)

これを使って https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json にアクセスすると、東京都の天気予報データが取得できます。

取得できるデータ

JSON形式で天気予報が返され、主に以下の情報を含みます。

1. publishingOffice(発表機関)

発表した気象台の名前
例: "publishingOffice": "東京地方気象台"

2. reportDatetime(発表日時)

データが発表された日時(ISO 8601形式)
例: "reportDatetime": "2025-04-01T05:00:00Z"

3. timeSeries(時間帯ごとの予報)

  • 天気(晴れ、曇り、雨 など)
  • 気温(最高・最低)
  • 降水確率
  • 風向・風速
    などが時間帯ごとにまとめられています。

例:

"timeSeries": [
  {
    "timeDefines": ["2025-04-01T09:00:00Z", "2025-04-01T15:00:00Z", "2025-04-01T21:00:00Z"],
    "areas": [
      {
        "area": { "name": "東京", "code": "130010" },
        "weathers": ["晴れ", "曇り", "雨"],
        "temps": [15, 18, 12]
      }
    ]
  }
]

2.3 予報情報の表示(displayForecast()関数)

displayForecast() 関数は、取得したJSONデータを利用してユーザーに視覚的にわかりやすいテーブルを生成するための仕組みを提供します。

function displayForecast(data, officeName) {
  if (!Array.isArray(data) || data.length === 0) {
    return `<p>${officeName} の天気予報データがありません。</p>`;
  }

  const forecastObj = data[0];
  const timeSeries = forecastObj.timeSeries;
  const weatherSeries = timeSeries[0];
  const timeDefines = weatherSeries.timeDefines;

  let forecastHTML = `<b>${officeName} の天気予報<br></b>`;
  
  for (const area of weatherSeries.areas) {
    const areaName = area.area.name;
    const weathers = area.weathers || [];
    const winds = area.winds || [];
  
    forecastHTML += `<b>${areaName}</b>`;
    forecastHTML += `<table>
      <tr>
        <th width="100px;">日付</th>
        <th width="40%;">天気</th>
        <th width="40%;">風向・風速</th>
      </tr>`;
  
    const numDays = Math.min(weathers.length, timeDefines.length);
  
    for (let i = 0; i < numDays; i++) {
      const formattedDate = formatForecastDate(timeDefines[i]);
      const weatherText = weathers[i] || "-";
      const wind = winds[i] || "-";
    
      forecastHTML += `
      <tr>
        <td>${formattedDate}</td>
        <td>${weatherText}</td>
        <td>${wind}</td>
      </tr>`;
    }
    
    forecastHTML += `</table>`;
  }
  return forecastHTML;
}

この関数では、まず取得したデータが配列であること、またデータが存在するかをチェックします。不正なデータであれば、エラーに近いメッセージを返すようにしてユーザーに知らせます。 その後、最初のタイムシリーズの情報から、各エリアごとに天気予報情報を抽出。日付は formatForecastDate() 関数によりフォーマットされ、テーブルの形式で整然と出力されます。 こうした実装は、抽出したデータ量や構造が変更されても、柔軟に対応できるよう設計されており、メンテナンス性の高さが評価されるポイントです。

2.4 日付フォーマットの工夫

気象庁のデータに含まれる日付はISO形式などの標準的な形式で与えられる場合が多いですが、ユーザーにとって分かりやすい形式に変換する必要があります。 formatForecastDate() 関数は、Date オブジェクトとtoLocaleDateString メソッドを利用して、シンプル且つ日本語の曜日情報などを含めた形式に変換しています。

function formatForecastDate(dateStr) {
  const date = new Date(dateStr);
  const options = { month: 'numeric', day: 'numeric', weekday: 'short' };
  return date.toLocaleDateString('ja-JP', options);
}

このようにすることで、たとえば「4/1 (火)」のような表示形式となり、ユーザーにとって直感的に理解しやすい情報となります。

まとめ

今回の記事では、気象庁が提供している天気予報データを取得し、HTML/CSS/JavaScriptで表示する一連のプロセスについて詳しく解説しました。以下のポイントが特に重要です。

  • 非同期通信の習得fetch APIasync/awaitを利用することで、スムーズなデータ取得が実現できます。
  • 堅牢なエラーハンドリングtry/catch によるエラーハンドリング、及びデータ整形の工夫により、予期せぬエラーにも対処できるコード設計となっています。
  • 拡張性の高さ: 基本機能はシンプルながら、追加情報の統合、UI/UXの向上、自動更新機能、さらには最新のWebフレームワークやAR/VRとの連携といった、さまざまな発展の可能性を秘めています。

このプロジェクトは、Web APIを利用する上での基礎から応用までの知識を実践的に学ぶための絶好の教材です。実際に手を動かして、コードを読み解き、機能拡張を試みることで、現代のWeb開発に必要なスキルセットが大いに向上するでしょう。

今回のコードはシンプルかつ拡張性が高く、非常に実践的だと思います。皆さんもぜひ、このサンプルをベースに、自分なりのカスタマイズや機能追加に挑戦してみてください。