From c18ff504e495554fd2111e2c62406eef8f5da579 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Sat, 23 May 2026 10:13:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20CMA=20=E6=B8=A9=E5=BA=A6?= =?UTF-8?q?=E6=8F=90=E5=8F=96=EF=BC=9A=E6=94=B9=E7=94=A8=E7=BA=AF=E6=96=87?= =?UTF-8?q?=E6=9C=AC=E6=95=B0=E5=AD=97=E5=8C=B9=E9=85=8D=E6=9B=BF=E4=BB=A3?= =?UTF-8?q?=20HTML=20=E6=A0=87=E7=AD=BE=E7=8C=9C=E6=B5=8B=EF=BC=8C?= =?UTF-8?q?=E5=A4=A9=E6=B0=94=E4=BC=98=E5=85=88=20CMA=E3=80=81=E6=B8=A9?= =?UTF-8?q?=E5=BA=A6=E5=9B=9E=E9=80=80=20OM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/daily_weather_report.py | 104 ++++++++++++++---------------- 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/src/utils/daily_weather_report.py b/src/utils/daily_weather_report.py index aaec86f6..62719ad2 100644 --- a/src/utils/daily_weather_report.py +++ b/src/utils/daily_weather_report.py @@ -115,14 +115,13 @@ def _fetch_cma_forecast(city_key: str) -> Optional[Dict[str, Any]]: low_str: Optional[str] = None if tem_text: - # Patterns: 25℃ or 25°C - high_match = re.search(r"]*>(-?\d+)\s*(?:℃|°C|°c)?", tem_text) - if high_match: - high_str = high_match.group(1) - # Night temp in : 19℃ - low_match = re.search(r"]*>(-?\d+)\s*(?:℃|°C|°c)?", tem_text) - if low_match: - low_str = low_match.group(1) + # Strip all HTML tags, then find numbers followed by degree + clean = re.sub(r"<[^>]+>", " ", tem_text) + nums = re.findall(r"(-?\d+)\s*(?:℃|°C|°c|°)?", clean) + if len(nums) >= 1: + high_str = nums[0] + if len(nums) >= 2: + low_str = nums[1] if not weather and not high_str: return None @@ -161,64 +160,57 @@ def _fetch_city_data( ) -> Optional[Dict[str, Any]]: name = CITY_NAME_ZH.get(city_key, city_key) - # 1. Try CMA first for weather description + official forecast high + # 1. Try CMA first for weather description cma = _fetch_cma_forecast(city_key) - if cma and cma.get("weather") and cma.get("forecast_high") is not None: - logger.info( - "daily_weather_report: {} using CMA weather={} high={}", - city_key, - cma["weather"], - cma["forecast_high"], - ) - return { - "city": city_key, - "name": name, - "weather": cma["weather"], - "forecast_high": cma["forecast_high"], - } - # 2. Fall back to Open-Meteo + # 2. Get Open-Meteo data for temperature fallback + om_high = None info = CITY_REGISTRY.get(city_key) - if not info: - return None + if info: + try: + results = collector.fetch_all_sources( + city_key, + lat=info["lat"], + lon=info["lon"], + include_taf=False, + include_ensemble=False, + include_multi_model=False, + ) + if isinstance(results, dict): + om = results.get("open-meteo", {}) + daily = om.get("daily", {}) if isinstance(om, dict) else {} + daily_highs = daily.get("temperature_2m_max", []) or [] + om_high = daily_highs[0] if daily_highs else None + except Exception as exc: + logger.warning( + "daily_weather_report: OM fetch failed for {}: {}", city_key, exc + ) - try: - results = collector.fetch_all_sources( - city_key, - lat=info["lat"], - lon=info["lon"], - include_taf=False, - include_ensemble=False, - include_multi_model=False, - ) - except Exception as exc: - logger.warning(f"daily_weather_report: OM fetch failed for {city_key}: {exc}") - return None + # Use CMA weather + CMA high, fall back to OM high + weather: Optional[str] = None + forecast_high: Optional[float] = None - if not isinstance(results, dict): - return None - - om = results.get("open-meteo", {}) if isinstance(results, dict) else {} - current = om.get("current_weather", {}) if isinstance(om, dict) else {} - daily = om.get("daily", {}) if isinstance(om, dict) else {} - - daily_highs = daily.get("temperature_2m_max", []) or [] - today_high = daily_highs[0] if daily_highs else None - - # Use CMA weather if available, fall back to WMO code translation - weather = ( - cma.get("weather") - if (cma and cma.get("weather")) - else _wmo_to_weather(current.get("weathercode")) - ) - forecast_high = cma.get("forecast_high") if cma else None + if cma: + weather = cma.get("weather") + forecast_high = cma.get("forecast_high") if forecast_high is None: - forecast_high = today_high + forecast_high = om_high + + if not weather and not forecast_high: + return None + + logger.info( + "daily_weather_report: {} weather={} high={} (cma_ok={})", + city_key, + weather or "?", + forecast_high, + bool(cma and cma.get("weather")), + ) return { "city": city_key, "name": name, - "weather": weather, + "weather": weather or "?", "forecast_high": forecast_high, }