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 _time

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Inspect last_error in the message — it tells you which failure mode dominated (rate limit vs network vs parsing).
  2. If rate limiting: slow down (the fetcher already sleeps between calls), increase delays, or run off-hours.
  3. Verify network access to eastmoney.com and sina.com from the host.
  4. Upgrade akshare to match current upstream endpoints (pip install -U akshare).
  5. 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

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


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/164bb9c743197666. Report an issue: GitHub.