#!/usr/bin/env python3 """ hk_rate.py — 每日刷新HKD/CNY汇率 用法: from hk_rate import hkd_to_cny, refresh_rate rate = hkd_to_cny() # 自动使用缓存,过期则刷新 refresh_rate() # 强制刷新 缓存文件:~/.cache/hk_exchange_rate.json 有效期:24小时 """ import json, os, time, sys from datetime import date CACHE_PATH = os.path.expanduser("~/.cache/hk_exchange_rate.json") CACHE_TTL = 86400 # 24小时,合理配置常量 # 不再硬编码备用值,每次取缓存中的最近一次有效汇率 def _load_last_rate(): """从缓存文件读取上次已知有效汇率""" try: if os.path.exists(CACHE_PATH): with open(CACHE_PATH) as f: data = json.load(f) rate = data.get("rate", 0) if 0.7 < rate < 1.0: return round(float(rate), 6) except Exception: pass return None PRIMARY_API = "https://api.exchangerate-api.com/v4/latest/HKD" BACKUP_API = "https://api.exchangerate-api.com/v4/latest/USD" def _fetch_rate(): """从API获取 HKD/CNY 汇率""" import urllib.request ua = "Mozilla/5.0" # 主API:直接用HKD→CNY try: req = urllib.request.Request(PRIMARY_API, headers={"User-Agent": ua}) with urllib.request.urlopen(req, timeout=8) as r: data = json.loads(r.read()) cny = data.get("rates", {}).get("CNY") if cny and 0.7 < cny < 1.0: # 合理性检查 return round(float(cny), 6) except Exception: pass # 备用:USD→HKD + USD→CNY 间接计算 try: req = urllib.request.Request(BACKUP_API, headers={"User-Agent": ua}) with urllib.request.urlopen(req, timeout=8) as r: data = json.loads(r.read()) rates = data.get("rates", {}) hkd = rates.get("HKD") cny = rates.get("CNY") if hkd and cny: rate = cny / hkd if 0.7 < rate < 1.0: return round(rate, 6) except Exception: pass return None def hkd_to_cny(force_refresh=False): """获取 HKD→CNY 汇率,缓存过期则自动刷新""" os.makedirs(os.path.dirname(CACHE_PATH), exist_ok=True) now = time.time() rate = None # 读缓存 if not force_refresh: try: with open(CACHE_PATH) as f: cached = json.load(f) cache_date = cached.get("date", "") rate = cached.get("rate") cached_at = cached.get("cached_at", 0) # 同一天且未过期 if (cache_date == date.today().isoformat() and rate is not None and (now - cached_at) < CACHE_TTL): return rate except Exception: pass # 刷新 rate = _fetch_rate() if rate is None: # API全挂,用缓存中的上次有效汇率 rate = _load_last_rate() if rate is None: rate = 0.87 # 极限兜底,纯预防 print(f"[hk_rate] API不可达,使用 {rate} (fallback)", file=sys.stderr) else: # 写缓存 try: with open(CACHE_PATH, "w") as f: json.dump({ "rate": rate, "date": date.today().isoformat(), "cached_at": now, "source": "exchangerate-api.com", }, f) except Exception: pass return rate def refresh_rate(): return hkd_to_cny(force_refresh=True) if __name__ == "__main__": r = hkd_to_cny() print(f"HKD/CNY = {r}")