TDN-IntensityGMM-TW / fetch_cwa_api.py
walbcglgh's picture
Upload folder using huggingface_hub
3c5cae5 verified
Raw History Blame Contribute Delete
4.1 kB
"""Pull the CWA open-data significant-earthquake report (E-A0015-001).
The API needs a free authorization code. Provide it either in a file next to this
script:
.cwa_api_key (one line, e.g. CWA-XXXXXXXX...)
or via the environment variable CWA_API_KEY.
Usage:
python fetch_cwa_api.py --inspect # 1 call, print the response shape
python fetch_cwa_api.py --from 2020-01-01 --to 2020-12-31
python fetch_cwa_api.py --datetime "2020-06-14T00:00:00"
"""
import argparse
import json
import os
import urllib.parse
import urllib.request
from palert.paths import DATA_DIR, ROOT
ENDPOINT = "https://opendata.cwa.gov.tw/api/v1/rest/datastore/E-A0015-001"
KEY_FILE = os.path.join(ROOT, ".cwa_api_key")
RAW_DIR = os.path.join(DATA_DIR, "raw", "cwa_api")
os.makedirs(RAW_DIR, exist_ok=True)
def load_key():
key = os.environ.get("CWA_API_KEY")
if not key and os.path.exists(KEY_FILE):
with open(KEY_FILE, encoding="utf-8") as fh:
key = fh.read().strip()
if not key:
raise SystemExit(
"No API key. Put it in .cwa_api_key (one line) or set CWA_API_KEY."
)
return key
def call(params, key=None):
query = dict(params)
query.setdefault("format", "JSON")
query["Authorization"] = key or load_key()
url = ENDPOINT + "?" + urllib.parse.urlencode(query, doseq=True)
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
with urllib.request.urlopen(req, timeout=60) as resp:
return json.loads(resp.read().decode("utf-8"))
def summarize(obj, depth=0, path="", max_depth=4):
pad = " " * depth
if isinstance(obj, dict):
for k, v in obj.items():
if isinstance(v, (dict, list)) and depth < max_depth:
n = f"[{len(v)}]" if isinstance(v, list) else ""
print(f"{pad}{k}: {type(v).__name__}{n}")
summarize(v, depth + 1, f"{path}.{k}", max_depth)
else:
print(f"{pad}{k}: {repr(v)[:70]}")
elif isinstance(obj, list) and obj:
print(f"{pad}(first element)")
summarize(obj[0], depth + 1, path + "[0]", max_depth)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--inspect", action="store_true", help="single call, print the structure")
ap.add_argument("--datetime", dest="datetime_", help="single origin time yyyy-MM-ddThh:mm:ss")
ap.add_argument("--from", dest="date_from", help="start date yyyy-MM-dd")
ap.add_argument("--to", dest="date_to", help="end date yyyy-MM-dd")
ap.add_argument("--limit", type=int, default=1000)
ap.add_argument("--max-pages", type=int, default=50)
args = ap.parse_args()
if args.inspect:
data = call({"limit": 1})
print(json.dumps(data, ensure_ascii=False)[:400])
print("\n--- structure ---")
summarize(data)
return
if args.datetime_:
data = call({"OriginTime": args.datetime_, "limit": args.limit})
out = os.path.join(RAW_DIR, "single.json")
with open(out, "w", encoding="utf-8") as fh:
json.dump(data, fh, ensure_ascii=False, indent=2)
print("saved", out)
return
if not (args.date_from and args.date_to):
ap.error("need --datetime, --inspect, or --from/--to")
collected = []
for page in range(args.max_pages):
params = {"limit": args.limit, "offset": page * args.limit}
data = call(params)
out = os.path.join(RAW_DIR, f"page_{page:03d}.json")
with open(out, "w", encoding="utf-8") as fh:
json.dump(data, fh, ensure_ascii=False, indent=2)
recs = (data.get("records") or {})
batch = []
for v in recs.values():
if isinstance(v, list):
batch = v
break
print(f"page {page}: {len(batch)} records")
if not batch:
break
collected.extend(batch)
if len(batch) < args.limit:
break
print(f"[total] {len(collected)} records across pages")
if __name__ == "__main__":
main()