ZhuLinsen/daily_stock_analysis · error · DataFetchError
Akshare 获取港股数据失败: {e}
Error message
Akshare 获取港股数据失败: {e} What it means
The generic DataFetchError raised by AkshareFetcher._fetch_hk_data when ak.stock_hk_hist fails with any exception not classified as rate limiting. It wraps the original akshare exception (available via __cause__) and is the signal for DataFetcherManager to try the next HK data source in its priority chain.
Source
Thrown at data_provider/akshare_fetcher.py:885
if df is not None and not df.empty:
logger.info(f"[API返回] ak.stock_hk_hist 成功: 返回 {len(df)} 行数据, 耗时 {api_elapsed:.2f}s")
logger.info(f"[API返回] 列名: {list(df.columns)}")
logger.info(f"[API返回] 日期范围: {df['日期'].iloc[0]} ~ {df['日期'].iloc[-1]}")
logger.debug(f"[API返回] 最新3条数据:\n{df.tail(3).to_string()}")
else:
logger.warning(f"[API返回] ak.stock_hk_hist 返回空数据, 耗时 {api_elapsed:.2f}s")
return df
except Exception as e:
error_msg = str(e).lower()
# 检测反爬封禁
if any(keyword in error_msg for keyword in ['banned', 'blocked', '频率', 'rate', '限制']):
logger.warning(f"检测到可能被封禁: {e}")
raise RateLimitError(f"Akshare 可能被限流: {e}") from e
raise DataFetchError(f"Akshare 获取港股数据失败: {e}") from e
def _normalize_data(self, df: pd.DataFrame, stock_code: str) -> pd.DataFrame:
"""
标准化 Akshare 数据
Akshare 返回的列名(中文):
日期, 开盘, 收盘, 最高, 最低, 成交量, 成交额, 振幅, 涨跌幅, 涨跌额, 换手率
需要映射到标准列名:
date, open, high, low, close, volume, amount, pct_chg
"""
df = df.copy()
# 列名映射(Akshare 中文列名 -> 标准英文列名)
column_mapping = {
'日期': 'date',
'开盘': 'open',
'收盘': 'close',View on GitHub (pinned to 5159bd72e8)
Solutions
- Check e.__cause__: TypeError usually means akshare API change → pin/upgrade akshare; JSONDecodeError → block page or endpoint change.
- Normalize HK codes to 5 digits before calling (e.g. '00700', not '700').
- Retry once after a short sleep for transient 5xx, then let fallback take over.
- Confirm ak.stock_hk_hist works standalone in a REPL with the same arguments.
Example fix
# before
akshare_fetcher.fetch('700', start, end) # HK code missing padding
# after
code = '700'.zfill(5) # '00700'
akshare_fetcher.fetch(code, start, end) Defensive patterns
Strategy: fallback
Validate before calling
code = '700'.zfill(5) # HK codes need 5-digit zero padding for ak.stock_hk_hist assert len(code) == 5 and code.isdigit()
Type guard
def is_valid_hk_code(code: str) -> bool:
c = code.lower().removeprefix('hk')
return len(c) == 5 and c.isdigit() Try / catch
try:
df = akshare_fetcher.fetch(hk_code, start, end)
except RateLimitError:
raise
except DataFetchError as e:
logger.warning('akshare HK failed for %s: %s', hk_code, e)
df = manager.fetch(hk_code, start, end) Prevention
- Normalize HK codes to 5-digit padded form at config load.
- Test ak.stock_hk_hist standalone after akshare upgrades.
- Keep a second HK-capable source in the chain.
When it happens
Trigger: Calling fetch for an HK code ('00700') when stock_hk_hist raises: invalid symbol argument (e.g. '700' without zero padding), network timeout to East Money, JSON decode error on an HTML block page without keywords, or akshare interface changes after upgrade.
Common situations: HK codes passed without 5-digit zero-padding; akshare version drift changing stock_hk_hist parameters ('period'/'adjust' renamed); intermittent East Money 5xx errors.
Related errors
- Akshare 获取 ETF 数据失败: {e}
- Akshare 获取美股数据失败: {e}
- {call_name} 调用超过 {wait_seconds:g}s,已放弃等待
- {call_name} 调用进程未返回结果
- AkshareFetcher 不支持美股 {stock_code},请使用 YfinanceFetcher 获取正确的复
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/09a9d05664b4ee44.
Report an issue: GitHub.