ZhuLinsen/daily_stock_analysis · error · DataFetchError
Akshare 所有渠道获取失败: {last_error}
Error message
Akshare 所有渠道获取失败: {last_error} What it means
DataFetchError raised when all internal akshare channels for a fetch have been tried and every one failed; the last channel's exception text is embedded. In _fetch_stock_data the fallback order tries multiple sources (e.g. Eastmoney, Sina), logging a warning per failure, so this error means the whole chain is exhausted (often due to rate limiting or network problems affecting all sources).
Source
Thrown at data_provider/akshare_fetcher.py:528
]
last_error = None
for fetch_method, source_name in methods:
try:
logger.info(f"[数据源] 尝试使用 {source_name} 获取 {stock_code}...")
df = fetch_method(stock_code, start_date, end_date)
if df is not None and not df.empty:
logger.info(f"[数据源] {source_name} 获取成功")
return df
except Exception as e:
last_error = e
logger.warning(f"[数据源] {source_name} 获取失败: {e}")
# 继续尝试下一个
# 所有都失败
raise DataFetchError(f"Akshare 所有渠道获取失败: {last_error}")
def _fetch_stock_data_em(self, stock_code: str, start_date: str, end_date: str) -> pd.DataFrame:
"""
获取普通 A 股历史数据 (东方财富)
数据来源:ak.stock_zh_a_hist()
"""
import akshare as ak
# 防封禁策略 1: 随机 User-Agent
self._set_random_user_agent()
# 防封禁策略 2: 强制休眠
self._enforce_rate_limit()
logger.info(f"[API调用] ak.stock_zh_a_hist(symbol={stock_code}, ...)")
try:
import time as _timeView on GitHub (pinned to 5159bd72e8)
Solutions
- Inspect last_error in the message — it tells you which failure mode dominated (rate limit vs network vs parsing).
- If rate limiting: slow down (the fetcher already sleeps between calls), increase delays, or run off-hours.
- Verify network access to eastmoney.com and sina.com from the host.
- Upgrade akshare to match current upstream endpoints (pip install -U akshare).
- Configure the provider fallback chain to try non-akshare sources (e.g. yfinance for overlap coverage) when this error occurs.
Example fix
# before: hammering all symbols back-to-back
for code in codes:
df = fetcher.fetch_stock_data(code, start, end)
# after: pace requests
import time
for code in codes:
df = fetcher.fetch_stock_data(code, start, end)
time.sleep(2) Defensive patterns
Strategy: fallback
Validate before calling
# pre-batch check: confirm at least one akshare channel responds before a long run
probe = fetcher.fetch_stock_data('000001', recent_5d_start, recent_5d_end)
assert probe is not None and not probe.empty, 'akshare channels unhealthy; postpone batch' Type guard
def is_akshare_all_channels_failed(exc: Exception) -> bool:
return isinstance(exc, DataFetchError) and '所有渠道获取失败' in str(exc) Try / catch
try:
df = fetcher.fetch_stock_data(code, start, end)
except DataFetchError as e:
if '所有渠道获取失败' in str(e):
log.warning('akshare exhausted for %s, falling back: %s', code, e)
df = alternate_fetcher.fetch_stock_data(code, start, end)
else:
raise Prevention
- Pace batch fetches (sleep + jitter) and cache results to avoid exhausting every channel at once.
- Wire a second data source into the provider chain so exhaustion degrades instead of failing the run.
- Alert when last_error mentions rate/ban keywords — the next full batch will fail too.
When it happens
Trigger: Fetching A-share daily data where both _fetch_stock_data_em (ak.stock_zh_a_hist) and _fetch_stock_data_sina (ak.stock_zh_a_daily) raise — e.g. the host is rate-limited/banned by both Eastmoney and Sina, or there is no egress to either host.
Common situations: Batch jobs fetching hundreds of symbols without pacing, triggering anti-scraping bans; running from a cloud IP range that data sources block; weekends/maintenance windows when endpoints return errors; outdated akshare whose endpoint signatures changed so every channel fails identically.
Related errors
- {call_name} 调用超过 {wait_seconds:g}s,已放弃等待
- Akshare(EM) 可能被限流: {e}
- Akshare 可能被限流: {e}
- Akshare 获取 ETF 数据失败: {e}
- {call_name} 调用进程未返回结果
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/164bb9c743197666.
Report an issue: GitHub.