binary-husky/gpt_academic · error · Exception

所有可用镜像站点均无法完成下载

Error message

所有可用镜像站点均无法完成下载

What it means

Raised after the loop over working mirrors completes without a single successful download response: every mirror that passed the health check nonetheless failed during the actual POST (exception, non-ok status, or captcha/HTML instead of the PDF). If individual exceptions were recorded, the last one is re-raised instead; this generic Exception only appears when all mirrors returned res.ok == False without raising.

Source

Thrown at crazy_functions/review_fns/data_sources/scihub_source.py:142

                    mirror,
                    headers=self.headers,
                    data=self.payload,
                    proxies=self.proxies,
                    timeout=self.timeout
                )
                if res.ok:
                    logger.info(f"成功使用镜像站点: {mirror}")
                    self.url = mirror  # 更新当前使用的镜像
                    time.sleep(1)  # 降低等待时间以提高效率
                    return res
            except Exception as e:
                logger.error(f"尝试镜像 {mirror} 失败: {str(e)}")
                last_exception = e
                continue

        if last_exception:
            raise last_exception
        raise Exception("所有可用镜像站点均无法完成下载")

    def _extract_url(self, response):
        """从响应中提取PDF下载链接"""
        soup = BeautifulSoup(response.content, 'html.parser')
        try:
            # 尝试多种方式提取PDF链接
            pdf_element = soup.find(id='pdf')
            if pdf_element:
                content_url = pdf_element.get('src')
            else:
                # 尝试其他可能的选择器
                pdf_element = soup.find('iframe')
                if pdf_element:
                    content_url = pdf_element.get('src')
                else:
                    # 查找直接的PDF链接
                    pdf_links = soup.find_all('a', href=lambda x: x and '.pdf' in x)
                    if pdf_links:

View on GitHub (pinned to d6bde0fa54)

Solutions

  1. Inspect logger.error lines just before the raise — they show each mirror's failure reason (status code vs exception).
  2. Add delay/backoff between probe and download, or reduce the probe burst, to avoid tripping rate limits.
  3. Verify the DOI actually exists on SciHub by opening a mirror in a browser with the same DOI.
  4. Rotate exit IP (different proxy) or try again later; fall back to the arXiv/open-access source for the paper.
Defensive patterns

Strategy: retry

Try / catch

try:
    res = scihub._fetch_from_mirrors()
except Exception as e:
    msg = str(e)
    if '所有可用镜像站点均无法完成下载' in msg or '尝试镜像' in msg:
        time.sleep(30)
        return scihub.download(doi, attempt=retry_no + 1)  # outer backoff
    raise

Prevention

When it happens

Trigger: Mirrors respond 200 to the health check but return 403/502/redirect-to-captcha for the real DOI POST; SciHub rate-limits the IP after the probe burst; the payload/DOI is not resolvable so every mirror answers an error page; proxies drop long POSTs.

Common situations: Scihub serving Cloudflare challenges to datacenter IPs; a DOI that SciHub does not have in its repository; stale mirror URLs that now park/redirect; aggressive probing (5 mirrors) triggering rate limits before the real download.

Related errors


AI-assisted analysis of binary-husky/gpt_academic@d6bde0fa54 (2026-08-14). Data as JSON: /api/errors/19f92031ea9099c1. Report an issue: GitHub.