网络爬虫中的CAPTCHA处理

CAPTCHA类型,比解决更加有效的预防策略,以及代理在CAPTCHA避免中的关键作用. 用于检测和路由的代码示例.

网络爬虫中的CAPTCHA处理

为什么CAPTCHAs 是史克威尔最大的障碍

CAPTCHA存在以区分人类和bots,它们对此越来越有效. 当您的刮刮器遇到CAPTCHA时,这意味着目标站点已经检测到自动化行为——您的请求频率太高,IP信任度低,或者您的浏览器指纹看起来可疑. 最佳的CAPTCHA战略是预防而不是解决.

本指南涵盖了您将遇到的CAPTCHA类型,为什么预防比解决更有效、更便宜,以及代理如何在完全避免CAPTCHA方面发挥关键作用。

这篇文章是我们 完整网页搜索代理指南 丛书。 关于了解探测系统,见 反毒系统如何检测代理。 。 。

2026年CAPTCHA类型

类型如何运作绕行困难
reCAPTCHA v2(复选框)点击“ 我不是机器人” + 可选图像挑战中型
reCAPTCHA v3(隐形)没有用户互动的分数行为 0.0-1.0
h Captcha (美国)图像选择挑战( 类似于 reCAPTCHA v2)中型
云浮转弯浏览器挑战, 通常是隐形的
自定义图像 CAPTCHAs特定地点的挑战(扭曲文本、谜题)变量
工作证明浏览器必须计算散列( Cloudflare Under attack)中型

隐形CAPTCHA 真正的威胁

最危险的CAPTCHA是那些你从未见过的。 (原始内容存档于2019-03-03). reCAPTCHA v3云浮转弯 在背景中运行,分析鼠标运动,滚动行为,打字模式,以及浏览器环境. 它们在不显示任何挑战的情况下分配一个信任分数——如果分数过低,则请求会静默地被阻断或重定向.

预防与解决:为什么预防胜利

方针每笔费用速度可靠性可缩放性
预防(没有触发CAPTCHA)0美元 (单位:美元)即时最高不错
CAPTCHA 解决服务每1 000美元-3美元10-60秒85-95% (单位:千美元)中调
基于AI的自动解析每1 000美元2-5美元5-30秒70%-90%有限
在规模上,预防既节省金钱又节省时间。 每天解决10万个CAPTCHA需要100-500美元,并增加休息时间。 防止它们除了适当的代理和请求管理之外,别无其他代价。

预防战略1:使用高质量的住宅代用品

一项最有效的CAPTCHA预防措施是使用信任率高的住宅代管。 住宅IP是由ISP分配给真实家庭的,因此网站无法轻易区分您的请求与真实用户流量.

import requests
# Residential proxy — high trust score, fewer CAPTCHAs
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
def scrape_with_residential(url: str) -> str:
    """Use residential proxies to avoid triggering CAPTCHAs."""
    session = requests.Session()
    session.proxies = {"http": PROXY, "https": PROXY}
    session.headers.update({
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/120.0.0.0 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
        "Accept-Encoding": "gzip, deflate, br",
    })
    resp = session.get(url, timeout=30)
    return resp.text

ProxyHat的住宅池提供来自真实的ISP的IP. 190多个国家,给予每个请求最高的信任分。 见 住宅对数据中心 详细比较一下

预防战略2:实事求是的要求模式

CAPTCHA经常由机器人行为模式引发,而不仅仅是IP的声誉. 让你的刮刀看起来像人:

Python 执行

import requests
import random
import time
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
USER_AGENTS = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 Safari/605.1.15",
]
REFERRERS = [
    "https://www.google.com/",
    "https://www.bing.com/",
    "https://duckduckgo.com/",
    None,  # Direct visit
]
def human_like_scrape(urls: list[str]) -> list[str]:
    """Scrape with realistic human behavior patterns."""
    results = []
    session = requests.Session()
    session.proxies = {"http": PROXY, "https": PROXY}
    for url in urls:
        # Randomize headers per request
        headers = {
            "User-Agent": random.choice(USER_AGENTS),
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Language": "en-US,en;q=0.9",
            "Accept-Encoding": "gzip, deflate, br",
            "Connection": "keep-alive",
            "Upgrade-Insecure-Requests": "1",
        }
        referrer = random.choice(REFERRERS)
        if referrer:
            headers["Referer"] = referrer
        try:
            resp = session.get(url, headers=headers, timeout=30)
            results.append(resp.text)
        except requests.RequestException:
            results.append(None)
        # Human-like delays: 1-5 seconds with occasional longer pauses
        if random.random() < 0.1:
            time.sleep(random.uniform(5, 15))  # 10% chance of long pause
        else:
            time.sleep(random.uniform(1, 4))
    return results

节点.js 执行

const HttpsProxyAgent = require('https-proxy-agent');
const fetch = require('node-fetch');
const agent = new HttpsProxyAgent('http://USERNAME:PASSWORD@gate.proxyhat.com:8080');
const USER_AGENTS = [
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36',
  'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
];
function randomDelay() {
  const isLongPause = Math.random() < 0.1;
  const ms = isLongPause
    ? 5000 + Math.random() * 10000
    : 1000 + Math.random() * 3000;
  return new Promise(r => setTimeout(r, ms));
}
async function humanLikeScrape(urls) {
  const results = [];
  for (const url of urls) {
    const headers = {
      'User-Agent': USER_AGENTS[Math.floor(Math.random() * USER_AGENTS.length)],
      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
      'Accept-Language': 'en-US,en;q=0.9',
    };
    try {
      const res = await fetch(url, { agent, headers, timeout: 30000 });
      results.push(await res.text());
    } catch {
      results.push(null);
    }
    await randomDelay();
  }
  return results;
}

预防战略3:聪明的知识产权轮换

您旋转IP的方式直接影响 CAPTCHA 费率 。 主动旋转(每个请求新IP)实际上可以增加一些站点的CAPTCHA,因为访问同一会话路径的不同IP的一系列请求看起来很可疑.

import requests
import uuid
def create_session_for_site(site_id: str):
    """Create a sticky session that maintains the same IP per site.
    This avoids the suspicious pattern of different IPs accessing the same flow."""
    session_id = uuid.uuid5(uuid.NAMESPACE_URL, site_id).hex[:8]
    proxy = f"http://USERNAME-session-{session_id}:PASSWORD@gate.proxyhat.com:8080"
    session = requests.Session()
    session.proxies = {"http": proxy, "https": proxy}
    return session
# Same IP for all requests to a specific product section
session = create_session_for_site("example.com-electronics")
page1 = session.get("https://example.com/electronics?page=1")
page2 = session.get("https://example.com/electronics?page=2")
page3 = session.get("https://example.com/electronics?page=3")
# Different IP for a different section
session2 = create_session_for_site("example.com-clothing")
clothes1 = session2.get("https://example.com/clothing?page=1")

关于更多的旋转模式,见 大型碎屑代用旋转策略。 。 。

预防战略4:尊重率限制

CAPTCHA往往是利率限制之后的升级. 如果正确处理速率限制信号,则很少看到CAPTCHAs:

import requests
import time
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
CAPTCHA_INDICATORS = [
    "captcha",
    "recaptcha",
    "hcaptcha",
    "challenge",
    "verify you are human",
    "please complete the security check",
]
def is_captcha_page(html: str) -> bool:
    """Detect if the response is a CAPTCHA challenge page."""
    html_lower = html.lower()
    return any(indicator in html_lower for indicator in CAPTCHA_INDICATORS)
def scrape_with_captcha_detection(urls: list[str]) -> list[dict]:
    results = []
    session = requests.Session()
    session.proxies = {"http": PROXY, "https": PROXY}
    captcha_count = 0
    backoff = 2.0
    for url in urls:
        try:
            resp = session.get(url, timeout=30)
            if resp.status_code == 200 and not is_captcha_page(resp.text):
                results.append({"url": url, "status": "success", "body": resp.text})
                captcha_count = 0
                backoff = max(backoff * 0.9, 1.0)  # Reduce backoff on success
            elif is_captcha_page(resp.text) or resp.status_code == 403:
                captcha_count += 1
                results.append({"url": url, "status": "captcha"})
                if captcha_count >= 3:
                    # Too many CAPTCHAs — increase backoff significantly
                    backoff = min(backoff * 3, 60)
                    print(f"CAPTCHA streak: {captcha_count}. Backing off to {backoff:.0f}s")
                else:
                    backoff = min(backoff * 1.5, 30)
        except requests.RequestException as e:
            results.append({"url": url, "status": "error", "error": str(e)})
        time.sleep(backoff)
    return results

综合税率限制战略见 速率限制解释。 。 。

当您必须处理 CAPTCHA : 检测和运行

即使有完美的预防,一些CAPTCHA也是不可避免的. 在您的管道中建立检测功能, 这样您就可以通过 CAPTCHA 页面进行特殊处理 :

import requests
from enum import Enum
PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
class ResponseType(Enum):
    SUCCESS = "success"
    CAPTCHA = "captcha"
    BLOCKED = "blocked"
    ERROR = "error"
def classify_response(resp: requests.Response) -> ResponseType:
    """Classify a response to determine next action."""
    if resp.status_code == 403:
        return ResponseType.BLOCKED
    if resp.status_code == 429:
        return ResponseType.BLOCKED
    if resp.status_code == 200:
        html = resp.text.lower()
        captcha_signals = ["captcha", "recaptcha", "hcaptcha", "cf-challenge"]
        if any(s in html for s in captcha_signals):
            return ResponseType.CAPTCHA
        return ResponseType.SUCCESS
    return ResponseType.ERROR
def scrape_with_routing(urls: list[str]) -> dict:
    """Scrape URLs and route based on response classification."""
    session = requests.Session()
    session.proxies = {"http": PROXY, "https": PROXY}
    results = {"success": [], "captcha": [], "blocked": [], "error": []}
    for url in urls:
        try:
            resp = session.get(url, timeout=30)
            response_type = classify_response(resp)
            results[response_type.value].append(url)
            if response_type == ResponseType.CAPTCHA:
                # Route to CAPTCHA queue for manual or service-based solving
                print(f"CAPTCHA detected: {url}")
            elif response_type == ResponseType.BLOCKED:
                # Rotate IP and retry
                print(f"Blocked: {url}")
        except requests.RequestException:
            results["error"].append(url)
    print(f"Success: {len(results['success'])}, "
          f"CAPTCHAs: {len(results['captcha'])}, "
          f"Blocked: {len(results['blocked'])}")
    return results

CAPTCHA 预防清单

  • 使用住宅代理. 他们的信用分数最高 引发的CAPTCHA最少. 代理哈特住宅代理 提供数百万个干净的IP.
  • 设定现实的页眉 。 总是发送用户代理,接受,接受-语言,以及其他标准浏览器头.
  • 加上人类般的延迟. 请求之间随机1-5秒的延迟,偶尔会有较长的暂停.
  • 正确维持会话 通过粘度会话对相关请求使用 cookie 和一致的IP.
  • 敬重机器人. txt. (中文(简体) ). 检测机器人.txt违规的站点升级为CAPTCHA更快.
  • 监测CAPTCHA的费率。 如果你的CAPTCHA率超过5%, 你的方法中的东西需要修复。
  • 避免在高峰时段刮刮。 反机器人系统在高流量期间更具攻击性.
  • 正确旋转用户代理 。 使用最近现实的浏览器字符串 。 在同一会话上不要混合移动和桌面 UA 。

关于您首选语言的代理设置,请参见 在 Python 中使用代理, (中文). 使用节点中的代理,或 使用 Go 中的代理探索 网页搜索的代理用户名 开始吧

经常被问到的问题

代理可以帮助避免CAPTCHAs吗?

是的,相当重要。 优质住宅代理拥有干净的IP声誉,很少触发CAPTCHA. Datacenter IP更常被标记,因为它们是已知的自动化源. 住宅代用品与适当要求模式相结合,几乎消除了大多数目标的CAPTCHA。

什么是最便宜的方法 处理CAPTCHA的规模?

预防。 投资住宅代用品和适当报废模式的成本远低于CAPTCHA规模的解决服务. 如果您必须解决CAPTCHA,第三方服务费用为每1000美元1-3美元,但每个请求增加10-60秒的延迟.

无头浏览器是否帮助 CAPTCHA ?

它们通过JavaScript执行提供真实的浏览器环境来帮助隐形CAPTCHAs(reCAPTCHA v3,Turnstile). 然而,它们的速度较慢,而且资源更密集。 仅用于特定需要浏览器级验证的目标.

我怎么知道我是否有CAPTCHA的页面?

请检查access-date=中的日期值 (帮助) CAPTCHA指标的响应HTML:"captcha","captcha","hcaptcha","挑战",或"验证你是人类". 同时注意403个出乎意料的反应,并重新定向以挑战URL. 将自动探测器安装到您的刮刮管道中。

为什么我仍然得到 CAPTCHA 与住宅代理?

通常是因为请求模式,而不是IP质量. 常见原因:每分钟请求过多,浏览器头缺失,饼干处理问题,或刮刮模式过于系统化. 慢下来, 添加焦躁, 并且对相关请求使用粘度会话 。

准备开始了吗?

通过AI过滤访问148多个国家的5000多万个住宅IP。

查看价格住宅代理
← 返回博客