反检测浏览器内核实战:ruyipage / DrissionPage / camoufox / CloakBrowser

前言

在 cookie 池架构里,思路是「真浏览器采放行 cookie → curl_cffi 同出口 IP + 同指纹回放」。
浏览器内核负责过质询、拿真实会话,回放侧用 curl_cffiimpersonate 复刻内核的 TLS/JA3 指纹。
不同防护(Cloudflare / Akamai / PerimeterX / Imperva 等)对内核的要求差异很大,选错内核直接卡死。

本文把项目里在用的四个内核 —— ruyipage / DrissionPage(dp) / camoufox(官方 + 三方 fork)/ CloakBrowser ——
的原生用法与工程封装用法整理清楚,并给出选型顺序和回放侧指纹对齐表。

环境说明:全部跑在 conda 的 py310 环境
C:/Users/YanchuangJin/miniforge3/envs/py310/python.exe,装了 ruyipage / camoufox / cloakbrowser / curl_cffi / DrissionPage)。

四内核速览

内核 基座 反检测强度 典型能解 回放 impersonate
DrissionPage (dp) 本机 Chrome ★★☆☆☆(CDP 可被检测) 静默 JS 挑战 chrome150(对齐本机 Chrome 大版本)
ruyipage Firefox 151 ★★★☆☆ CF Managed/Turnstile、Fastly、Akamai 部分 firefox151
camoufox 反检测 Firefox ★★★★☆ CF 自适应 JA3 严格质询(onbuy) firefox* + 采集时实际 UA
CloakBrowser 隐身 Chromium ★★★★★(击败 CDP 检测) Chrome 类站点最硬的一档 chrome146(免费版)

升级顺序:Chrome 类站点被拦 → dp → cloak;Firefox 类质询更硬 → ruyipage → camoufox

工程上四者统一为同一个后端接口(spiders/cookie_pool/backends/):

1
2
3
4
5
6
7
8
9
10
# backends/__init__.py
def get_backend(name):
if name in ("cloak", "cloakbrowser"): ...
if name == "ruyipage": ...
if name in ("drissionpage", "dp"): ...
if name == "camoufox": ...

# 每个后端模块只暴露两个函数:
# available() -> bool 当前环境能否用
# async fetch(**kw) -> dict 返回 {cookies, ua, blocked, block_marker, ready, page_len}

站点接入只需在 SiteConfig 里写 backend="ruyipage" / "camoufox" / …,通常不改实现代码


1. DrissionPage(dp)—— 驱动本机 Chrome

最轻量:直接驱动本机已安装的 Chrome(实测 Chrome 150.0.7871.47),适合「必须真实本机 Chrome 环境」的静默 JS 挑战。
缺点是走 CDP,指纹上能被检测出自动化(Chrome 类硬站会被 Access Denied,此时升级到 CloakBrowser)。

原生用法

1
2
3
4
5
6
7
8
9
10
11
12
from DrissionPage import ChromiumPage, ChromiumOptions

co = ChromiumOptions()
co.set_paths(local_port=9222, user_data_path=r"D:\tmp\dp_profile",
browser_path=r"C:\Program Files\Google\Chrome\Application\chrome.exe")
co.headless(True) # 4.x;3.x 是 set_headless(True)
co.no_imgs(True) # 4.x;3.x 是 set_no_imgs(True)

page = ChromiumPage(co) # 用位置参数,3.x/4.x 通用
page.get("https://example.com")
cookies = page.cookies(all_domains=True) # 4.x;3.x 是 page.get_cookies(as_dict=True, all_domains=True)
page.quit()

DrissionPage 3.x / 4.x 接口差异(项目里用 shim 抹平)

py310 装的是 3.2.30、系统 Python 是 4.1.1.4,两版接口不兼容,工程里在 _dp_core.py 统一:

操作 3.x 4.x
headless set_headless(on) headless(on)
禁图 set_no_imgs(on) no_imgs(on)
取 cookie page.get_cookies(as_dict=True, all_domains=True) page.cookies(all_domains=True)(由 property 变 method)
构造首参 addr_driver_opts addr_or_opts
  • 构造统一用位置参数 ChromiumPage(co);路径统一走 set_paths(local_port=, user_data_path=, browser_path=)
  • 认证代理走本机中继 spiders/common/browser_proxy.configure_chromium_proxy
    —— Chrome 137+ 不再支持账密代理直连,必须本地起中继。
  • 坑:① 控制台 GBK 编码不能 print ✓/✗,输出用 ASCII;② 3.x 关浏览器时 _recv_loop 会打一条
    JSONDecodeError(CDP websocket 收到空消息),是 teardown 噪音、不影响结果。

工程后端只需:backend="drissionpage"(别名 dp)。


2. ruyipage —— Firefox 151 指纹内核

深度打补丁的 Firefox 151,支持智能指纹(geo 探测 + fpfile 注入 + BiDi 仿真),
静默 JS 挑战(浏览器自动 reload 就过,无验证码)和 CF Managed/Turnstile 都能处理。

查 API 首选本地 METADATA(含完整中文示例,别凭记忆):
.../envs/py310/Lib/site-packages/ruyipage-1.2.43.dist-info/METADATA
与 PyPI 发布页 https://pypi.org/project/ruyipage/

原生用法(手动 profile + 代理 + fpfile)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from ruyipage import FirefoxOptions, FirefoxPage
from ruyipage._runtime.installer import get_executable_path

opts = FirefoxOptions()
opts.set_browser_path(get_executable_path())
opts.set_pref("permissions.default.image", 2) # 禁图
opts.headless(True)
opts.set_profile(r"D:\tmp\ruyi_profile") # 独立 profile = 每次全新会话
opts.set_proxy("http://host:port")
# 账密代理:写 fpfile 里的 httpauth.username/password,走 BiDi 自动应答 407
with open("fp.txt", "w") as f:
f.write("httpauth.username:USER\nhttpauth.password:PWD\n")
opts.set_fpfile("fp.txt")

page = FirefoxPage(opts)
page.get("https://target.com", timeout=60)
html = page.html
cookies = page.cookies(as_dict=False)
page.quit(force=True)

智能指纹一站式(geo 敏感站必备)

数据中心代理地理不固定时,出口 IP 的国家/时区要和浏览器指纹对齐,否则 Akamai 之类会在搜索页弹挑战。
apply_smart_fingerprint 经代理做一次 geo 查询,自动对齐 locale / timezone / geolocation:

1
2
3
4
5
6
7
8
9
from ruyipage import apply_smart_fingerprint
fp_ctx = apply_smart_fingerprint(
opts, proxy_host=host, proxy_port=port, proxy_user=u, proxy_pwd=p,
require_country=None, # 对齐 IP 实际国家即可,不强制某国(否则 CountryMismatchError)
userdir=profile_dir,
fpfile_name="ruyi_fp.txt",
)
page = FirefoxPage(opts)
fp_ctx.apply_emulation(page, set_geolocation=True, set_locale=True, set_timezone=True)

工程实战里的几个关键坑(_ruyi_core.py

  • 每次采集用独立临时 profile,用完删:ruyipage 自建的临时 profile 「通常」才清理、不保证,长跑会在 C 盘堆积。
  • fpfile 必须落在本次唯一 profile 目录内:多分片并行时若共用固定路径,两进程会互相覆盖代理凭据 → 407。
  • 强杀 Firefox 进程树page.quit() 只 terminate 启动器(geckodriver),不杀 Firefox 子进程
    —— Windows 杀父不杀子,每次残留一组 firefox.exe。用本次唯一 profile 目录名精准定位进程树 kill。
  • CF 质询框在跨源独立 context,不在 document.querySelectorAll('iframe') 里;必须走
    browsingContext.getTree(BiDi)检测,再交 handle_cloudflare_challenge 处理。
  • 锁 UA 不抖动:复制包内 fingerprints.jsonfirefox_minor_jitter 锁成 [0]
    让采集端 UA 恒为 151,和回放 curl_cffi firefox151 精确对齐。

工程后端:backend="ruyipage"(或 turnstile = ruyipage + CF Managed 处理)。


3. camoufox —— 反检测 Firefox(官方 + 三方 fork)

对 Firefox 深度打补丁、不注入 JS 即可改指纹,比 ruyipage/invisible 更「像真人」。
onbuy 的 Cloudflare 自适应 JA3 严格质询就是靠它解的(ruyipage 被升级成交互式解不出、dp 的 JA3 curl 又回放不了)。

3.1 官方版(pip)

1
2
pip install "camoufox[geoip]"       # geoip extra 会带本地 mmdb
python -m camoufox fetch # 下载浏览器二进制(官方 FF135,约 700MB)
1
2
3
4
5
6
7
8
9
from camoufox.async_api import AsyncCamoufox   # 同步版:from camoufox.sync_api import Camoufox

async with AsyncCamoufox(headless=True, humanize=True,
geoip=True, locale="en-US") as browser:
page = await browser.new_page()
await page.goto("https://target.com", wait_until="domcontentloaded")
html = await page.content()
jar = {c["name"]: c["value"] for c in await page.context.cookies()}
ua = await page.evaluate("navigator.userAgent")

geoip 三态(关键):

  • geoip=True:经出口探测 api.ipify.org 得真实 IP 再本地查地理。出口能自由访问 ipify 时用它
  • geoip="209.146.101.43":直接对指定 IP 做本地 mmdb 查询,跳过被墙 / 被拦的 ipify(推荐做法)。
  • geoip=False:不做地理对齐(指纹可能不一致,触发风控)。

WebRTC 处理(重要,SOCKS 代理场景防真实 IP 泄漏):

1
2
3
4
5
6
7
8
9
Camoufox(
proxy={"server": "socks5://127.0.0.1:1080"},
block_webrtc=True, # 禁 WebRTC,防 UDP 泄漏真实 IP
firefox_user_prefs={ # 或强制 WebRTC 只走代理(更接近整机 VPN)
"media.peerconnection.ice.proxy_only": True,
"media.peerconnection.ice.default_address_only": True,
"network.proxy.socks_remote_dns": True,
},
)

实测:SOCKS 只代理 TCP,Firefox 的 WebRTC(UDP) 不走 SOCKS 会泄漏真实 IP、与出口不一致 → 触发 Akamai 行为质询。
block_webrtc=True 能消除泄漏;但要 WebRTC 真报代理 IP(PDP 那种更严检测),需整机 TUN 模式(Clash/sing-box)而非浏览器代理。

3.2 ⚠️ playwright 版本必须钉 1.51.0

camoufox(FF135)**必须搭 playwright==1.51.0**:

1
2
pip install "playwright==1.51.0"
# camoufox 用自己 fetch 的浏览器,无需 playwright install firefox

用 1.60 打开会报 JS 错的真实站点会崩:Page.goto: Connection closed while reading from the driver
stderr 顶部是 Node 崩溃横幅。根因:camoufox FF135 的 juggler 发的 pageerror 事件没有 location 字段,
而 playwright 1.60 的 driver 去读 pageError.location.url → TypeError → 整个 Node driver 崩。

Windows 上跑 camoufox/playwright 前必须
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()),否则起子进程 NotImplementedError

3.3 三方 fork(coryking/camoufox)+ 自定义构建

官方内核只到 FF135;要更高版本(FF142 / FF150)的反检测构建,用三方 fork:

1
pip install "git+https://github.com/coryking/camoufox.git@v142.0.1-fork.27#subdirectory=pythonlib"

配合自编译的全隐身内核,用 executable_path 直接指到 camoufox.exe

1
2
3
4
5
6
7
8
9
10
11
12
13
from camoufox.sync_api import Camoufox
from camoufox.addons import DefaultAddons

with Camoufox(
executable_path=r"C:\...\camoufox150_build\camoufox.exe",
os="windows", ff_version=150,
humanize=True, geoip=True, locale=["en-US", "en"],
window=(1366, 768),
exclude_addons=[DefaultAddons.UBO],
i_know_what_im_doing=True, # 用自定义 executable_path 必须加
) as b:
page = b.new_page(no_viewport=True) # no_viewport 避开新版 playwright 传 isMobile 与旧内核不匹配
page.goto("https://target.com")
  • 覆盖 camoufox pathAppData\Local\camoufox\camoufox\Cache)成 fork 内核后,需补 version.json
    (release 落在 [beta.19, 1) 区间才 is_supported)。
  • Linux 无 X 环境用 headless="virtual"(自带 Xvfb 真实渲染,无 headless 特征),需先 apt install xvfb

3.4 回放侧的坑:每会话随机 UA

camoufox 每个会话随机 UA,所以回放必须用采集时的实际 UA(不能硬编码):采集后回传
navigator.userAgent,消费端 consumer.sessionentry["ua"]curl_cffi 的请求头,
impersonatefirefox* 对齐 JA3。

工程后端:backend="camoufox"


4. CloakBrowser —— 反检测最强的隐身 Chromium

源码级指纹补丁的隐身 Chromium:击败 CDP 检测、无 headless 泄漏、Windows 原生 GPU 直通、过 incognito 检测
(”passes every bot detection test”)。实测反检测强度最高 —— bloomingdales 的 Akamai 上,它是唯一能拿到
真实首页(1.58MB)的内核(dp/普通 Chrome 被 Access Denied、ruyipage/invisible/camoufox 卡 sec-cpt 行为质询)。

1
2
3
pip install -U cloakbrowser        # 实测 0.4.9
# 免费版内核 Chrome146;Pro 版 Chrome148 + 最新反爬补丁(cloakbrowser.dev 7 天试用)
# 首次 launch 自动拉内核二进制;启动会打印 free-tier banner(stdout 噪音,无害)

原生用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from cloakbrowser import launch_async
from tools.trans_proxy import proxy_to_playwright

browser = await launch_async(
proxy=proxy_to_playwright("http://user:pwd@host:port"), # None=直连
headless=False,
humanize=True,
geoip=True, # 有代理时按出口 IP 地理对齐指纹(CloakBrowser 自带)
args=['--blink-settings=imagesEnabled=false'], # 禁图
)
ctx = await browser.new_context()
page = await ctx.new_page()
await page.goto("https://target.com", wait_until="domcontentloaded", timeout=120000)
html = await page.content()
jar = {c["name"]: c["value"] for c in await page.context.cookies()}
await browser.close()
  • 回放 curl_cffi 用 **chrome146**(对齐免费版内核大版本;Pro 版对齐 chrome148)。
  • 限制:CloakBrowser 也解不了 bloomingdales 深层页(search/PDP)的 Akamai 硬拒 —— 它只放行首页,
    这是站点策略层面的(非内核能解)。

工程后端:backend="cloak"(别名 cloakbrowser)。


5. 回放侧指纹对齐(curl_cffi)

内核采完 cookie,回放要用 curl_cffi 复刻同一内核的 TLS/JA3 指纹,否则同 IP 同 cookie 也会被拦:

采集内核 回放 impersonate
ruyipage (FF151) firefox151
camoufox (FF135/自定义) firefox* + 采集时实际 UA
DrissionPage (本机 Chrome150) chrome150
CloakBrowser (免费 Chrome146) chrome146

本地装的是 KingJem 自编译的 curl_cffi fork(curl-impersonate + curl_cffi 0.15.5),
chrome141-150(无 147)/ firefox144-153 / brave 等新指纹;标准版 curl_cffi 没有这些。
部署前先探测目标机器有没有这个 fork,否则回放报 ImpersonateError

6. 选型决策

  1. 先按防护类型定基座:Chrome 类站点走 dp/cloak;Firefox 更能过的质询走 ruyipage/camoufox。
  2. 按被拦程度升级
    • Chrome 侧:dp(本机 Chrome)→ cloak(隐身 Chromium)
    • Firefox 侧:ruyipage(FF151)→ camoufox(反检测 FF,含 fork)
  3. geo 敏感站:数据中心代理务必开 geoip 对齐(camoufox geoip=;ruyipage apply_smart_fingerprint)。
  4. 代理下防 WebRTC 泄漏:camoufox block_webrtc / ice.proxy_only;要过最严的 PDP 需整机 TUN 路由。
  5. 回放对齐指纹与 UA:impersonate 对齐内核大版本;camoufox 还要带采集时的实际 UA。

这套内核 + 回放的组合,覆盖了项目里绝大多数受反爬保护的零售站点;剩下极少数(如 bloomingdales 深层页)
是站点策略层面的硬拒,非换内核能解,需换数据源或真人桌面 + 整机 TUN 环境。


反检测浏览器内核实战:ruyipage / DrissionPage / camoufox / CloakBrowser
https://kingjem.github.io/2026/07/10/browser-kernels-guide/
作者
Ruhai
发布于
2026年7月10日
许可协议