From bc7b58f5825fdc290b3be4250c920e2f9d7c66cc Mon Sep 17 00:00:00 2001 From: cfdaily Date: Sat, 2 May 2026 18:50:54 +0800 Subject: [PATCH] auto-sync: 2026-05-02 18:50:54 --- data_platform/updater.py | 46 ++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/data_platform/updater.py b/data_platform/updater.py index 3026e776..3804371b 100644 --- a/data_platform/updater.py +++ b/data_platform/updater.py @@ -58,7 +58,8 @@ def get_last_date(code: str, exchange: str) -> str: def fetch_incremental(code: str, start_date: str, end_date: str): - """用akshare获取增量数据""" + """获取增量数据:先试akshare,失败用腾讯K线""" + # 1. akshare try: import akshare as ak df = ak.stock_zh_a_hist( @@ -67,17 +68,40 @@ def fetch_incremental(code: str, start_date: str, end_date: str): end_date=end_date.replace("-", ""), adjust="" ) - if df is None or df.empty: - return None - df = df.rename(columns={"日期": "date", "开盘": "open", "收盘": "close", - "最高": "high", "最低": "low", "成交量": "volume", - "成交额": "amount"}) - df["date"] = pd.to_datetime(df["date"]).dt.strftime("%Y-%m-%d") - for c in ["open", "high", "low", "close", "volume", "amount"]: - df[c] = pd.to_numeric(df[c], errors="coerce").fillna(0) - return df[["date", "open", "high", "low", "close", "volume", "amount"]] + if df is not None and not df.empty: + df = df.rename(columns={"日期": "date", "开盘": "open", "收盘": "close", + "最高": "high", "最低": "low", "成交量": "volume", + "成交额": "amount"}) + df["date"] = pd.to_datetime(df["date"]).dt.strftime("%Y-%m-%d") + for c in ["open", "high", "low", "close", "volume", "amount"]: + df[c] = pd.to_numeric(df[c], errors="coerce").fillna(0) + return df[["date", "open", "high", "low", "close", "volume", "amount"]] except Exception as e: - logger.warning(f"akshare获取失败 {code}: {e}") + pass # akshare失败,静默切到腾讯 + + # 2. 腾讯K线API + try: + prefix = 'sh' if code.startswith(('6', '5', '1')) else 'sz' + tq = f"{prefix}{code}" + days = (pd.Timestamp(end_date) - pd.Timestamp(start_date)).days + 10 + url = f"https://web.ifzq.gtimg.cn/appstock/app/fqkline/get?_var=kline_dayqfq¶m={tq},day,,{days},qfqa" + import urllib.request, json + with urllib.request.urlopen(url, timeout=10) as r: + raw = r.read().decode('gbk') + json_str = raw.split('=', 1)[1] + data = json.loads(json_str) + klines = data.get("data", {}).get(tq, {}).get("day", []) + if not klines: + return None + df = pd.DataFrame(klines, columns=["date", "open", "close", "high", "low", "volume"]) + for c in ["open", "close", "high", "low", "volume"]: + df[c] = pd.to_numeric(df[c], errors="coerce").fillna(0) + df["amount"] = 0.0 + df["date"] = pd.to_datetime(df["date"]).dt.strftime("%Y-%m-%d") + mask = (df["date"] >= start_date) & (df["date"] <= end_date) + return df.loc[mask, ["date", "open", "high", "low", "close", "volume", "amount"]] + except Exception as e: + logger.warning(f"腾讯K线也失败 {code}: {e}") return None