From 3a94f5b4b71b197517ef0b3a2c51a95f9de0bc8e Mon Sep 17 00:00:00 2001 From: zlt Date: Wed, 9 Sep 2026 12:30:02 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=AC=E5=8F=B8=E6=B7=B1=E5=BA=A6=E5=8F=96?= =?UTF-8?q?=E6=95=B0=EF=BC=9A=E7=A9=BA=E5=88=97=20NaN=20=E6=94=B6=E6=88=90?= =?UTF-8?q?=20None=EF=BC=8C=E8=BF=90=E8=A1=8C=E6=97=A5=E6=99=9A=E4=BA=8E?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=97=A5=E7=AE=97=E9=9B=B6=E5=A4=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 --- sources.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sources.py b/sources.py index 9ed5a20..44c95be 100644 --- a/sources.py +++ b/sources.py @@ -1211,18 +1211,31 @@ def company_reviews(codes, ds: str, *, read_pg=None) -> dict: ran_day, age = None, None k = _prefix_any(str(r.get("ts_code"))) brain = sm.get("brain") or {} - out[k] = {"period": r.get("period"), "review_version": r.get("review_version"), + if age is not None and age < 0: + age = 0 # 报告运行日晚于数据日(今早刚跑):算零天,不算负数 + out[k] = {"period": _clean_str(r.get("period")), "review_version": _clean_str(r.get("review_version")), "overall": sm.get("overall"), "groups": sm.get("groups"), "valuation": sm.get("valuation"), "doubt_hard": bool(sm.get("doubt_hard")), "quality_reasons": sm.get("quality_reasons") or [], "grade_counts": sm.get("grade_counts") or _count_grades(grades), "grade_line": sm.get("grade_line"), "thesis": sm.get("thesis"), "confidence": sm.get("confidence"), "invalidation": sm.get("invalidation"), "antithesis": sm.get("antithesis"), "catalyst": sm.get("catalyst"), - "brain_status": r.get("brain_status") or brain.get("status"), "brain_used": bool(r.get("brain_used")), + "brain_status": _clean_str(r.get("brain_status")) or _clean_str(brain.get("status")), + "brain_used": bool(r.get("brain_used")) if r.get("brain_used") not in (None, "") and r.get("brain_used") == r.get("brain_used") else False, "ran_at": ran_day.isoformat() if ran_day else None, "age_days": age, "report_url": f"{config.AKG_API_BASE}{sm.get('report_path') or '/company/' + str(r.get('ts_code')) + '/review'}"} return out +def _clean_str(v): + """空列经 pandas 会变成 NaN(浮点),JSON 序列化直接失败;统一收成 None。""" + if v is None: + return None + if isinstance(v, float) and v != v: + return None + s = str(v).strip() + return s or None + + def _count_grades(grades) -> dict: out = {"好": 0, "中": 0, "差": 0, "证据不足": 0} for v in (grades or {}).values():