Use Cases

使用验证码解决进行学术研究网络抓取

学术数据库和期刊门户使用验证码来限制自动访问。进行文献综述、文献计量分析和元研究的研究人员需要从这些来源大规模收集数据。 CaptchaAI 自动处理验证码挑战。


学术来源和验证码

来源 验证码类型 扳机 数据
谷歌学术 reCAPTCHA v3 大容量查询 引文、论文
考研 reCAPTCHA v2 重复搜索 生物医学文献
科学网 Cloudflare Turnstile 批量下载 引文指标
斯科普斯 reCAPTCHA v2 出口业务 文献计量数据
IEEE探索 reCAPTCHA v2 搜索+下载 工程论文
JSTOR reCAPTCHA v2 访问页面 人文/social 科学

引文数据收集器

import requests
import time
import re
from bs4 import BeautifulSoup
import csv

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"


def solve_captcha(method, sitekey, pageurl, **kwargs):
    data = {
        "key": CAPTCHAAI_KEY, "method": method,
        "googlekey": sitekey, "pageurl": pageurl, "json": 1,
    }
    data.update(kwargs)
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
    task_id = resp.json()["request"]
    for _ in range(60):
        time.sleep(5)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        r = result.json()
        if r["request"] != "CAPCHA_NOT_READY":
            return r["request"]
    raise TimeoutError("Timeout")


class AcademicScraper:
    def __init__(self, proxy=None):
        self.session = requests.Session()
        if proxy:
            self.session.proxies = {"http": proxy, "https": proxy}
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
            "Accept-Language": "en-US,en;q=0.9",
        })

    def search_papers(self, search_url, query, max_pages=10):
        """Search academic database for papers matching query."""
        all_papers = []

        for page in range(max_pages):
            url = f"{search_url}?q={query}&start={page * 10}"
            resp = self.session.get(url, timeout=30)

            # Handle CAPTCHA
            if self._has_captcha(resp.text):
                resp = self._solve_and_retry(resp.text, url)

            papers = self._parse_results(resp.text)
            if not papers:
                break  # No more results

            all_papers.extend(papers)
            print(f"Page {page + 1}: {len(papers)} papers")
            time.sleep(5)  # Respectful delay

        return all_papers

    def get_paper_details(self, paper_url):
        """Get detailed metadata for a single paper."""
        resp = self.session.get(paper_url, timeout=30)

        if self._has_captcha(resp.text):
            resp = self._solve_and_retry(resp.text, paper_url)

        soup = BeautifulSoup(resp.text, "html.parser")
        return {
            "title": self._safe_text(soup, "h1, .article-title"),
            "authors": self._safe_text(soup, ".authors, .author-list"),
            "abstract": self._safe_text(soup, ".abstract, #abstract"),
            "doi": self._safe_text(soup, ".doi, [data-doi]"),
            "journal": self._safe_text(soup, ".journal-name, .publication"),
            "year": self._safe_text(soup, ".pub-date, .year"),
            "citations": self._safe_text(soup, ".citation-count, .cited-by"),
        }

    def export_to_csv(self, papers, filename):
        """Export collected papers to CSV."""
        if not papers:
            return
        keys = papers[0].keys()
        with open(filename, "w", newline="", encoding="utf-8") as f:
            writer = csv.DictWriter(f, fieldnames=keys)
            writer.writeheader()
            writer.writerows(papers)
        print(f"Exported {len(papers)} papers to {filename}")

    def _has_captcha(self, html):
        return any(tag in html.lower() for tag in [
            'data-sitekey', 'g-recaptcha', 'cf-turnstile',
        ])

    def _solve_and_retry(self, html, url):
        match = re.search(r'data-sitekey="([^"]+)"', html)
        if not match:
            return self.session.get(url)

        sitekey = match.group(1)
        if 'cf-turnstile' in html:
            token = solve_captcha("turnstile", sitekey, url)
            return self.session.post(url, data={"cf-turnstile-response": token})
        else:
            token = solve_captcha("userrecaptcha", sitekey, url)
            return self.session.post(url, data={"g-recaptcha-response": token})

    def _parse_results(self, html):
        soup = BeautifulSoup(html, "html.parser")
        papers = []
        for item in soup.select(".gs_r, .search-result, article.result"):
            title_el = item.select_one("h3 a, .result-title a")
            if title_el:
                papers.append({
                    "title": title_el.get_text(strip=True),
                    "url": title_el.get("href", ""),
                    "snippet": self._safe_text(item, ".gs_rs, .abstract-snippet"),
                    "authors": self._safe_text(item, ".gs_a, .author-info"),
                })
        return papers

    def _safe_text(self, soup, selector):
        el = soup.select_one(selector)
        return el.get_text(strip=True) if el else ""


# Usage — Literature review
scraper = AcademicScraper(
    proxy="http://user:pass@residential.proxy.com:5000"
)

papers = scraper.search_papers(
    "https://scholar.example.com/scholar",
    query="machine learning CAPTCHA solving",
    max_pages=5,
)

# Get details for top papers
detailed = []
for paper in papers[:20]:
    if paper["url"]:
        detail = scraper.get_paper_details(paper["url"])
        detailed.append(detail)
        time.sleep(3)

scraper.export_to_csv(detailed, "literature_review.csv")

文献计量分析

def bibliometric_analysis(scraper, seed_papers, depth=2):
    """Follow citations to build a citation network."""
    visited = set()
    network = []

    def _crawl(paper_url, current_depth):
        if current_depth > depth or paper_url in visited:
            return
        visited.add(paper_url)

        try:
            details = scraper.get_paper_details(paper_url)
            network.append(details)

            # Follow "cited by" links
            resp = scraper.session.get(f"{paper_url}/citations", timeout=30)
            if scraper._has_captcha(resp.text):
                resp = scraper._solve_and_retry(resp.text, f"{paper_url}/citations")

            citations = scraper._parse_results(resp.text)
            for cite in citations[:5]:  # Limit breadth
                if cite["url"]:
                    _crawl(cite["url"], current_depth + 1)
                    time.sleep(3)

        except Exception as e:
            print(f"Error crawling {paper_url}: {e}")

    for paper in seed_papers:
        _crawl(paper["url"], 0)

    return network

学术网站的速率限制

来源 建议延迟 最大页数/Hour
谷歌学术 10-15秒 40-50
考研 3-5秒 100
科学网 5-10秒 60
斯科普斯 5-10秒 60
IEEE 3-5秒 100
JSTOR 5-10秒 60

学术网站很快禁止 IP。使用保守的延迟。


故障排除

问题 原因 处理方式
每次搜索时都会显示验证码 学术网站标记 IP 切换代理,将延迟增加到 15 秒以上
没有返回结果 返回验证码页面 解析前检查验证码
摘要缺失 付费专区背后 使用机构代理或开放访问
学者封锁知识产权 超出速率限制 等待30分钟,使用不同的IP
出口有限 网站上限批量下载 小批量下载

常问问题

是否允许抓取学术数据库?

公共元数据(标题、作者、摘要)通常是可访问的。全文访问取决于许可。 PubMed 明确支持通过其电子实用程序 API 进行编程访问。始终首选可用的官方 API。

如何避免在 Google Scholar 上被屏蔽?

在请求之间使用 10-15 秒的延迟,轮换自有服务器基础设施,并将查询限制为每小时 50 次。 Scholar 积极阻止自动访问。

我可以通过机构代理使用 CaptchaAI 吗?

是的。设置用于浏览会话的机构代理和用于验证码解决的 CaptchaAI - 它们独立工作。


相关指南

  • 轮换自有服务器基础设施
  • 代理质量影响解决率

加速你的文献综述——获取您的 CaptchaAI 密钥并自动化学术数据收集。

该文章已禁用评论。

相关文章

Use Cases 高需求 e-commerce checkout 的 CAPTCHA 测试
面向 QA 的指南:在自有 staging 环境中使用虚拟库存、测试支付 token 和 Captcha AI 验证 e-commerce checkout 的 CAPTCHA 集成。

面向 QA 的指南:在自有 staging 环境中使用虚拟库存、测试支付 token 和 Captcha AI 验证 e-commerce checkout 的 CA...

May 04, 2026
Use Cases Web 表单中 API 端点测试的 CAPTCHA 解决方案
Web 表单中 API 端点测试的 CAPTCHA 解决方案实用指南,包含现实场景、工作流程建议和使用 Captcha AI 的可操作步骤。

Web 表单中 API 端点测试的 CAPTCHA 解决方案实用指南,包含现实场景、工作流程建议和使用 Captcha AI 的可操作步骤。

May 07, 2026
Tutorials 在自有 QA 中安全地缓存与复用 CAPTCHA token
在自有 QA 环境中,按 token 类型与有效期合理地缓存与复用 CAPTCHA token 的模式 — 不涉及生产令牌复用。

在自有 QA 环境中,按 token 类型与有效期合理地缓存与复用 CAPTCHA token 的模式 — 不涉及生产令牌复用。

May 01, 2026