この記事は、防災アプリ開発 Advent Calendar 2025 の25日目に投稿しているものです。
はじめに
気象庁が発表する気象警報・注意報は、2026年5月下旬(予定)に大きく変わり、新たな防災気象情報が提供されることになります。
防災アプリ開発 Advent Calendar 2025 でも新たな防災気象情報に関する記事がありましたが、警報・注意報に向き合う時間が増えると「大雨警報と大雪警報って同時に出るんだっけ?」という疑問が皆さん湧いてくると思います。そうですよね。
調べましょう。
インターネットを頼る
(以下引用)
天気予報のルールを決めた「気象官署予報業務取扱便覧」によると、注意報や警報は、以下の通りのルールに従って発表しています。
あるそうです。
いかがでしたか?
本当?
上記を信じるのであれば、例えば大雨注意報と風雪注意報は同時に出ないはずです。
実際の発表事例を1つ見て見ましょう。
秋田県気象警報・注意報【気象特別警報・警報・注意報】 | 気象庁防災情報XMLデータベース

発表されてしまっています。残念。
ローラー作戦
もう何も信じられません。
過去の気象庁防災情報XMLを総ざらいして、実績で同時に出たことがあるかを見ていくことにしましょう。
データ
2020年6月1日から2025年12月25日までに発表された、ほぼ全ての気象警報・注意報のXML電文を対象とします。
条件
同一の二次細分区域について、以下の種別に該当する警報・注意報が同時に2つ以上の組み合わせで発表されている場合を該当ありとします。
| 種別 | 警報・注意報 |
|---|---|
| 大雨 | 大雨特別警報、大雨警報、大雨注意報 |
| 大雪 | 大雪特別警報、大雪警報、大雪注意報 |
| 風 | 暴風特別警報、暴風警報、強風注意報 |
| 風雪 | 暴風雪特別警報、暴風雪警報、風雪注意報 |
ただし、「大雨」と「風」の組み合わせ、「大雪」と「風雪」の組み合わせは一般に存在するため除外します。
つまり、以下の組み合わせを探索します。
| # | 組み合わせ |
|---|---|
| 1 | 「大雨」と「大雪」 |
| 2 | 「大雨」と「風雪」 |
| 3 | 「大雪」と「風」 |
| 4 | 「風」と「風雪」 |
コード
気象警報・注意報のXML電文が *_VPWW53.xml として存在する前提で、以下のスクリプトを回します。
なおスクリプトはバイブコーディングによるものです。
import sys
import io
from pathlib import Path
import xml.etree.ElementTree as ET
WARNING_TYPE = "気象警報・注意報(市町村等)"
RAIN = {"大雨特別警報", "大雨警報", "大雨注意報"}
SNOW = {"大雪特別警報", "大雪警報", "大雪注意報"}
WIND = {"暴風特別警報", "暴風警報", "強風注意報"}
BLIZZARD = {"暴風雪特別警報", "暴風雪警報", "風雪注意報"}
RAIN_B = [s.encode("utf-8") for s in RAIN]
SNOW_B = [s.encode("utf-8") for s in SNOW]
WIND_B = [s.encode("utf-8") for s in WIND]
BLIZ_B = [s.encode("utf-8") for s in BLIZZARD]
EXCLUDE_B = ["試験".encode("utf-8"), "訓練".encode("utf-8")]
def strip_ns(tag: str) -> str:
return tag.split("}", 1)[1] if "}" in tag else tag
def iter_files(root: Path):
yield from root.rglob("*_VPWW53.xml")
def is_candidate(data: bytes) -> bool:
if any(w in data for w in EXCLUDE_B):
return False
if any(k in data for k in RAIN_B) and any(k in data for k in SNOW_B):
return True
if any(k in data for k in WIND_B) and any(k in data for k in BLIZ_B):
return True
return False
def find_hits(path: Path, data: bytes):
out = []
in_target_warning = False
area_map = None
cur_muni = None
cur_flags = None
try:
for ev, elem in ET.iterparse(io.BytesIO(data), events=("start", "end")):
tag = strip_ns(elem.tag)
if ev == "start":
if tag == "Warning":
in_target_warning = ((elem.attrib.get("type") or "").strip() == WARNING_TYPE)
if in_target_warning:
area_map = {}
elif in_target_warning and tag == "Item":
cur_muni = None
cur_flags = {"rain": set(), "snow": set(), "wind": set(), "bliz": set()}
else:
if in_target_warning and tag == "Area":
for ch in elem:
if strip_ns(ch.tag) == "Name":
cur_muni = (ch.text or "").strip() or None
break
elif in_target_warning and tag == "Kind":
name = status = None
for ch in elem:
t = strip_ns(ch.tag)
if t == "Name":
name = (ch.text or "").strip() or None
elif t == "Status":
status = (ch.text or "").strip() or None
if name and status != "解除":
if name in RAIN: cur_flags["rain"].add(name)
if name in SNOW: cur_flags["snow"].add(name)
if name in WIND: cur_flags["wind"].add(name)
if name in BLIZZARD: cur_flags["bliz"].add(name)
elif in_target_warning and tag == "Item":
muni = cur_muni or "(市区町村不明)"
f = area_map.setdefault(muni, {"rain": set(), "snow": set(), "wind": set(), "bliz": set()})
f["rain"].update(cur_flags["rain"])
f["snow"].update(cur_flags["snow"])
f["wind"].update(cur_flags["wind"])
f["bliz"].update(cur_flags["bliz"])
elem.clear()
elif tag == "Warning":
if in_target_warning and area_map is not None:
for muni, f in area_map.items():
combos = []
if f["rain"] and f["snow"]:
combos.append("/".join(sorted(f["rain"])) + " + " + "/".join(sorted(f["snow"])))
if f["wind"] and f["bliz"]:
combos.append("/".join(sorted(f["wind"])) + " + " + "/".join(sorted(f["bliz"])))
if combos:
out.append((str(path), muni, " | ".join(combos)))
in_target_warning = False
area_map = None
elem.clear()
return out
except Exception:
return []
def main():
if len(sys.argv) != 2:
print("usage: python script.py <root-dir>", file=sys.stderr)
sys.exit(1)
root = Path(sys.argv[1])
for path in iter_files(root):
try:
data = path.read_bytes()
except Exception:
continue
if not is_candidate(data):
continue
for fpath, muni, combo in find_hits(path, data):
print(f"{fpath} {muni} {combo}")
if __name__ == "__main__":
main()
実行すると、
/path/to/your/file.xml 八戸市 大雨注意報 + 大雪注意報
のように出力されます。
結果
5年分の実績である約33万回の警報・注意報発表状況を整理すると、以下のようになりました。
| 組み合わせ | 同時に発表されるか | 事例 |
|---|---|---|
| 「大雨」と「大雪」 | 発表される |
2025-12-05 14:23 新潟県長岡市 大雨注意報と大雪注意報 |
| 「大雨」と「風雪」 | 発表される |
2025-12-04 15:17 秋田県秋田市 大雨注意報と暴風雪注意報 |
| 「大雪」と「風」 | 発表される |
2025-12-14 14:44 北海道大樹町 大雪警報と暴風警報 |
| 「風」と「風雪」 | 発表されない (少なくとも2020年以降で) |
「大雨」「大雪」、「大雨」「風雪」、「大雪」「風」の組み合わせは、いずれも珍しいものではなく、直近でも発表事例がありました。
対して「風」と「風雪」の組み合わせですが、こちらは過去5年で1回も事例がありませんでした。
そして「大雨警報と大雪警報は同時に発表されるか?」については、直近5年でその発表事例を見つけることが出来ませんでした。
大雨注意報と大雨注意報のパターンや、片方が警報のパターンはよくありましたので、大雨警報と大雪警報の基準を同時に満たす気象場が起こりにくいだけで、仕組みとして出すことは可能なのでないかと思います。
つまり、記事タイトルの答えは「たぶん出る」です。
いかがでしたか?
さいごに
一見矛盾するような雨と雪の警報・注意報が一体どのようなからくりで同時に発表されるのかは分かりませんが、同時に発表されているからといって注意・警戒期間が完全に一致しているわけではない、あるいは陸上・海上で対象が異なる、温度場が雨と雪の境目にあたる、などが同時に発表される理由としてあるのではないかと思います。
何はともあれ「気象官署予報業務取扱便覧」を来年のサンタさんにお願いしましょう。
