基于cef和chromium的浏览器集群
背景
在JS动态加载遍地都是的现在,通用爬虫系统离不开强大的浏览器集群。市面上有诸多关于selenium和puppeteer操纵浏览器进行爬取的教程。但是随着反爬技术的发展,selenium的特征很容易被检测,这里有一些相关的讨论:Can a website detect when you are using selenium with chromedriver? 。当然清除selenium特征,或者篡改检测的代码也是一种应对策略。除了自动化测试流派,是否还有其他操纵浏览器的方式呢?本文提出基于CEF(Chromium Embedded Framework)和Chromium,定制一套专业的爬虫浏览器环境,并工程化为浏览器集群。
Chromium
反爬技术中的浏览器指纹,即获取浏览器具有辨识度的独一无二的特征,计算出值来作为浏览器的标识,正在被广泛使用。(Cross-)Browser Fingerprinting via OS and Hardware Level Features 这篇论文讲述了一些通过操作系统和硬件层面对浏览器信息进行收集和比对的方式。
Chromium是一个开源浏览器项目,相比Chrome浏览器,其开源属性让我们有了修改和定制浏览器的机会,以规避基于浏览器指纹的反爬,增加专属于爬虫的功能。
CEF
CEF是支持在其他应用中嵌入Chromium浏览器的框架,提供了丰富的接口以操纵浏览器。这里主要介绍下CEF的编译和二次开发。
编译
注:以下编译是在Windows x64环境下进行的。
推荐使用已编译好内核的libcef,选择Standard Distribution。另外,还需要下载一款跨平台的编译辅助工具CMake,选择Windows win64-x64 Installer。最后当然还得下载个Visual Studio 2019,需要安装的组件有Windows 10 SDK、MSBuild、用于Windows的C++ CMake工具。
准备完这些之后,先打开cmake-gui,where is source code选择cef_binary所在的文件夹,where to build the binaries在cef_binary里边新建一个build目录,总体如下图所示。

点击Configure,按下图配置,并点击Finish。

正常会出现下图的提示。

接着点击Generate即可。
在build文件夹,用Visual Studio打开cef.sln文件。
接下来我们编译最简单的示例代码cefsimple。首先将cefsimple设为启动项目,然后在菜单栏生成里边点击生成cefsimple。

不出意外就能在cef_binary\build\tests\cefsimple\Debug文件夹里找到编译完的cefsimple。
浏览器集群

上面这张图当年只画了方向,确实有点烂尾。这里补一个我最近在跑的真实项目:energycrawler。
EnergyCrawler:把浏览器真正做成“集群”(实践补完)
上面这张图我当年只讲了思路,没讲落地。后来在 energycrawler 里我把这套东西跑起来了,重点不是“怎么爬一页”,而是“怎么管理一批浏览器节点”。
我一开始踩的坑也很典型:浏览器只是工具进程,任务一多就互相污染;一个节点抖了,整批任务卡住。后面改成三层以后,才稳定下来:
-
调度层(管任务和槽位)
CrawlerManager负责队列、worker、起停和重试(api/services/crawler_manager.py)。
每个任务分配独立ENERGYCRAWLER_BROWSER_ID,把“任务”和“浏览器会话”绑定,避免 cookie / localStorage / 签名状态串号。 -
浏览器服务层(把 CEF 当节点来管)
energy-service/main.go把 CEF 能力封成 gRPC 服务,Python 侧通过energy_client/client.py调CreateBrowser / Navigate / ExecuteJS / SetProxy。
这一步最关键:浏览器不再是“脚本里的临时对象”,而是可调度、可复用、可替换的节点。 -
执行层(业务 crawler)
任务进程从main.py进入平台 crawler。以小红书为例,签名走XHSEnergyAdapter(media_platform/xhs/energy_client_adapter.py),抓取逻辑在media_platform/xhs/core.py,数据落到store/xhs/_store_impl.py。
围绕“集群”这个主题,真正有价值的是这几件事:
- 节点隔离:并发任务时每个 worker 用独立 browser session。
- 节点稳定:签名层做缓存、状态保存和失败重试(
media_platform/xhs/signature_state.py)。 - 任务恢复:分页进度写 checkpoint,中断后续跑(
tools/crawl_checkpoint.py)。 - 集群可观测:关键链路统一事件日志,API 可看任务和节点状态(
tools/utils.py+api/routers/crawler.py)。
所以回头看,CEF/Chromium 只是底座;“浏览器集群”真正的工程难点,是调度、隔离、恢复和监控这四件事。