JavaScriptで気象庁から1週間の天気予報を取得してwebサイトに表示する

# はじめに
[気象庁の天気予報](https://www.jma.go.jp/bosai/forecast/)からjsonを取得して天気予報を表示します
外部モジュールやログイン必須のAPIは使いません。

今回は2パターン用意したのでどちらも紹介します。
- タイプ1(横長、テキスト有り) `840x120px`
<p class="codepen" data-height="260" data-default-tab="result" data-slug-hash="abKeBBR" data-user="LookUP-group" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/LookUP-group/pen/abKeBBR">
  天気予報: タイプ1(横長)</a> by LookUP-group (<a href="https://codepen.io/LookUP-group">@LookUP-group</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

- タイプ2(縦長、テキスト無し) `150x280px`
<p class="codepen" data-height="450" data-default-tab="result" data-slug-hash="dyKxONE" data-user="LookUP-group" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/LookUP-group/pen/dyKxONE">
  Untitled</a> by LookUP-group (<a href="https://codepen.io/LookUP-group">@LookUP-group</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 注意事項
下記ツイートでも書かれている通り正式なAPIではなく、いつ動作停止するかわからないので**使用は自己責任でお願いします**。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">一番伸びてるのはこれかしら。仕様の継続性や運用状況のお知らせを気象庁はお約束していないという意味で、APIではないと申し上げざるを得ないのですが、一方で政府標準利用規約に準拠してご利用いただけます。 <a href="https://t.co/QLuhI4DNDv">https://t.co/QLuhI4DNDv</a></p>&mdash; TOYODA Eizi (@e_toyoda) <a href="https://twitter.com/e_toyoda/status/1364504338572410885?ref_src=twsrc%5Etfw">February 24, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# ソースコード

※全て同じディレクトリに置くか各自パスを調整してください。

<details><summary>タイプ1(横長)</summary><div>

```html:weather.html
<link rel="stylesheet" href="./weather.css">
<div id="location"><a href="https://www.jma.go.jp/bosai/forecast/" target="_blank">気象庁のデータを元に作成</a></div>
<div class="weatherForecast">
  <div class="weather">
    <div class="date">--/--(-)</div>
    <img class="weatherImg">
    <div class="weatherTelop">--</div>
    <div><span class="tempMin">-℃</span>/<span class="tempMax">-℃</span></div>
  </div>
</div>
<script>
  for (let i = 0; i < 6; i++) {
    const el = document.querySelector('.weather').cloneNode(true);
    document.querySelector('.weatherForecast').appendChild(el);
  }
</script>
<script src="./weather.js"></script>

```

```css:weather.css
.weatherForecast {
  width: 840px;
  height: 120px;
  display: flex;
  text-align: center;
  border: 1px solid #000;
}

.weather {
  width: calc(100% / 7);
  height: 100%;
  box-sizing: border-box;
  border: 1px solid #666;
}

.weather > div {
  height: 20%;
  font-size: 14px;
}

.weatherImg {
  height: 42%;
}

.tempMin {
  color: blue;
}

.tempMax {
  color: red;
}
```

```js:weather.js
const weatherCode = {
  100: ["100.svg", "500.svg", "晴れ"],
  101: ["101.svg", "501.svg", "晴れ時々曇り"],
  102: ["102.svg", "502.svg", "晴れ一時雨"],
  103: ["102.svg", "502.svg", "晴れ時々雨"],
  104: ["104.svg", "504.svg", "晴れ一時雪"],
  105: ["104.svg", "504.svg", "晴れ時々雪"],
  106: ["102.svg", "502.svg", "晴れ一時雨か雪"],
  107: ["102.svg", "502.svg", "晴れ時々雨か雪"],
  108: ["102.svg", "502.svg", "晴れ一時雨か雷雨"],
  110: ["110.svg", "510.svg", "晴れ後時々曇り"],
  111: ["110.svg", "510.svg", "晴れ後曇り"],
  112: ["112.svg", "512.svg", "晴れ後一時雨"],
  113: ["112.svg", "512.svg", "晴れ後時々雨"],
  114: ["112.svg", "512.svg", "晴れ後雨"],
  115: ["115.svg", "515.svg", "晴れ後一時雪"],
  116: ["115.svg", "515.svg", "晴れ後時々雪"],
  117: ["115.svg", "515.svg", "晴れ後雪"],
  118: ["112.svg", "512.svg", "晴れ後雨か雪"],
  119: ["112.svg", "512.svg", "晴れ後雨か雷雨"],
  120: ["102.svg", "502.svg", "晴れ朝夕一時雨"],
  121: ["102.svg", "502.svg", "晴れ朝の内一時雨"],
  122: ["112.svg", "512.svg", "晴れ夕方一時雨"],
  123: ["100.svg", "500.svg", "晴れ山沿い雷雨"],
  124: ["100.svg", "500.svg", "晴れ山沿い雪"],
  125: ["112.svg", "512.svg", "晴れ午後は雷雨"],
  126: ["112.svg", "512.svg", "晴れ昼頃から雨"],
  127: ["112.svg", "512.svg", "晴れ夕方から雨"],
  128: ["112.svg", "512.svg", "晴れ夜は雨"],
  130: ["100.svg", "500.svg", "朝の内霧後晴れ"],
  131: ["100.svg", "500.svg", "晴れ明け方霧"],
  132: ["101.svg", "501.svg", "晴れ朝夕曇り"],
  140: ["102.svg", "502.svg", "晴れ時々雨と雷"],
  160: ["104.svg", "504.svg", "晴れ一時雪か雨"],
  170: ["104.svg", "504.svg", "晴れ時々雪か雨"],
  181: ["115.svg", "515.svg", "晴れ後雪か雨"],
  200: ["200.svg", "200.svg", "曇り"],
  201: ["201.svg", "601.svg", "曇り時々晴れ"],
  202: ["202.svg", "202.svg", "曇り一時雨"],
  203: ["202.svg", "202.svg", "曇り時々雨"],
  204: ["204.svg", "204.svg", "曇り一時雪"],
  205: ["204.svg", "204.svg", "曇り時々雪"],
  206: ["202.svg", "202.svg", "曇り一時雨か雪"],
  207: ["202.svg", "202.svg", "曇り時々雨か雪"],
  208: ["202.svg", "202.svg", "曇り一時雨か雷雨"],
  209: ["200.svg", "200.svg", "霧"],
  210: ["210.svg", "610.svg", "曇り後時々晴れ"],
  211: ["210.svg", "610.svg", "曇り後晴れ"],
  212: ["212.svg", "212.svg", "曇り後一時雨"],
  213: ["212.svg", "212.svg", "曇り後時々雨"],
  214: ["212.svg", "212.svg", "曇り後雨"],
  215: ["215.svg", "215.svg", "曇り後一時雪"],
  216: ["215.svg", "215.svg", "曇り後時々雪"],
  217: ["215.svg", "215.svg", "曇り後雪"],
  218: ["212.svg", "212.svg", "曇り後雨か雪"],
  219: ["212.svg", "212.svg", "曇り後雨か雷雨"],
  220: ["202.svg", "202.svg", "曇り朝夕一時雨"],
  221: ["202.svg", "202.svg", "曇り朝の内一時雨"],
  222: ["212.svg", "212.svg", "曇り夕方一時雨"],
  223: ["201.svg", "601.svg", "曇り日中時々晴れ"],
  224: ["212.svg", "212.svg", "曇り昼頃から雨"],
  225: ["212.svg", "212.svg", "曇り夕方から雨"],
  226: ["212.svg", "212.svg", "曇り夜は雨"],
  228: ["215.svg", "215.svg", "曇り昼頃から雪"],
  229: ["215.svg", "215.svg", "曇り夕方から雪"],
  230: ["215.svg", "215.svg", "曇り夜は雪"],
  231: ["200.svg", "200.svg", "曇り海岸霧か霧雨"],
  240: ["202.svg", "202.svg", "曇り時々雨と雷"],
  250: ["204.svg", "204.svg", "曇り時々雪と雷"],
  260: ["204.svg", "204.svg", "曇り一時雪か雨"],
  270: ["204.svg", "204.svg", "曇り時々雪か雨"],
  281: ["215.svg", "215.svg", "曇り後雪か雨"],
  300: ["300.svg", "300.svg", "雨"],
  301: ["301.svg", "701.svg", "雨時々晴れ"],
  302: ["302.svg", "302.svg", "雨時々止む"],
  303: ["303.svg", "303.svg", "雨時々雪"],
  304: ["300.svg", "300.svg", "雨か雪"],
  306: ["300.svg", "300.svg", "大雨"],
  308: ["308.svg", "308.svg", "雨で暴風を伴う"],
  309: ["303.svg", "303.svg", "雨一時雪"],
  311: ["311.svg", "711.svg", "雨後晴れ"],
  313: ["313.svg", "313.svg", "雨後曇り"],
  314: ["314.svg", "314.svg", "雨後時々雪"],
  315: ["314.svg", "314.svg", "雨後雪"],
  316: ["311.svg", "711.svg", "雨か雪後晴れ"],
  317: ["313.svg", "313.svg", "雨か雪後曇り"],
  320: ["311.svg", "711.svg", "朝の内雨後晴れ"],
  321: ["313.svg", "313.svg", "朝の内雨後曇り"],
  322: ["303.svg", "303.svg", "雨朝晩一時雪"],
  323: ["311.svg", "711.svg", "雨昼頃から晴れ"],
  324: ["311.svg", "711.svg", "雨夕方から晴れ"],
  325: ["311.svg", "711.svg", "雨夜は晴れ"],
  326: ["314.svg", "314.svg", "雨夕方から雪"],
  327: ["314.svg", "314.svg", "雨夜は雪"],
  328: ["300.svg", "300.svg", "雨一時強く降る"],
  329: ["300.svg", "300.svg", "雨一時みぞれ"],
  340: ["400.svg", "400.svg", "雪か雨"],
  350: ["300.svg", "300.svg", "雨で雷を伴う"],
  361: ["411.svg", "811.svg", "雪か雨後晴れ"],
  371: ["413.svg", "413.svg", "雪か雨後曇り"],
  400: ["400.svg", "400.svg", "雪"],
  401: ["401.svg", "801.svg", "雪時々晴れ"],
  402: ["402.svg", "402.svg", "雪時々止む"],
  403: ["403.svg", "403.svg", "雪時々雨"],
  405: ["400.svg", "400.svg", "大雪"],
  406: ["406.svg", "406.svg", "風雪強い"],
  407: ["406.svg", "406.svg", "暴風雪"],
  409: ["403.svg", "403.svg", "雪一時雨"],
  411: ["411.svg", "811.svg", "雪後晴れ"],
  413: ["413.svg", "413.svg", "雪後曇り"],
  414: ["414.svg", "414.svg", "雪後雨"],
  420: ["411.svg", "811.svg", "朝の内雪後晴れ"],
  421: ["413.svg", "413.svg", "朝の内雪後曇り"],
  422: ["414.svg", "414.svg", "雪昼頃から雨"],
  423: ["414.svg", "414.svg", "雪夕方から雨"],
  425: ["400.svg", "400.svg", "雪一時強く降る"],
  426: ["400.svg", "400.svg", "雪後みぞれ"],
  427: ["400.svg", "400.svg", "雪一時みぞれ"],
  450: ["400.svg", "400.svg", "雪で雷を伴う"],
};

// ここのXXXXXX.jsonを変更する
const url = "https://www.jma.go.jp/bosai/forecast/data/forecast/XXXXXX.json";

const dayList = ["日", "月", "火", "水", "木", "金", "土"];

const timeDefinesList = new Array();
const weatherCodeList = new Array();
const tempsMinList = new Array();
const tempsMaxList = new Array();

fetch(url)
  .then(function (response) {
    return response.json();
  })
  .then(function (weather) {
    document
      .getElementById("location")
      .prepend(
        `${weather[1].publishingOffice}: ${weather[1].timeSeries[0].areas[0].area.name} `
      );
    const isTodaysData = weather[0].timeSeries[2].timeDefines.length === 4;
    const weatherCodes = weather[0].timeSeries[0].areas[0].weatherCodes;
    const timeDefines = weather[0].timeSeries[0].timeDefines;
    const temps = weather[0].timeSeries[2].areas[0].temps;
    weatherCodeList.push(weatherCodes[0], weatherCodes[1]);
    timeDefinesList.push(timeDefines[0], timeDefines[1]);
    if (isTodaysData) {
      tempsMinList.push(temps[0] === temps[1] ? "--" : temps[0], temps[2]);
      tempsMaxList.push(temps[1], temps[3]);
    } else {
      tempsMinList.push("--", temps[0]);
      tempsMaxList.push("--", temps[1]);
    }

    const startCount =
      weather[1].timeSeries[0].timeDefines.indexOf(timeDefines[1]) + 1;
    for (let i = startCount; i < startCount + 5; i++) {
      weatherCodeList.push(weather[1].timeSeries[0].areas[0].weatherCodes[i]);
      timeDefinesList.push(weather[1].timeSeries[0].timeDefines[i]);
      tempsMinList.push(weather[1].timeSeries[1].areas[0].tempsMin[i]);
      tempsMaxList.push(weather[1].timeSeries[1].areas[0].tempsMax[i]);
    }

    const date = document.getElementsByClassName("date");
    const weatherImg = document.getElementsByClassName("weatherImg");
    const weatherTelop = document.getElementsByClassName("weatherTelop");
    const tempMin = document.getElementsByClassName("tempMin");
    const tempMax = document.getElementsByClassName("tempMax");

    weatherCodeList.forEach(function (el, i) {
      let dt = new Date(timeDefinesList[i]);
      let weekdayCount = dt.getDay();
      if (weekdayCount === 0) date[i].style.color = "red";
      if (weekdayCount === 6) date[i].style.color = "blue";
      var m = ("00" + (dt.getMonth() + 1)).slice(-2);
      var d = ("00" + dt.getDate()).slice(-2);
      date[i].textContent = `${m}/${d}(${dayList[weekdayCount]})`;
      var isNight = Number(i === 0 && !isTodaysData)
      weatherImg[i].src = "https://www.jma.go.jp/bosai/forecast/img/" + weatherCode[el][isNight];
      weatherTelop[i].textContent = weatherCode[el][2];
      tempMin[i].textContent = tempsMinList[i] + "℃";
      tempMax[i].textContent = tempsMaxList[i] + "℃";
    });
  });

```
</div></details>

<details><summary>タイプ2(縦長)</summary><div>

```html:weather.html
<link rel="stylesheet" href="./weather.css">
<div id="location"></div>
<a href="https://www.jma.go.jp/bosai/forecast/" target="_blank">気象庁のデータを元に作成</a>
<div class="weatherForecast">
  <div class="weather">
    <div class="date">(-)</div>
    <img class="weatherImg">
    <div class="temp"><span class="tempMin">--</span>/<span class="tempMax">--</span></div>
  </div>
</div>
<script>
  for (let i = 0; i < 6; i++) {
    const el = document.querySelector('.weather').cloneNode(true);
    document.querySelector('.weatherForecast').appendChild(el);
  }
</script>
<script src="./weather.js"></script>

```

```css:weather.css
.weatherForecast {
  width: 150px;
  height: 280px;
  display: flex;
  flex-direction: column;
  border: 1px solid #000;
}

.weather {
  width: 100%;
  height: calc(100% / 7);
  display: flex;
  align-items: center;
  box-sizing: border-box;
  border: 1px solid #666;
}

.date {
  width: 25%;
}

.weatherImg {
  width: 40%;
}

.temp {
  width: 35%;
  text-align: center;
}

.tempMin {
  color: blue;
}

.tempMax {
  color: red;
}
```

```js:weather.js
const weatherCode = {
  100: ['100.svg', '500.svg'],
  101: ['101.svg', '501.svg'],
  102: ['102.svg', '502.svg'],
  103: ['102.svg', '502.svg'],
  104: ['104.svg', '504.svg'],
  105: ['104.svg', '504.svg'],
  106: ['102.svg', '502.svg'],
  107: ['102.svg', '502.svg'],
  108: ['102.svg', '502.svg'],
  110: ['110.svg', '510.svg'],
  111: ['110.svg', '510.svg'],
  112: ['112.svg', '512.svg'],
  113: ['112.svg', '512.svg'],
  114: ['112.svg', '512.svg'],
  115: ['115.svg', '515.svg'],
  116: ['115.svg', '515.svg'],
  117: ['115.svg', '515.svg'],
  118: ['112.svg', '512.svg'],
  119: ['112.svg', '512.svg'],
  120: ['102.svg', '502.svg'],
  121: ['102.svg', '502.svg'],
  122: ['112.svg', '512.svg'],
  123: ['100.svg', '500.svg'],
  124: ['100.svg', '500.svg'],
  125: ['112.svg', '512.svg'],
  126: ['112.svg', '512.svg'],
  127: ['112.svg', '512.svg'],
  128: ['112.svg', '512.svg'],
  130: ['100.svg', '500.svg'],
  131: ['100.svg', '500.svg'],
  132: ['101.svg', '501.svg'],
  140: ['102.svg', '502.svg'],
  160: ['104.svg', '504.svg'],
  170: ['104.svg', '504.svg'],
  181: ['115.svg', '515.svg'],
  200: ['200.svg', '200.svg'],
  201: ['201.svg', '601.svg'],
  202: ['202.svg', '202.svg'],
  203: ['202.svg', '202.svg'],
  204: ['204.svg', '204.svg'],
  205: ['204.svg', '204.svg'],
  206: ['202.svg', '202.svg'],
  207: ['202.svg', '202.svg'],
  208: ['202.svg', '202.svg'],
  209: ['200.svg', '200.svg'],
  210: ['210.svg', '610.svg'],
  211: ['210.svg', '610.svg'],
  212: ['212.svg', '212.svg'],
  213: ['212.svg', '212.svg'],
  214: ['212.svg', '212.svg'],
  215: ['215.svg', '215.svg'],
  216: ['215.svg', '215.svg'],
  217: ['215.svg', '215.svg'],
  218: ['212.svg', '212.svg'],
  219: ['212.svg', '212.svg'],
  220: ['202.svg', '202.svg'],
  221: ['202.svg', '202.svg'],
  222: ['212.svg', '212.svg'],
  223: ['201.svg', '601.svg'],
  224: ['212.svg', '212.svg'],
  225: ['212.svg', '212.svg'],
  226: ['212.svg', '212.svg'],
  228: ['215.svg', '215.svg'],
  229: ['215.svg', '215.svg'],
  230: ['215.svg', '215.svg'],
  231: ['200.svg', '200.svg'],
  240: ['202.svg', '202.svg'],
  250: ['204.svg', '204.svg'],
  260: ['204.svg', '204.svg'],
  270: ['204.svg', '204.svg'],
  281: ['215.svg', '215.svg'],
  300: ['300.svg', '300.svg'],
  301: ['301.svg', '701.svg'],
  302: ['302.svg', '302.svg'],
  303: ['303.svg', '303.svg'],
  304: ['300.svg', '300.svg'],
  306: ['300.svg', '300.svg'],
  308: ['308.svg', '308.svg'],
  309: ['303.svg', '303.svg'],
  311: ['311.svg', '711.svg'],
  313: ['313.svg', '313.svg'],
  314: ['314.svg', '314.svg'],
  315: ['314.svg', '314.svg'],
  316: ['311.svg', '711.svg'],
  317: ['313.svg', '313.svg'],
  320: ['311.svg', '711.svg'],
  321: ['313.svg', '313.svg'],
  322: ['303.svg', '303.svg'],
  323: ['311.svg', '711.svg'],
  324: ['311.svg', '711.svg'],
  325: ['311.svg', '711.svg'],
  326: ['314.svg', '314.svg'],
  327: ['314.svg', '314.svg'],
  328: ['300.svg', '300.svg'],
  329: ['300.svg', '300.svg'],
  340: ['400.svg', '400.svg'],
  350: ['300.svg', '300.svg'],
  361: ['411.svg', '811.svg'],
  371: ['413.svg', '413.svg'],
  400: ['400.svg', '400.svg'],
  401: ['401.svg', '801.svg'],
  402: ['402.svg', '402.svg'],
  403: ['403.svg', '403.svg'],
  405: ['400.svg', '400.svg'],
  406: ['406.svg', '406.svg'],
  407: ['406.svg', '406.svg'],
  409: ['403.svg', '403.svg'],
  411: ['411.svg', '811.svg'],
  413: ['413.svg', '413.svg'],
  414: ['414.svg', '414.svg'],
  420: ['411.svg', '811.svg'],
  421: ['413.svg', '413.svg'],
  422: ['414.svg', '414.svg'],
  423: ['414.svg', '414.svg'],
  425: ['400.svg', '400.svg'],
  426: ['400.svg', '400.svg'],
  427: ['400.svg', '400.svg'],
  450: ['400.svg', '400.svg']
}

// ここのXXXXXX.jsonを変更する
const url = "https://www.jma.go.jp/bosai/forecast/data/forecast/XXXXXX.json";

const dayList = ["日", "月", "火", "水", "木", "金", "土"];
const weatherCodeList = new Array();
const tempsMinList = new Array();
const tempsMaxList = new Array();

fetch(url)
	.then(function(response) {
		return response.json();
	})
	.then(function(weather) {
    document
    .getElementById("location").textContent = `${weather[1].timeSeries[0].areas[0].area.name}`;
    const isTodaysData = weather[0].timeSeries[2].timeDefines.length === 4;
    const weatherCodes = weather[0].timeSeries[0].areas[0].weatherCodes;
    const timeDefines = weather[0].timeSeries[0].timeDefines;
    const temps = weather[0].timeSeries[2].areas[0].temps;
    weatherCodeList.push(weatherCodes[0], weatherCodes[1]);
    if (isTodaysData) {
      tempsMinList.push(temps[0] === temps[1] ? "--" : temps[0], temps[2]);
      tempsMaxList.push(temps[1], temps[3]);
    } else {
      tempsMinList.push("--", temps[0]);
      tempsMaxList.push("--", temps[1]);
    }

    const startCount = weather[1].timeSeries[0].timeDefines.indexOf(timeDefines[1])+1;
    for (let i=startCount; i < startCount+5; i++) {
      weatherCodeList.push(weather[1].timeSeries[0].areas[0].weatherCodes[i]);
      tempsMinList.push(weather[1].timeSeries[1].areas[0].tempsMin[i]);
      tempsMaxList.push(weather[1].timeSeries[1].areas[0].tempsMax[i]);
    }

    const date = document.getElementsByClassName("date");
    const weatherImg = document.getElementsByClassName("weatherImg");
    const tempMin = document.getElementsByClassName("tempMin");
    const tempMax = document.getElementsByClassName("tempMax");
    const todayWeekdayCount = new Date(timeDefines[0]).getDay();

    weatherCodeList.forEach(function(el, i) {
      if (i === 0) {
        date[i].textContent = "今日"
      } else {
        const weekdayCount = (todayWeekdayCount + i) % 7;
        if (weekdayCount === 0) { date[i].style.color = "red" };
        if (weekdayCount === 6) { date[i].style.color = "blue" };
        date[i].textContent = "(" + dayList[weekdayCount] + ")";
      }
      var isNight = Number(i === 0 && !isTodaysData)
      weatherImg[i].src = "https://www.jma.go.jp/bosai/forecast/img/" + weatherCode[el][isNight];
      tempMin[i].textContent = tempsMinList[i];
      tempMax[i].textContent = tempsMaxList[i];
    });
  });
```

</div></details>


# 解説
- `weatherCode`: 天気コードを天気予報とそれに紐付いたsvgに変換するためのリストです。
- `https://www.jma.go.jp/bosai/forecast/data/forecast/XXXXXX.json`: "X"の部分を変更することで取得する地方を変更することができます。(コードは下記参照)
- 取得する時間によっては気温が取得できない場合があるのでその場合は`--`で埋めています。

# 地方コード一覧
| 気象台 | 地方名 | コード |
|:-|:-|:-|
|稚内地方気象台|宗谷地方|011000|
|旭川地方気象台|上川・留萌地方|012000|
|網走地方気象台|網走・北見・紋別地方|013000|
|釧路地方気象台|釧路・根室・十勝地方|014100|
|室蘭地方気象台|胆振・日高地方|015000|
|札幌管区気象台|石狩・空知・後志地方|016000|
|函館地方気象台|渡島・檜山地方|017000|
|青森地方気象台|津軽・下北|020000|
|盛岡地方気象台|内陸|030000|
|仙台管区気象台|東部|040000|
|秋田地方気象台|秋田県|050000|
|山形地方気象台|山形県|060000|
|福島地方気象台|中通り・浜通り|070000|
|水戸地方気象台|茨城県|080000|
|宇都宮地方気象台|栃木県|090000|
|前橋地方気象台|南部|100000|
|熊谷地方気象台|埼玉県|110000|
|銚子地方気象台|千葉県|120000|
|気象庁|東京地方|130000|
|横浜地方気象台|神奈川県|140000|
|甲府地方気象台|山梨県|190000|
|長野地方気象台|北部|200000|
|岐阜地方気象台|美濃地方|210000|
|静岡地方気象台|静岡県|220000|
|名古屋地方気象台|愛知県|230000|
|津地方気象台|三重県|240000|
|新潟地方気象台|新潟県|150000|
|富山地方気象台|富山県|160000|
|金沢地方気象台|石川県|170000|
|福井地方気象台|福井県|180000|
|彦根地方気象台|南部|250000|
|京都地方気象台|南部|260000|
|大阪管区気象台|大阪府|270000|
|神戸地方気象台|南部|280000|
|奈良地方気象台|奈良県|290000|
|和歌山地方気象台|和歌山県|300000|
|鳥取地方気象台|鳥取県|310000|
|松江地方気象台|島根県|320000|
|岡山地方気象台|南部|330000|
|広島地方気象台|南部|340000|
|徳島地方気象台|徳島県|360000|
|高松地方気象台|香川県|370000|
|松山地方気象台|愛媛県|380000|
|高知地方気象台|高知県|390000|
|下関地方気象台|山口県|350000|
|福岡管区気象台|福岡県|400000|
|佐賀地方気象台|佐賀県|410000|
|長崎地方気象台|南部・北部・五島|420000|
|熊本地方気象台|熊本県|430000|
|大分地方気象台|大分県|440000|
|宮崎地方気象台|宮崎県|450000|
|鹿児島地方気象台|鹿児島県（奄美地方除く）|460100|
|沖縄気象台|沖縄本島地方|471000|
|南大東島地方気象台|大東島地方|472000|
|宮古島地方気象台|宮古島地方|473000|
|石垣島地方気象台|八重山地方|474000|

# 最後に
ここで取得できるjsonには降水確率を取得したり、信頼度を取得したりもできるので各自カスタマイズして使ってみてください。

# 参考サイト
[気象庁の天気予報JSONファイルをWebAPI的に利用したサンプルアプリ](https://anko.education/apps/weather_api)
[気象庁公式の天気予報の情報（JSON）を curl・Node.js で取得し Node.js での処理を試す](https://qiita.com/youtoy/items/932bc48b03ced5a45c71)
[気象庁JSONデータ](https://qiita.com/michan06/items/48503631dd30275288f7)