cwadayi commited on
Commit
3234236
·
verified ·
1 Parent(s): 750a4d3

Create fetch_cwa_alarm_list.py

Browse files
Files changed (1) hide show
  1. fetch_cwa_alarm_list.py +118 -0
fetch_cwa_alarm_list.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ from __future__ import annotations
3
+ import requests
4
+ from datetime import datetime, timedelta, timezone
5
+
6
+ CWA_ALARM_API = "https://app-2.cwa.gov.tw/api/v1/earthquake/alarm/list"
7
+
8
+ def _parse_cwa_time(s: str) -> tuple[str, str]:
9
+ """
10
+ 解析 CWA 的 originTime。
11
+ - 若帶有時區或 'Z',尊重其時區;輸出台灣時間與 UTC。
12
+ - 若無時區(常見 'YYYY-MM-DD HH:MM:SS'),視為台灣時間 (UTC+8)。
13
+ 回傳: (tw_str, utc_str) -> "YYYY-MM-DD HH:MM"
14
+ """
15
+ if not s:
16
+ return ("未知", "未知")
17
+ try:
18
+ if "T" in s or s.endswith("Z") or "+" in s:
19
+ dt = datetime.fromisoformat(s.replace("Z", "+00:00"))
20
+ else:
21
+ dt = datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
22
+ dt = dt.replace(tzinfo=timezone(timedelta(hours=8)))
23
+ tw = dt.astimezone(timezone(timedelta(hours=8))).strftime("%Y-%m-%d %H:%M")
24
+ utc = dt.astimezone(timezone.utc).strftime("%Y-%m-%d %H:%M")
25
+ return (tw, utc)
26
+ except Exception:
27
+ return (s, "未知")
28
+
29
+ def fetch_cwa_alarm_list(limit: int = 5) -> str:
30
+ """
31
+ 取得中央氣象署「地震預警」清單並格式化為文字(抓常見欄位;最多 limit 筆)。
32
+ 顯示:事件ID、狀態/訊息型別#序號、震級、深度、震中座標、台灣時間與UTC、預警地區。
33
+ """
34
+ try:
35
+ r = requests.get(CWA_ALARM_API, timeout=10)
36
+ r.raise_for_status()
37
+ payload = r.json()
38
+ except Exception as e:
39
+ return f"❌ 地震預警查詢失敗:{e}"
40
+
41
+ # 取出清單
42
+ items = None
43
+ if isinstance(payload, dict):
44
+ items = payload.get("data") or payload.get("records") or payload.get("list") or payload.get("items")
45
+ if items is None and isinstance(payload, list):
46
+ items = payload
47
+ if not items:
48
+ return "✅ 目前沒有地震預警。"
49
+
50
+ # 依 originTime 由新到舊排序
51
+ def _key(it):
52
+ s = it.get("originTime") or ""
53
+ try:
54
+ if "T" in s or s.endswith("Z") or "+" in s:
55
+ dt = datetime.fromisoformat(s.replace("Z", "+00:00"))
56
+ else:
57
+ dt = datetime.strptime(s, "%Y-%m-%d %H:%M:%S").replace(tzinfo=timezone(timedelta(hours=8)))
58
+ return dt.astimezone(timezone.utc)
59
+ except Exception:
60
+ return datetime.min.replace(tzinfo=timezone.utc)
61
+
62
+ try:
63
+ items = sorted(items, key=_key, reverse=True)
64
+ except Exception:
65
+ pass
66
+
67
+ lines = ["🚨 地震預警(最新):", "-" * 20]
68
+ count = 0
69
+ for it in items:
70
+ if count >= limit:
71
+ break
72
+
73
+ identifier = it.get("identifier") or it.get("eventId") or it.get("id") or "—"
74
+ status = it.get("status") or "—"
75
+ msg_type = it.get("msgType") or "—"
76
+ msg_no = it.get("msgNo") or it.get("msgSeq") or "—"
77
+
78
+ def _num(x):
79
+ xs = str(x)
80
+ ok = xs.replace(".", "", 1).replace("-", "", 1).isdigit()
81
+ return float(xs) if ok else None
82
+
83
+ mag = _num(it.get("magnitudeValue") or it.get("magnitude") or it.get("ml") or it.get("mw"))
84
+ mag_str = f"{mag:.1f}" if mag is not None else "—"
85
+
86
+ depth = _num(it.get("depth"))
87
+ depth_str = f"{depth:.0f}" if depth is not None else "—"
88
+
89
+ lat = _num(it.get("epicenterLat") or it.get("latitude") or it.get("lat"))
90
+ lon = _num(it.get("epicenterLon") or it.get("longitude") or it.get("lon"))
91
+ lat_str = f"{lat:.2f}" if lat is not None else "—"
92
+ lon_str = f"{lon:.2f}" if lon is not None else "—"
93
+
94
+ origin = it.get("originTime") or ""
95
+ tw_str, utc_str = _parse_cwa_time(origin)
96
+
97
+ areas = it.get("locationDesc") or it.get("areas") or it.get("alertAreas")
98
+ if isinstance(areas, list):
99
+ areas_txt = "、".join(str(a) for a in areas if a)
100
+ elif isinstance(areas, str):
101
+ areas_txt = areas
102
+ else:
103
+ areas_txt = "—"
104
+
105
+ lines.append(
106
+ f"事件: {identifier} | 狀態: {status} | 類型: {msg_type}#{msg_no}\n"
107
+ f"震級/深度: M{mag_str} / {depth_str} km\n"
108
+ f"震中: lat {lat_str}, lon {lon_str}\n"
109
+ f"時間: {tw_str}(台灣) / {utc_str}(UTC)\n"
110
+ f"預警地區: {areas_txt}"
111
+ )
112
+ lines.append("")
113
+ count += 1
114
+
115
+ if len(items) > limit:
116
+ lines.append(f"... 另有 {len(items) - limit} 筆。")
117
+
118
+ return "\n".join(lines).strip()