跳转至

爬虫工程:反检测、IP 池、覆盖率

更新日期:2026-04-26

时效性提醒

本页涉及 Cloudflare 风控版本号、residential IP 商家定价、curl-impersonate 支持的浏览器版本等数据,截至 2025/early 2026 公开信息。CF 风控月级别更新,定价季度变化 —— 上线前 sanity-check 一遍。

预训练数据的"原料层"几乎全部依赖爬虫。Common Crawl 给一个免费基线(每月 ~3-5 PB 压缩),但只覆盖前 N 万站点的浅层,长尾、私域、JS-rendered SPA、被 CF 挡住的高质量站点完全不在内。自建爬虫不是"为了不付钱",是为了拿 CC 拿不到的内容。


一、爬虫架构总览

flowchart LR
    seed["种子 URL 池<br/>(sitemap, top-1M, 手工)"] --> sched["调度器<br/>(URL 去重 + 优先级)"]
    sched --> fetch["抓取层<br/>(IP 池 + UA 池 + headless)"]
    fetch --> classify{"是 HTML?"}
    classify -- 是 --> extract["内容提取<br/>(trafilatura)"]
    classify -- 否 --> store["原始入库"]
    extract --> store
    store --> linker["新链接发现<br/>(回填 sched)"]
    linker --> sched

    classDef pool fill:#f5f3eb,stroke:#bdb9ab,color:#1a1a1a;
    classDef op fill:#fff,stroke:#cc785c,color:#1a1a1a;
    class seed,store pool
    class sched,fetch,classify,extract,linker op

工业级开源参考:

  • Scrapy(Python)—— 通用框架,写定制 spider 主流
  • browsertrix-crawler(webrecorder.io)—— 容器化、WACZ 输出、原生支持 JS 渲染
  • Apache Nutch(Java)—— 老牌分布式,CC 早期用过
  • Crawl4AI / Firecrawl —— 2024+ 新一代,主打 LLM-friendly 输出
  • cc-pyspark —— 在 Spark 上处理 Common Crawl WARC 的范式

二、反检测对抗

爬虫被反爬挡住,问题层次从底到顶:网络层 → TLS 层 → HTTP 层 → 浏览器指纹层 → 行为层 → ML 评分层。任何一层穿不过都会被 challenge / block。

2.1 Cloudflare 风控全景

CF 是 web 抓取的最大对手。当前公开档:

等级 名称 触发条件 绕过难度
免费 Bot Fight Mode UA、navigator.webdriver、IP reputation 综合打分 低 — TLS 伪装 + 干净 IP 即可
免费 Managed Challenge 高于阈值时显示 5-10s 等待页 中 — 需要执行 JS challenge(Turnstile token 生成)
付费 Pro Turnstile(替代 hCaptcha) 嵌入式无感验证,行为信号 + 浏览器指纹 高 — 需要真实浏览器 + 行为模拟
付费 Enterprise Bot Management ML 模型实时评分(0-100),可定制规则 极高 — 通常只能换 IP / 换站

实操要点: - Bot Fight Mode 是 CF 站点默认开启的最低门槛,2024 年起 navigator.webdriver / Headless Chrome 默认指纹直接被识别 - Turnstile 看似无感,背后做 ~30-50 个浏览器 API 探针 + cursor 轨迹 + 时序熵;纯 puppeteer/playwright 几乎必死,需 stealth 插件 + 真实浏览器内核 - 2025 年起 CF 加强了 HTTP/2 fingerprint 检测(pseudo-header 顺序、SETTINGS frame 内容),单独伪装 TLS 不够

2.2 TLS 指纹(JA3 / JA4 / JA4+)

每次 TLS 握手时,client 发的 ClientHello 包里有:cipher suite 顺序、extension 顺序、curve 列表、ALPN、signature algorithms 等 ~10 个字段。Python requests / httpx 的指纹Chrome / Firefox 不同;CF 等中间件可以从 ClientHello 直接判断"这是个机器人"。

  • JA3(2017,Salesforce 提出):5 个字段拼接 → MD5 → 32 字符指纹。Python requests 默认 JA3 全网共识,秒识别
  • JA4 / JA4+(FoxIO 2023):JA3 升级版,分多个独立维度(JA4 = TLS Client,JA4S = TLS Server,JA4H = HTTP),更细致、更难规避
  • HTTP/2 fingerprint(Akamai 提出格式):SETTINGS / WINDOW_UPDATE / HEADERS frame 顺序

绕过工具链

工具 语言 怎么做 状态
curl-impersonate(lwthiker) C fork curl + 改 SSL 库(BoringSSL/NSS)暴露 cipher 顺序,原生发出 Chrome/Firefox/Safari 的 ClientHello 维护中,覆盖到最新 Chrome stable
curl_cffi(yifeikong) Python curl-impersonate 的 Python 绑定 + requests 风格 API 主流选择
tls-client(bogdanfinn) Go 改 Go crypto/tls 库 量大爬虫常用
noble-tls / rebrowser Node Node 端方案 较新
# curl_cffi 用法 — 最常见的 Python 反 TLS 指纹方案
from curl_cffi import requests

# impersonate Chrome 124+ 的完整 TLS + HTTP/2 指纹
resp = requests.get(
    "https://target.com",
    impersonate="chrome",   # 也可指定 chrome120 / safari17_0 等
    proxies={"http": "http://...", "https": "http://..."},
)

2.3 浏览器指纹(Canvas / WebGL / Audio / 字体)

跨过 TLS 还有 客户端 JS 指纹

维度 怎么取 区分度
Canvas fingerprint <canvas> 渲染特定图,读 PNG 哈希 GPU + 字体决定,跨设备熵 ~15 bit
WebGL fingerprint getParameter(UNMASKED_RENDERER) 显卡型号字符串,区分度高
AudioContext fingerprint OfflineAudioContext 处理已知波形,读输出 CPU + audio stack,~10 bit
Font enumeration Canvas measureText 多种字体看渲染差异 系统字体集
navigator.webdriver / .plugins 直接读属性 Headless Chrome 默认 webdriver=true最低门槛信号
Battery / Permissions / Sensors API 调对应 API 看响应 Headless 通常 throw

对抗思路

  • puppeteer-extra-plugin-stealth —— 现在事实标准,monkey-patch 上述所有信号
  • undetected-chromedriver —— Selenium 系的 stealth 实现
  • playwright-stealth —— Playwright 端口
  • rebrowser-patches —— 2024 出现,patch Chromium DevTools Protocol 的 Runtime.callFunctionOn 泄露
  • Browserless / Bright Data Scraping Browser —— 付费托管 + 内置 stealth

真理:每加一个 stealth patch,反爬服务(DataDome、PerimeterX、Akamai Bot Manager)也加一条对应检测。这是 cat-and-mouse,没有"一劳永逸"的方案。最稳的姿势是真实浏览器 + 真实物理设备 + 真实用户使用模式录制 + 用 CDP 操控,但成本与维护极高。

2.4 行为信号

ML 反爬看的是 整段会话 的统计:

  • 鼠标轨迹(贝塞尔曲线 vs 直线、加速度)
  • 点击间隔时序(正常人 200-2000ms,机器 <50ms 或恒定 500ms)
  • 滚动速度 / 页面停留 / focus event
  • 是否触发 mousemovetouchstart(移动端)
  • 表单填写是否一次性 paste(机器)vs 逐字符 keystroke(人)

工业级爬虫会在 puppeteer 里模拟人类轨迹(基于真实用户录制的轨迹库)。开源参考:ghost-cursorbezier-mouse


三、IP 池工程

抓数百万站点必然要 IP 池。三个等级:

类型 来源 单 GB 成本(2025 估算) 干净度 适用
Datacenter IP AWS / GCP / DigitalOcean <$0.5 低(IP range 在 spamhaus / abuseipdb) 抓低风控站、测试
ISP Proxies Datacenter 但 ASN 标 ISP $1-3 中风控站,性价比好
Residential IP 真实家庭宽带(合规通过 SDK 联运) $5-15 CF / DataDome 站
Mobile IP 4G/5G LTE proxy 设备机柜 $20-50 极高(多设备共享 NAT,反查极难) 最难爬的反爬站、移动端 API

主流商家(2025 公开报价):

  • Bright Data(前 Luminati)—— 行业最大,residential ~$8/GB(pay-as-you-go),合规最完整
  • IPRoyal —— residential ~$3.5/GB,性价比好,社区评价稳
  • Smartproxy / Decodo(rebrand 2024)—— ~$4-7/GB
  • Oxylabs —— Bright Data 主要竞争,定价相近
  • Webshare —— datacenter + ISP 价格屠夫,~$0.1-1/GB
  • MobileSoax / Proxy-Cheap / 自建 4G modem 农场

策略

# IP 轮换不是越频繁越好 — CF 等风控会从"短时间内多 IP 同 cookie/UA"识别
# 最佳实践: 每个 session 绑定一个 IP,session 内保持,session 切换时切 IP

class StickyIPSession:
    def __init__(self, proxy_pool):
        self.pool = proxy_pool

    def new_session(self, ttl=600):  # 10 分钟黏一个 IP
        ip = self.pool.acquire()
        return Session(proxy=ip, ttl=ttl)

合规警告:residential / mobile IP 涉及真实用户网络。绝对不能 用于扫描登录、爆破、抓敏感个人数据。商家合同会列禁止用途,违反会被 ban + 法律风险。预训练数据采集做公开 web 内容是合规边界内的灰区,私域抓取 / 登录抓取要单独考虑(见 private-domain)。


四、蜜罐识别

反爬一招:放正常用户看不见、爬虫会跟的链接,链一中即识别。

常见模式:

<!-- 1. CSS 隐藏 -->
<a href="/admin/honey" style="display:none">click</a>
<a href="/track/bot-123" style="visibility:hidden">x</a>

<!-- 2. 视觉外置 -->
<a href="/trap" style="position:absolute; left:-9999px">x</a>

<!-- 3. 颜色伪装 -->
<a href="/trap" style="color:white; background:white">.</a>

<!-- 4. 0×0 -->
<a href="/trap" style="width:0; height:0; overflow:hidden">x</a>

<!-- 5. 表单蜜罐字段(常见反垃圾) -->
<form>
  <input name="email" required>
  <input name="email_confirm" style="display:none"><!-- 机器会填,正常用户看不见 -->
</form>

爬虫规避:

  • link extractor 加 CSS 检查 — 跑无头浏览器解析时,对每个 <a>getComputedStyle 检查 visibility / display / opacity / 尺寸;过滤不可见链接
  • 跳过 rel="nofollow" —— 站方明确不希望机器跟,遵守
  • robots.txt 真心遵守 —— 蜜罐路径常列在 robots Disallow,反向利用:robots Disallow 的 url 群里大概率有蜜罐
  • 避开 honeypot URL pattern —— /wp-admin/honey-*/track/*-bot-*/secret/* 等公开蜜罐路径库可订阅(Project Honeypot

五、爬虫覆盖率测量

业务方反复问的:"你爬了多少?覆盖了多少?" 没法直接答,要分维度:

5.1 覆盖率定义

维度 怎么测
URL 数 显然,但 1 亿 URL 不一定比 1000 万好(重复 / 低质)
域名数 唯一 ETLD+1(example.com)数,去掉 subdomain
语言覆盖 按 fasttext lid 标分语言后,与目标语言能力需求对比
主题覆盖 用 LDA / 文本嵌入聚类,看主题分布是否长尾
新鲜度 抓取时间分布,3 个月内占比
HTML 渲染需求 需要 JS 才能拿到内容的占比

5.2 与 Google 索引的差距

Google 索引规模:公开估计 400-500B 个 URL(2024,Google 自己未公布精确数)。Common Crawl 单 snapshot ~3-5B URL,全部 snapshot 累计 ~250B URL(去重前)。Common Crawl 大概覆盖 Google 的 ½ 量级,但因为:

  • 不抓 JS-only SPA 内容
  • 不抓登录后页面
  • robots.txt 严格遵守,错过 ~10-20% 高质量站
  • 不抓 PDF / video transcripts / image OCR

可用文本量 上估计只有 Google 实际索引文本的 20-30%。这是为什么 frontier lab 都自己再爬一遍。

5.3 漏抓识别

实操:

# 用 Wayback Machine 的 CDX API 反查目标域名,看 archive 上有但你没抓的
# 例: https://web.archive.org/cdx/search/cdx?url=example.com/*&output=json
# 对比你的 db: 算覆盖率 = 你的 / Wayback's

# 同样可以用 Common Crawl Index (https://index.commoncrawl.org)
# CC index 是免费的,按 URL prefix 查询

更系统的:自己维护 种子 URL 大全(domains lists、search engine query 反推、社交网络 share URL pool 等),定期 cross-check。


六、实操栈(参考 LLM 预训练)

任务 工具
通用 spider Scrapy + curl_cffi 后端(替换默认 downloader)
JS 渲染需求 playwright + playwright-stealth + 家用 IP
反 CF 重型 Bright Data Scraping Browser / Browserless / 自建 puppeteer + stealth + mobile IP
URL 调度 Redis + 自定义优先级队列;亿级 URL 上 Apache Nutch 或自研
内容提取 trafilatura(详见 parser
输出存储 WARC 文件(与 CC 兼容)+ ParquetDataset 二级索引
监控 Prometheus + Grafana:成功率 / 平均响应时间 / IP 报废率 / per-domain 限速

七、追问延伸

问题 方向 详见
私域数据(CSDN / Reddit / Twitter)怎么搞? 各自反爬强度不同,CSDN 中等、Reddit 有公开 API + 第三方 dump、Twitter 已切 X.com 几乎不可爬 private-domain
爬完之后怎么 parser? trafilatura 默认够用,复杂站点 per-domain 自定义 parser
直接用 Common Crawl 不就行了? CC 是基线,频率每月一次,长尾 / SPA / 登录后内容 CC 没有 archives
不想自爬,找供应商? Together / Datology / HuggingFace 等卖打包好的语料 vendors

参考链接


上级 · B1. 预训练数据 Pipeline:爬取→清洗→去重→过滤→配比