2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

☀️Flaskで作る!気象庁オープンデータAPIを使った天気・気温カレンダーWebアプリ

Posted at

はじめに

こんにちは!今回は気象庁のオープンデータAPIを活用して、東京・大阪・名古屋の週間天気を表示するカレンダー形式のWebアプリをFlaskで作ってみました。

こんな感じで表示されます👇

スクリーンショット 2025-08-09 0.38.13.png


🧭 この記事でできること

  • 気象庁APIを使って最新の天気・気温を取得
  • FlaskでシンプルなWebアプリを構築
  • HTML+CSSでカレンダー形式に整形
  • 地域選択機能付き(東京/大阪/名古屋)

🌐 気象庁オープンデータAPIとは?

気象庁のオープンデータ提供サイトでは、誰でも天気予報のJSONデータを取得できます。

✅ 使うエンドポイント

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

✅ 主な地域コード

地域 コード
東京 130000
大阪 270000
名古屋 230000

このデータから、

  • 日付(timeDefines)
  • 天気(weathers)
  • 気温(temps)
    を抽出して使います。

🛠️ 開発環境の準備

pip install flask requests

📄 app.py(Flaskアプリ)

from flask import Flask, render_template, request
import requests
from datetime import datetime

app = Flask(__name__)

areas = {
    '東京': '130000',
    '大阪': '270000',
    '名古屋': '230000'
}

@app.route('/', methods=['GET', 'POST'])
def index():
    today = datetime.now()
    calendar = []
    error = None
    selected_area = request.form.get('area', '東京')
    forecast_url = f"https://www.jma.go.jp/bosai/forecast/data/forecast/{areas[selected_area]}.json"

    try:
        res = requests.get(forecast_url)
        data = res.json()
        timeseries = data[0]["timeSeries"]
        weather_dates = timeseries[0]["timeDefines"]
        weathers = timeseries[0]["areas"][0]["weathers"]
        temps = timeseries[2]["areas"][0]["temps"]
        days = ['','','','','','','']

        for i in range(min(7, len(weather_dates))):
            date = weather_dates[i][:10]
            weather = weathers[i]
            temp = temps[i] if i < len(temps) else "-"
            dt = datetime.strptime(date, '%Y-%m-%d')
            weekday = days[(dt.weekday() + 1) % 7]

            # 天気に応じたアイコン
            weather_icon = ''
            if '' in weather:
                weather_icon = '☀️'
            elif '' in weather:
                weather_icon = ''
            elif '' in weather:
                weather_icon = '🌧️'
            elif '' in weather:
                weather_icon = '❄️'
            else:
                weather_icon = '🌈'

            calendar.append({
                'date': date,
                'weekday': weekday,
                'weather': weather,
                'weather_icon': weather_icon,
                'temp': temp
            })
    except Exception as e:
        error = f"API取得エラー: {e}"

    return render_template('calendar.html',
                           calendar=calendar,
                           error=error,
                           today=today.strftime('%Y-%m-%d'),
                           areas=areas,
                           selected_area=selected_area)

if __name__ == '__main__':
    app.run(debug=True)

app.py のポイント解説

セクション 内容
areas 地域名とAPI用コードを定義
requests.get() 天気予報JSONを取得
data[0]["timeSeries"] 天気や気温の情報が入っている
calendar.append(...) 日付・天気・気温を1日ずつまとめる
weather_icon 天気に応じたアイコンを表示
render_template() HTMLテンプレートにデータを渡す

🖼️ templates/calendar.html

<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>天気・気温カレンダー</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="{{ url_for('static', filename='calendar.css') }}">
  </head>
  <body>
    <div class="container">
      <h1>天気・気温カレンダー({{ selected_area }})</h1>
      {% if error %}
        <div class="result"><p style="color:red;">{{ error }}</p></div>
      {% endif %}
      <form method="post" style="text-align:center; margin-bottom:1em;">
        <label for="area">地域:</label>
        <select name="area" id="area">
          {% for name, code in areas.items() %}
            <option value="{{ name }}" {% if name == selected_area %}selected{% endif %}>{{ name }}</option>
          {% endfor %}
        </select>
        <button type="submit">表示</button>
      </form>
      <table>
        <tr><th>日付・曜日</th><th>天気</th><th>気温(℃)</th></tr>
        {% for item in calendar %}
        <tr {% if item.date == today %}class="today"{% endif %}>
          <td>{{ item.date }}({{ item.weekday }})</td>
          <td>{{ item.weather_icon }} {{ item.weather }}</td>
          <td>{{ item.temp }}</td>
        </tr>
        {% endfor %}
      </table>
    </div>
  </body>
</html>

🎨 static/calendar.css

body {
  font-family: 'Roboto', sans-serif;
  background: linear-gradient(120deg, #fbc2eb 0%, #a6c1ee 100%);
  margin: 0;
  min-height: 100vh;
}
.container {
  max-width: 500px;
  margin: 3em auto;
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 4px 24px rgba(0,0,0,0.12);
  padding: 2em 2.5em;
}
h1 {
  text-align: center;
  color: #7b4397;
  margin-bottom: 1.5em;
}
table {
  width: 100%;
  border-collapse: collapse;
  background: #fafafa;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
th, td {
  border-bottom: 1px solid #eee;
  padding: 0.7em 0.5em;
  text-align: center;
}
th {
  background: #7b4397;
  color: #fff;
}
tr.today td {
  background: #fbc2eb;
  font-weight: bold;
}
.result p {
  background: #ffeaea;
  color: #d32f2f;
  border-radius: 8px;
  padding: 0.7em;
  display: inline-block;
  box-shadow: 0 2px 8px rgba(211,47,47,0.12);
}

🚀 アプリ起動方法

python app.py

ブラウザで http://127.0.0.1:5000/ にアクセスすると、天気・気温カレンダーが表示されます。


🌱 応用アイデア

  • 地図クリックで地域を選べるUI
  • 降水確率・風速などの追加表示
  • 天気アイコンを画像に変更
  • モバイル対応のレイアウト強化

📚 参考リンク


🙌 まとめ

Flask × 気象庁API を使うことで、初心者でもAPI連携Webアプリを簡単に作ることができます。

この記事が役に立ったら、**「いいね」や「ストック」**よろしくお願いします!質問・改善案もコメントでぜひ!

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?