fix(data): baostock_download断连自动re-login retry(限流鲁棒)

本机下131只后baostock broken pipe卡死(脚本无retry). 加reconnect()+download_one
max_retries=3(空结果/broken pipe→bs.logout+login重试). 下次跑断点续传skip 131.
This commit is contained in:
2026-07-10 07:10:36 +08:00
parent 18d4ba2013
commit 917d5bca2a
+47 -21
View File
@@ -64,27 +64,53 @@ def exists(code: str, adjust: str, start_year: int) -> bool:
return False
def download_one(code: str, start: str, end: str, adjustflag: str):
"""baostock 15min,返回 (df, None) 或 (None, err)"""
rs = bs.query_history_k_data_plus(
bs_symbol(code),
"date,time,open,high,low,close,volume,amount",
start_date=start, end_date=end, frequency="15", adjustflag=adjustflag,
)
rows, fields = [], rs.fields
while (rs.error_code == "0") & rs.next():
rows.append(rs.get_row_data())
if not rows:
return None, rs.error_msg
df = pd.DataFrame(rows, columns=fields)
for c in ("open", "high", "low", "close", "volume", "amount"):
df[c] = pd.to_numeric(df[c], errors="coerce")
t = df["time"].astype(str)
df["datetime"] = pd.to_datetime(
df["date"] + " " + t.str[8:10] + ":" + t.str[10:12], errors="coerce"
)
df = df.dropna(subset=["close", "datetime"]).sort_values("datetime")
return df, None
def reconnect() -> bool:
"""baostock 断连后重连(限流/broken pipe 恢复)"""
try:
bs.logout()
except Exception: # noqa: BLE001
pass
return bs.login().error_code == "0"
def download_one(code: str, start: str, end: str, adjustflag: str, max_retries: int = 3):
"""baostock 15min,返回 (df, None) 或 (None, err)。断连/限流自动 re-login retry。"""
last_err = ""
for attempt in range(max_retries):
try:
rs = bs.query_history_k_data_plus(
bs_symbol(code),
"date,time,open,high,low,close,volume,amount",
start_date=start, end_date=end, frequency="15", adjustflag=adjustflag,
)
rows, fields = [], rs.fields
while (rs.error_code == "0") & rs.next():
rows.append(rs.get_row_data())
if not rows:
last_err = rs.error_msg or "empty"
# 空可能是限流("接收数据异常")→ re-login 重试
if attempt < max_retries - 1:
reconnect()
time.sleep(2)
continue
return None, last_err
df = pd.DataFrame(rows, columns=fields)
for c in ("open", "high", "low", "close", "volume", "amount"):
df[c] = pd.to_numeric(df[c], errors="coerce")
t = df["time"].astype(str)
df["datetime"] = pd.to_datetime(
df["date"] + " " + t.str[8:10] + ":" + t.str[10:12], errors="coerce"
)
df = df.dropna(subset=["close", "datetime"]).sort_values("datetime")
return df, None
except Exception as e: # noqa: BLE001 broken pipe 等
last_err = f"{type(e).__name__}: {str(e)[:80]}"
if attempt < max_retries - 1:
reconnect()
time.sleep(2)
continue
return None, last_err
return None, last_err
def save_one(code, df, adjust):