0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

気象庁サイトを利用したビューアの作成 11 警報(表)

0
Posted at

目次・全体的な注意点(第1回の記事)

今回は、気象に関する警報・注意報の表示ページを作成していきます(2026年5月28日午後に行われた防災気象情報の体系整理後の気象庁ホームページに対応した内容です)

本ページ内では「レベル5特別警報」「レべル4危険警報」「レベル3警報」「レベル2注意報」「特別警報」「警報」「注意報」を「警報・注意報」と総称します

氾濫警報・注意報(指定河川洪水予報)に関する説明は別の記事で扱います

警報・注意報とは

災害が予想される際に気象庁が発表する情報です

2026年5月の防災気象情報の体系整理以降は、大雨・土砂災害・河川の氾濫・高潮に関する情報は「レベル5特別警報」「レベル4危険警報」「レベル3警報」「レベル2注意報」の段階に整理され、住民がとるべき行動と対応する形になりました。内閣府や気象庁は、警戒レベル4の情報が発表された際・発表されるまでに、ハザードマップなどで危険が予測される地域から避難することをお勧めしています

防災気象情報と警戒レベルとの対応について(気象庁)

その他の現象に関する情報は、「特別警報」「警報」「注意報」の3段階となっています

危険度 気象庁が発表 説明
↑高 特別警報 警報の基準を大きく超えるような、数十年に一度の台風や大雪が予想される場合に発表
警報 重大な災害が予想される場合に発表
注意報 災害が予想される場合に発表。また、先の時間に警報を発表する可能性がある時にも発表される

apiのURL

他の情報と同様、ブラウザの開発者ツールでネットワークタブを開いた状態で気象庁ホームページにアクセスし、Fetch/XHRでフィルタするとデータを格納したファイルが見つかります

全国の警報・注意報の発表状況は https://www.jma.go.jp/bosai/warning/data/r8/map.json に、都道府県ごとの警報・注意報の発表状況は https://www.jma.go.jp/bosai/warning/data/r8/{officeCode}.json に格納されています。{officeCode}の部分は都道府県によって異なり、地域ごとのコード番号は https://www.jma.go.jp/bosai/common/const/area.json に格納されています

なお、氾濫警報・注意報(指定河川洪水予報)は https://www.jma.go.jp/bosai/flood/data/r8/flood_xml.json に格納されます

apiの構造

気象庁ホームページの内部apiの構造は、気象庁防災情報XMLの構造をモデルとしているものが多いです。このため、気象庁防災情報XMLの解説資料が参考になる場合が多いです

警報関連の電文の説明は「気象警報・注意報時系列情報(R06)_解説資料.pdf」としてまとめられており、この資料の内容が参考になります

以下では、都道府県ごとのファイル https://www.jma.go.jp/bosai/warning/data/r8/{officeCode}.json を例に説明します
(全国のファイル https://www.jma.go.jp/bosai/warning/data/r8/map.json でも一部追加的な情報がなくなるだけで構造は同じです)

{officeCode}.json
[
  {
    "controlDatetime": "2026-06-06T04:30:37Z",
    "reportDatetime": "2026-06-06T13:30:00+09:00",
    "infoType": "発表",
    "publishingOffice": "名瀬測候所",
    "headlineText": "警報を解除します。",
    "warning": {
      "class10Items": [
        {
          "areaCode": "460040",
          "kinds": [
            { "code": "03", "status": "解除"}
          ]
        }
      ],
      "class20Items": [
        {
          "areaCode": "4622200",
          "kinds": [
            { "code": "10", "status": "解除"}
          ]
        },
        {
          "areaCode": "4630400",
          "kinds": [
            { "status": "発表警報・注意報はなし"}
          ]
        },......
      ]
    },
    "dataTypeCode": "VPWW55"
  },
  {
    "controlDatetime": "2026-06-06T04:30:37Z",
    "reportDatetime": "2026-06-06T13:30:00+09:00",
    "infoType": "発表",
    "publishingOffice": "名瀬測候所",
    "headlineText": "奄美地方では、土砂災害に注意してください。",
    "notice": "令和7年7月3日の地震で揺れの大きかった十島村と、令和8年5月20日の地震で揺れの大きかった与論町では、土砂災害に関する警報等の発表基準について通常より引き下げた暫定基準で運用しています。",
    "warning": {
      "class10Items": [
        {
          "areaCode": "460040",
          "kinds": [
            { "code": "29", "status": "危険警報から注意報"}
          ]
        }
      ],
      "class20Items": [
        {
          "areaCode": "4622200",
          "kinds": [
            { "code": "29", "status": "継続"}
          ]
        },
        {
          "areaCode": "4630400",
          "kinds": [
            { "code": "29", "status": "継続"}
          ]
        },......
      ]
    },
    "dataTypeCode": "VPWW56"
  },......
]

大まかには、class10Items以下に1次細分区域(○○県北部、○○県南部 等)ごとの発表状況が、class20Items以下に2次細分区域(おおむね市町村ごと)の発表状況が格納されています

{
  "areaCode": "4622200",
  "kinds": [
    { "code": "29", "status": "継続"}
  ]
}

上のコードは、areaCode 4622200(奄美市)に、警報コード29(レベル2土砂災害注意報)が継続して発表されていることを示します。areaCodeは先に述べた通り https://www.jma.go.jp/bosai/common/const/area.json に対応表があります

警報コードは解説資料の別表内に記載されており、以下の通りとなっています。(かっこ付きの情報は2026年時点では運用されていません)

現象 特別警報 危険警報 警報 注意報
大雨 33 43 03 10
土砂災害 39 49 09 29
氾濫 34 44 04 18
高潮 38 48 08 19
大雪 36 (46) 06 12
暴風/強風 35 (45) 05 15
暴風雪/風雪 32 (42) 02 13
波浪 37 (47) 07 16
14
融雪 17
濃霧 20
乾燥 21
なだれ 22
低温 23
24
着氷 25
着雪 26
その他 (27)

statusは「発表」「継続」「解除」「発表警報・注意報はなし」と「警報から注意報」等 警報以上の情報からの格下げを表すものがあります。「解除」以外であれば発表されているとみなせばOKです

警報・注意報が発表されていない場合は、以下のようにstatusが「解除」「発表警報・注意報はなし」となります。後者の場合はcode要素がなくなるので注意してください

{
  "areaCode": "4622200",
  "kinds": [
    { "code": "10", "status": "解除"}
  ]
},
{
  "areaCode": "4630400",
  "kinds": [
    { "status": "発表警報・注意報はなし"}
  ]
}

なお、警報・注意報は現象の種別ごとに7つの電文に分かれていますが、jsonファイルはこれらの電文を結合したものになっています。電文の種類はdataTypeCodeとして格納されています

dataTypeCode 説明
VPWW55 大雨警報・注意報
VPWW56 土砂災害警報・注意報
VPWW57 高潮警報・注意報
VPWW58 暴風(暴風雪)警報・注意報
VPWW59 波浪警報・注意報
VPWW60 大雪警報・注意報
VPWW61 その他の警報・注意報

表示用のコード

ここまでの内容を表に起こしていきます。今回は単一の都道府県の警報・注意報の発表状況を表形式で表示するページを作成します

警報の危険度別の配色を定義します。配色は 気象庁ホームページの配色指針 を参考にしました

<style>
  *{ font-family:sans-serif;}
  table, tr, td, th{ border-collapse:collapse; white-space:nowrap;}
  th,td{ padding:2px 8px; border-style:solid; border-width:1px 0; border-color:#d8d8db;}
  th{ background-color:#f1f1f4;}
  .lv5{ background:#0c000c; color:white;}
  .lv4{ background:#aa00aa; color:white;}
  .lv3{ background:#ff2800; color:white;}
  .lv2{ background:#f2e700; color:black;}
</style>

警報コードと警報名、危険度(配色)の対応表を定義します

const warnInfos = {
  "00":{"long":"解除","lv":0},
  "32":{"long":"暴風雪特別警報","lv":5},
  "33":{"long":"レベル5大雨特別警報","lv":5},
  "34":{"long":"レベル5氾濫特別警報","lv":5},
  // ......中略......
  "29":{"long":"レベル2土砂災害注意報","lv":2}
}

都道府県の選択欄を作るために地域情報を取得します

function getGlobals(){
  fetch("https://www.jma.go.jp/bosai/common/const/area.json")
  .then((response) => response.json())
  .then((response) => {
    areas = response;
    makeOfficeSelect();
  });
}

都道府県選択欄を作成します。その際、単純に{area.json}['offices']を前から読んでいくと、100000(群馬県)が最初になってしまう場合があるため、011000(北海道宗谷地方)から順におおむね北から並ぶよう、地域コードを数値比較してソーティングを行います

function makeOfficeSelect(){
  let officeSelect = "";
  let officeCodes = Object.keys(areas['offices']).sort((a,b)=>{return a-b});
  for( let officeCode of officeCodes){
    let officeName = areas['offices'][officeCode]['name'];
    officeSelect += "<option value='" + officeCode + "'>" + officeName + "</option>"
  }
  document.getElementById("officeSelect").innerHTML = officeSelect;
  get();
}

選択された都道府県の警報・注意報のファイルを取得します

function get(){
  const officeCode = document.getElementById("officeSelect").value;
  fetch("https://www.jma.go.jp/bosai/warning/data/r8/" + officeCode + ".json")
  .then((response) => response.json())
  .then((warns) => display(warns));
}

警報・注意報の一覧表を作成します。{area.json}の該当都道府県(areas['offices'][officeCode])の子要素を順番に読み取り、1次細分区域(class10s)→市町村等をまとめた地域(class15s)→2次細分区域(≒市町村。class20s)の順にループすることで都道府県内の市町村を列挙します。続いて、{officeCode}.json内の電文を順番に読み、地域コードが一致する地域の警報を読み取っていきます

for( let class10Code of areas['offices'][officeCode]['children']){
  for( let class15Code of areas['class10s'][class10Code]['children']){
    for( let class20Code of areas['class15s'][class15Code]['children']){
      const class20Name = areas['class20s'][class20Code]['name'];
      out += "<tr><th>" + class20Name + "</th><td>";
      for( let report of warns){
        for( let class20Item of report['warning']['class20Items']){
          const areaCode = class20Item['areaCode'];
          if( areaCode != class20Code){
            continue;
          }
          for( let kind of class20Item['kinds']){
            const warnCode = kind['code'], warnStatus = kind['status'];
            if( warnStatus=="解除" || warnStatus=="発表警報・注意報はなし"){
              continue;
            }else{
              let warnLevel = warnInfos[warnCode]['lv'], warnName = warnInfos[warnCode]['long'];
              out += "<span class='lv" + warnLevel + "'>" + warnName + "</span> ";
            }
          }
        }
      }
      out += "</td></tr>";
    }
  }
}

statusが「解除」「発表警報・注意報はなし」以外の場合は警報・注意報が発表されているとみなし、危険度(warnLevel)と警報名(warnName)を冒頭で定義した定数から取得し、表に書き加えていきます

表示ページ全体のソースコード

サンプルページ

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>警報</title>
  <style>
    *{ font-family:sans-serif;}
    table, tr, td, th{ border-collapse:collapse; white-space:nowrap;}
    th,td{ padding:2px 8px; border-style:solid; border-width:1px 0; border-color:#d8d8db;}
    th{ background-color:#f1f1f4;}
    .lv5{ background:#0c000c; color:white;}
    .lv4{ background:#aa00aa; color:white;}
    .lv3{ background:#ff2800; color:white;}
    .lv2{ background:#f2e700; color:black;}
  </style>
</head>
<body>
  <h1>警報</h1>
  <div id="menu">
    <select id="officeSelect"></select>
  </div>
  <div id="out"></div>
  <script>
    "use strict";
    const warnInfos = {
      "00":{"long":"解除","lv":0},
      "32":{"long":"暴風雪特別警報","lv":5},
      "33":{"long":"レベル5大雨特別警報","lv":5},
      "34":{"long":"レベル5氾濫特別警報","lv":5},
      "35":{"long":"暴風特別警報","lv":5},
      "36":{"long":"大雪特別警報","lv":5},
      "37":{"long":"波浪特別警報","lv":5},
      "38":{"long":"レベル5高潮特別警報","lv":5},
      "39":{"long":"レベル5土砂災害特別警報","lv":5},
      "43":{"long":"レベル4大雨危険警報","lv":4},
      "44":{"long":"レベル4氾濫危険警報","lv":4},
      "48":{"long":"レベル4高潮危険警報","lv":4},
      "49":{"long":"レベル4土砂災害危険警報","lv":4},
      "02":{"long":"暴風雪警報","lv":3},
      "03":{"long":"レベル3大雨警報","lv":3},
      "04":{"long":"レベル3氾濫警報","lv":3},
      "05":{"long":"暴風警報","lv":3},
      "06":{"long":"大雪警報","lv":3},
      "07":{"long":"波浪警報","lv":3},
      "08":{"long":"レベル3高潮警報","lv":3},
      "09":{"long":"レベル3土砂災害警報","lv":3},
      "10":{"long":"レベル2大雨注意報","lv":2},
      "12":{"long":"大雪注意報","lv":2},
      "13":{"long":"風雪注意報","lv":2},
      "14":{"long":"雷注意報","lv":2},
      "15":{"long":"強風注意報","lv":2},
      "16":{"long":"波浪注意報","lv":2},
      "17":{"long":"融雪注意報","lv":2},
      "18":{"long":"レベル2氾濫注意報","lv":2},
      "19":{"long":"レベル2高潮注意報","lv":2},
      "20":{"long":"濃霧注意報","lv":2},
      "21":{"long":"乾燥注意報","lv":2},
      "22":{"long":"なだれ注意報","lv":2},
      "23":{"long":"低温注意報","lv":2},
      "24":{"long":"霜注意報","lv":2},
      "25":{"long":"着氷注意報","lv":2},
      "26":{"long":"着雪注意報","lv":2},
      "27":{"long":"その他の注意報","lv":2},
      "29":{"long":"レベル2土砂災害注意報","lv":2}
    }
    let areas;

    getGlobals();

    function getGlobals(){
      fetch("https://www.jma.go.jp/bosai/common/const/area.json")
      .then((response) => response.json())
      .then((response) => {
        areas = response;
        makeOfficeSelect();
      });
    }

    function makeOfficeSelect(){
      let officeSelect = "";
      let officeCodes = Object.keys(areas['offices']).sort((a,b)=>{return a-b});
      for( let officeCode of officeCodes){
        let officeName = areas['offices'][officeCode]['name'];
        officeSelect += "<option value='" + officeCode + "'>" + officeName + "</option>"
      }
      document.getElementById("officeSelect").innerHTML = officeSelect;
      get();
    }

    document.getElementById("officeSelect").addEventListener("change",function(e){
      get();
    });

    function get(){
      const officeCode = document.getElementById("officeSelect").value;
      fetch("https://www.jma.go.jp/bosai/warning/data/r8/" + officeCode + ".json")
      .then((response) => response.json())
      .then((warns) => display(warns));
    }

    function display( warns){
      let out = "", officeCode = document.getElementById("officeSelect").value;
      out += "<table>";
      for( let class10Code of areas['offices'][officeCode]['children']){
        for( let class15Code of areas['class10s'][class10Code]['children']){
          for( let class20Code of areas['class15s'][class15Code]['children']){
            const class20Name = areas['class20s'][class20Code]['name'];
            out += "<tr><th>" + class20Name + "</th><td>";
            for( let report of warns){
              for( let class20Item of report['warning']['class20Items']){
                const areaCode = class20Item['areaCode'];
                if( areaCode != class20Code){
                  continue;
                }
                for( let kind of class20Item['kinds']){
                  const warnCode = kind['code'], warnStatus = kind['status'];
                  if( warnStatus=="解除" || warnStatus=="発表警報・注意報はなし"){
                    continue;
                  }else{
                    let warnLevel = warnInfos[warnCode]['lv'], warnName = warnInfos[warnCode]['long'];
                    out += "<span class='lv" + warnLevel + "'>" + warnName + "</span> ";
                  }
                }
              }
            }
            out += "</td></tr>";
          }
        }
      }
      out += "</table>";
      document.getElementById("out").innerHTML = out;
    }
  </script>
</body>
</html>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?