news 2026/3/30 6:45:09

【DrissionPage源码-1】dp和selenium的异同

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【DrissionPage源码-1】dp和selenium的异同

一、selenium架构详解/为什么多了一层

核心问题:为什么说 Selenium “多了一层”?

让我们先对比 CDP 和 Selenium 的架构:

CDP 架构(2 层)

Python 代码 ↓ WebSocket(直连) Chrome 浏览器

Selenium 架构(3 层,Selenium 3)

Python 代码 ↓ HTTP chromedriver(中间层!) ↓ CDP Chrome 浏览器

关键区别:Selenium 多了chromedriver这一层!


Selenium WebDriver 完整架构(Selenium 3)

┌─────────────────────────────────────────────────────────┐ │ 第 1 层:Client Library │ │ (Python, Java, C#, etc.) │ │ │ │ from selenium import webdriver │ │ driver = webdriver.Chrome() │ │ driver.get('https://example.com') │ └────────────────────┬────────────────────────────────────┘ │ │ JSON Wire Protocol over HTTP │ (REST API 调用) │ ▼ ┌─────────────────────────────────────────────────────────┐ │ 第 2 层:Browser Driver(中间层) │ │ (chromedriver, geckodriver, etc.) │ │ │ │ - 接收 HTTP 请求 │ │ - 解析 JSON 命令 │ │ - 转换为浏览器特定的命令 │ │ - 内部使用 CDP/DevTools 与浏览器通信 │ └────────────────────┬────────────────────────────────────┘ │ │ CDP (Chrome DevTools Protocol) │ 或其他浏览器原生协议 │ ▼ ┌─────────────────────────────────────────────────────────┐ │ 第 3 层:Real Browser │ │ (Chrome, Firefox, Safari, etc.) │ │ │ │ - 真实的浏览器实例 │ │ - 执行 DOM 操作、JS 代码等 │ └─────────────────────────────────────────────────────────┘

详细解析每一层

第 1 层:Selenium Client Library

这是你写的 Python/Java 代码:

fromseleniumimportwebdriver# 创建 driver 实例driver=webdriver.Chrome()# 执行操作driver.get('https://www.baidu.com')element=driver.find_element('id','kw')element.send_keys('hello')element.submit()

功能

  • 提供面向对象的 API
  • 将你的命令转换为 HTTP 请求
  • 支持多种语言(Python, Java, C#, Ruby, JavaScript)

第 2 层:Browser Driver(关键的"中间层")

这是chromedriver.exegeckodriver.exe等独立的可执行文件。

为什么需要这一层?

历史原因

  • Selenium 最初设计时,浏览器还没有标准化的自动化协议
  • 每个浏览器的内部机制不同(Chrome 用 CDP,Firefox 用 Marionette)
  • Selenium 需要一个"翻译层"来统一这些差异
chromedriver 的工作流程
# 当你执行这行代码driver.get('https://www.baidu.com')# 实际发生的事情:

1. Client Library → chromedriver(HTTP 请求)

POST http://localhost:9515/session/xxx/url HTTP/1.1 Content-Type: application/json { "url": "https://www.baidu.com" }

2. chromedriver 内部(解析 + 转换)

// chromedriver 收到 JSON 请求// 解析命令:"navigate to URL"// 转换为 CDP 命令// 通过 CDP 发送到 Chrome:{"id":1,"method":"Page.navigate","params":{"url":"https://www.baidu.com"}}

3. chromedriver → Chrome(CDP WebSocket)

chromedriver 内部维护了一个到 Chrome 的 WebSocket 连接,使用 CDP 协议通信。

4. Chrome 执行 → 返回结果

Chrome 导航到页面后,通过 CDP 返回结果:

{"id":1,"result":{"frameId":"xxx","loaderId":"yyy"}}

5. chromedriver → Client(HTTP 响应)

HTTP/1.1 200 OK Content-Type: application/json { "status": 0, "value": null }

为什么 Selenium 比 CDP 慢?

正是因为这个"中间层"!

性能对比

操作CDP (直连)Selenium (3 层)
通信路径Python → ChromePython → chromedriver → Chrome
协议转换0 次2 次(JSON Wire ↔ CDP)
网络开销1 次 WebSocket2 次(HTTP + WebSocket)
延迟~5ms~15-30ms

实际测试

importtime# CDP (Playwright)fromplaywright.sync_apiimportsync_playwright start=time.time()withsync_playwright()asp:browser=p.chromium.launch()page=browser.new_page()page.goto('https://www.baidu.com')print(f'CDP:{time.time()-start:.2f}s')# ~0.5s# Seleniumfromseleniumimportwebdriver start=time.time()driver=webdriver.Chrome()driver.get('https://www.baidu.com')print(f'Selenium:{time.time()-start:.2f}s')# ~1.2s

Selenium 4 的改进

Selenium 4 移除了 JSON Wire Protocol,直接使用W3C WebDriver Protocol

Selenium 3: Client → JSON Wire → chromedriver → CDP → Chrome (自定义协议) Selenium 4: Client → W3C WebDriver → chromedriver → CDP → Chrome (标准化协议,更快)

改进

  • 标准化通信协议(W3C 标准)
  • 更好的跨浏览器兼容性
  • 稍微提升了性能(但仍然慢于直接 CDP)

chromedriver 的内部实现(C++ 源码)

chromedriver 是开源的,位于 Chromium 仓库中:

// chromium/src/chrome/test/chromedriver/server/http_handler.ccvoidHttpHandler::HandleRequest(constHttpRequest&request,HttpResponse*response){// 1. 解析 HTTP 请求std::string method=request.method;std::string path=request.path;std::string body=request.body;// 2. 根据 WebDriver 命令分发if(path=="/session"){CreateSession(body,response);}elseif(path.find("/url")!=std::string::npos){Navigate(body,response);}// ... 其他命令}voidHttpHandler::Navigate(conststd::string&body,HttpResponse*response){// 3. 解析 JSONbase::Value parsed=base::JSONReader::Read(body);std::string url=parsed.FindKey("url")->GetString();// 4. 转换为 CDP 命令base::Value cdp_command;cdp_command.SetKey("method","Page.navigate");cdp_command.SetKey("params",base::Value::Dict().Set("url",url));// 5. 通过 DevToolsClient 发送到 Chromedevtools_client_->SendCommand(cdp_command);// 6. 等待响应并返回// ...}

关键文件

  • chrome/test/chromedriver/server/- HTTP 服务器
  • chrome/test/chromedriver/chrome/- CDP 客户端
  • chrome/test/chromedriver/commands.cc- 命令实现

为什么不能去掉 chromedriver?

你可能会问:既然 chromedriver 内部用的是 CDP,为什么不直接用 CDP?

Selenium 的优势(尽管慢)

  1. 跨浏览器统一接口
    • 一套代码支持 Chrome、Firefox、Safari、Edge
    • 不需要关心底层协议差异
  2. W3C 标准
    • WebDriver 是 W3C 官方标准
    • 大量工具和生态支持
  3. 历史兼容性
    • 海量现有代码和教程
    • 企业级稳定性

CDP 的优势(为什么更快)

  1. 直连
    • 没有中间层
    • 减少协议转换开销
  2. 完整功能
    • CDP 提供比 WebDriver 更多的功能
    • 网络拦截、性能监控、覆盖率等
  3. 原生性能
    • Chrome 官方协议
    • 最优化的通信

总结对比

CDP(DrissionPage, Playwright, Puppeteer)

┌──────────┐ │ Python │ └────┬─────┘ │ WebSocket (直连) ▼ ┌──────────┐ │ Chrome │ └──────────┘

Selenium

┌──────────┐ │ Python │ └────┬─────┘ │ HTTP ▼ ┌──────────┐ │chromedriver│ ← 多了这一层! └────┬─────┘ │ CDP ▼ ┌──────────┐ │ Chrome │ └──────────┘

二、selenium和drissionpage 相比多了哪些风险点

Selenium 的检测风险主要源于它必须遵守W3C WebDriver 标准,以及它为了实现跨浏览器控制而引入的中间层(ChromeDriver)特征

相比 DrissionPage,Selenium多了以下几个致命的风险监测点:


1. 致命特征:navigator.webdriver

这是最基础也是最直接的检测点。

  • Selenium:
    根据 W3C 协议规定,凡是通过 WebDriver 控制的浏览器,必须将 navigator.webdriver 属性设为 true。
    • 风险: 网站 JS 只需要一行代码 if (navigator.webdriver) { 杀无赦 }。虽然可以通过 JS 注入去修改它,但在 Selenium 中,页面加载和 JS 注入之间存在时间差(Race Condition),在页面初始化的瞬间(Script Execution Start),这个值为 true,极易被捕捉。
  • DrissionPage:
    由于它直接通过 CDP 的 Page.addScriptToEvaluateOnNewDocument 在页面加载注入 JS,它可以完美地将这个值设为 undefined,让网页完全感知不到。

2. 源代码特征:CDC 变量 (CDC_xxxxxxxx)

这是 Selenium(特指 ChromeDriver)独有的深层特征。

  • Selenium:
    ChromeDriver 为了在浏览器内部执行 JavaScript 并与外部通信,会在浏览器的 JS 上下文中注入特定的全局变量。最著名的就是以cdc<fontstyle="color:rgb(26,28,30);"></font><fontstyle="color:rgb(26,28,30);">开头的变量(例如</font><fontstyle="color:rgb(26,28,30);"></font>cdc_<font style="color:rgb(26, 28, 30);"> </font><font style="color:rgb(26, 28, 30);">开头的变量(例如</font><font style="color:rgb(26, 28, 30);"> </font>cdc<fontstyle="color:rgb(26,28,30);"></font><fontstyle="color:rgb(26,28,30);">开头的变量(例如</font><fontstyle="color:rgb(26,28,30);"></font>cdc_asdjflasutopfhvcZLmcfl_)。
    • 风险: 高级反爬虫(如 Akamai, Cloudflare)会扫描 window 对象下的属性。如果发现了cdc<fontstyle="color:rgb(26,28,30);"></font><fontstyle="color:rgb(26,28,30);">或</font><fontstyle="color:rgb(26,28,30);"></font>cdc_<font style="color:rgb(26, 28, 30);"> </font><font style="color:rgb(26, 28, 30);">或</font><font style="color:rgb(26, 28, 30);"> </font>cdc<fontstyle="color:rgb(26,28,30);"></font><fontstyle="color:rgb(26,28,30);"></font><fontstyle="color:rgb(26,28,30);"></font>wdc_ 开头的变量,直接判定为 Selenium。
    • 补救困难: 除非你用 16 进制编辑器修改 chromedriver.exe 二进制文件中的字符串,否则很难去除。
  • DrissionPage:
    完全没有这个问题。因为它不使用 ChromeDriver,是通过 WebSocket 发送纯 CDP 指令,不需要在 JS 上下文里塞这种“联络暗号”。

3. 命令执行差异:isTrusted 事件属性

这涉及到模拟点击和按键的真实性。

  • Selenium:
    Selenium 的 click() 或 send_keys() 生成的事件,虽然现在的 Driver 已经做得很好,但在某些复杂的 JS 验证下,生成的 Event 对象中的 isTrusted 属性可能表现异常,或者缺少某些物理硬件关联的属性(如 pointerId, pressure 等)。
  • DrissionPage:
    它提供了两种模式:
    • 浏览器模拟: 通过 CDP 的 Input.dispatchMouseEvent,这和 Selenium 类似,有一定风险。
    • 更底层的控制: 它更容易结合 Python 的系统级输入库,或者通过 CDP 构建更完美的事件链,甚至通过“接管模式”让用户手动操作过验证码,程序接管后续流程。

4. 浏览器的“纯净度”与启动参数

  • Selenium:
    默认情况下,Selenium 每次启动都是一个新的、干净的浏览器实例(临时 Profile)。
    • 风险: 没有历史记录、没有缓存、没有 Cookie、Local Storage 为空。这种“白板”浏览器在风控系统眼里非常可疑(像是刚出生的婴儿却在做复杂操作)。
    • 此外,Selenium 启动时默认带有大量特征参数,如 –enable-automation, –test-type。
  • DrissionPage:
    • 非常擅长接管模式。你可以先手动打开一个浏览器(积累了正常的用户行为、缓存、Cookie),然后 DrissionPage 通过端口连上去。
    • 优势: 在这种情况下,你的浏览器指纹是完美的真实用户指纹,Selenium 很难做到如此丝滑的接管。

5. 通信时序(Timing Attack)

我们在上一节讨论过架构差异,这直接导致了时序特征。

  • Selenium:
    Python -> HTTP -> ChromeDriver -> CDP -> Chrome。
    • 风险: 这种长链路导致命令执行有固定的延迟模式(RTT)。某些高阶反爬(如瑞数)会统计你的 JS 执行时间、鼠标移动轨迹的采样率。如果发现操作之间有极其稳定的“机器延迟”,就会触发风控。(不确定真假,ai 给的-
  • DrissionPage:
    Python -> WebSocket -> Chrome。
    • 优势: 通信延迟极低,并发能力强。你可以编写更复杂的鼠标轨迹算法,以极高的频率发送 CDP 包来模拟人类的抖动和变速,这在 Selenium 中因为 HTTP 瓶颈很难做到。

6. User-Agent 和 Headless 特征

虽然两者都可以改 UA,但 Selenium 在 Headless(无头)模式下的特征暴露得更彻底。

  • Selenium:
    早期版本在 Headless 模式下,User-Agent 会包含 HeadlessChrome 字样。虽然现在可以改,但配合 navigator.plugins(无插件)、navigator.languages(语言单一)等特征,极易被识别。
  • DrissionPage:
    它封装了很多便捷的配置(如 Stealth 模式),自动帮你处理了 Headless 模式下的很多特征(自动补全插件列表、语言、WebGL 指纹噪声等),而 Selenium 原生是不管这些的,需要你自己写大量的 execute_script 去补。

总结表格

检测点Selenium (WebDriver)DrissionPage (CDP)风险等级 (Selenium)
Navigator.webdriver强制为 true (极难修改)可设为 undefined🔴 极高
JS 注入变量 ($cdc_)存在 (需修改二进制去除)不存在🔴 极高
启动参数默认含 –enable-automation可完全自定义/无自动化Flag🟠 高
时序特征HTTP 延迟大,操作僵硬WebSocket 低延迟,更拟人🟠 高
接管现有浏览器困难 (需特定配置)原生支持,极简🟡 中
浏览器指纹默认“白板”环境易继承真实环境🟡 中

结论:
Selenium 的风险在于**“它太标准了”。它是为了测试而生的,所以它诚实地告诉浏览器“我是机器人”。而 DrissionPage 是为了自动化(和爬虫)而生的,它的设计初衷就是“控制”而非“测试”**,所以它避开了那些自我暴露的协议规范。

更多文章,敬请关注gzh:零基础爬虫第一天

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/29 0:01:36

【DrissionPage源码-2】dp如何控制浏览器

接上篇&#xff0c;来实验一下只用pythoncdp 启动操作浏览器 一、python 实现cdp控制浏览器--remote-debugging-port9222 --remote-allow-origins*// 必须添加 --remote-allow-origins* 参数&#xff08;或者指定具体来源&#xff09;&#xff0c;否则 Python 脚本通过 WebSock…

作者头像 李华
网站建设 2026/3/27 23:01:56

如何用PaddlePaddle实现图像分割任务?U-Net实战教学

如何用PaddlePaddle实现图像分割任务&#xff1f;U-Net实战教学 在医学影像诊断、工业质检或遥感分析中&#xff0c;我们常常需要精确识别图像中的特定区域——比如肿瘤边界、裂缝位置或植被覆盖范围。传统方法依赖人工标注和规则提取&#xff0c;效率低且泛化能力差。而如今&a…

作者头像 李华
网站建设 2026/3/28 4:01:54

Minecraft跨平台存档转换终极指南:Chunker让游戏世界无缝衔接

Minecraft跨平台存档转换终极指南&#xff1a;Chunker让游戏世界无缝衔接 【免费下载链接】Chunker Convert Minecraft worlds between Java Edition and Bedrock Edition 项目地址: https://gitcode.com/gh_mirrors/chu/Chunker 还在为不同设备间的Minecraft存档无法互…

作者头像 李华
网站建设 2026/3/25 3:14:35

3步解锁键盘潜能:从普通用户到效率大师的终极指南

3步解锁键盘潜能&#xff1a;从普通用户到效率大师的终极指南 【免费下载链接】kmonad An advanced keyboard manager 项目地址: https://gitcode.com/gh_mirrors/km/kmonad 你是否曾因频繁切换Escape键而感到手指疲惫&#xff1f;是否觉得Caps Lock键占据了宝贵的位置却…

作者头像 李华
网站建设 2026/3/25 10:31:02

FastDFS-Client 终极使用指南:轻松构建分布式文件存储系统

在当今大数据时代&#xff0c;如何高效存储和管理海量文件成为每个开发者必须面对的挑战。FastDFS-Client作为Java平台上的分布式文件系统客户端&#xff0c;提供了简单易用的API接口&#xff0c;让开发者能够快速集成高性能的文件存储解决方案。 【免费下载链接】FastDFS_Clie…

作者头像 李华
网站建设 2026/3/27 10:16:31

Weblate术语库管理实战指南:从问题诊断到精准解决方案

Weblate术语库管理实战指南&#xff1a;从问题诊断到精准解决方案 【免费下载链接】weblate Web based localization tool with tight version control integration. 项目地址: https://gitcode.com/gh_mirrors/we/weblate Weblate作为基于Web的本地化工具&#xff0c;其…

作者头像 李华