auto-sync: 2026-05-02 18:58:57
This commit is contained in:
+24
-35
@@ -58,51 +58,40 @@ def get_last_date(code: str, exchange: str) -> str:
|
||||
|
||||
|
||||
def fetch_incremental(code: str, start_date: str, end_date: str):
|
||||
"""获取增量数据:先试akshare,失败用腾讯K线"""
|
||||
# 1. akshare
|
||||
"""获取增量数据:腾讯K线(主源,稳定无代理问题)"""
|
||||
# 直接用腾讯K线API(akshare有代理问题,作为降级备源)
|
||||
try:
|
||||
import akshare as ak
|
||||
df = ak.stock_zh_a_hist(
|
||||
symbol=code, period="daily",
|
||||
start_date=start_date.replace("-", ""),
|
||||
end_date=end_date.replace("-", ""),
|
||||
adjust=""
|
||||
)
|
||||
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:
|
||||
pass # akshare失败,静默切到腾讯
|
||||
|
||||
# 2. 腾讯K线API
|
||||
try:
|
||||
import urllib.request, json
|
||||
import urllib.request
|
||||
import json as _json
|
||||
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?param={tq},day,,{days},"
|
||||
# 用无代理opener避免akshare代理污染
|
||||
opener = urllib.request.build_opener(urllib.request.ProxyHandler({}))
|
||||
proxy_handler = urllib.request.ProxyHandler({})
|
||||
opener = urllib.request.build_opener(proxy_handler)
|
||||
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
|
||||
with opener.open(req, timeout=10) as r:
|
||||
data = json.loads(r.read())
|
||||
klines = data.get("data", {}).get(tq, {}).get("day", [])
|
||||
resp = opener.open(req, timeout=10)
|
||||
raw = resp.read().decode('utf-8', errors='replace')
|
||||
data = _json.loads(raw)
|
||||
d = data.get('data')
|
||||
if not isinstance(d, dict):
|
||||
return None
|
||||
klines = d.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"]]
|
||||
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)
|
||||
result = df.loc[mask, ['date', 'open', 'high', 'low', 'close', 'volume', 'amount']]
|
||||
if result.empty:
|
||||
return None
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.warning(f"腾讯K线也失败 {code}: {e}")
|
||||
logger.warning(f'腾讯K线失败 {code}: {e}')
|
||||
return None
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user