爬虫工程:反检测、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
- 是否触发
mousemove、touchstart(移动端) - 表单填写是否一次性 paste(机器)vs 逐字符 keystroke(人)
工业级爬虫会在 puppeteer 里模拟人类轨迹(基于真实用户录制的轨迹库)。开源参考:ghost-cursor、bezier-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
- Mobile:Soax / 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 |
参考链接¶
- scrapfly.io 反爬技术博客 — 工业最新对抗实践
- curl-impersonate repo — TLS 伪装基础
- curl_cffi — Python 主流绑定
- puppeteer-extra-plugin-stealth — 浏览器 stealth 标准
- Project Honeypot — 蜜罐 URL 数据库
- Common Crawl Index — 免费 URL 索引查询
- JA4+ 规范 — 现代 TLS 指纹