网页爬虫浏览器控制测试【免费下载链接】puppeteer-extra Teach puppeteer new tricks through plugins.项目地址https://gitcode.com/gh_mirrors/pu/puppeteer-extra点击查看免费下载puppeteer-extra-plugin-stealth是puppeteer-extra生态中最核心的检测规避插件通过注入一系列隐身技术evasions让基于 Chromium 的无头浏览器在常见 bot 检测面前表现得与真实 Chrome 无异。本文以该插件的官方文档为主体结合仓库内 插件主入口、内置隐身技术目录 与测试脚本完整讲解安装、使用、按需定制、底层原理与效果验证方法读完即可在爬虫、自动化测试与数据采集场景中落地一套可配置的反检测方案。一、安装与依赖该插件既可以与puppeteer-extra配合使用也可以与playwright-extra配合使用二者在 package.json 中均被声明为可选的 peerDependency。单独安装插件yarn add puppeteer-extra-plugin-stealth # - or - npm install puppeteer-extra-plugin-stealth如果是首次接触puppeteer-extra插件体系一次性安装全套依赖最简单yarn add puppeteer puppeteer-extra puppeteer-extra-plugin-stealth # - or - npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealthpuppeteer-extra是puppeteer的即插即用替代品它在不改变 puppeteer 原有 API 的基础上为浏览器实例增加插件注册与生命周期能力。安装后建议阅读 puppeteer-extra 主文档 了解 Firefox 支持与其他插件的用法。二、快速上手两行代码开启全部隐身技术插件的核心设计是零配置默认值调用StealthPlugin()工厂函数并注册即默认启用全部可用 evasion 技术。// puppeteer-extra 是 puppeteer 的即插即用替代品 // 它通过插件机制增强了已安装的 puppeteer const puppeteer require(puppeteer-extra) // 添加 stealth 插件并使用默认配置即全部 evasion 技术 const StealthPlugin require(puppeteer-extra-plugin-stealth) puppeteer.use(StealthPlugin()) // 之后像使用普通 puppeteer 一样使用即可 puppeteer.launch({ headless: true }).then(async browser { console.log(Running tests..) const page await browser.newPage() await page.goto(https://bot.sannysoft.com) await page.waitForTimeout(5000) await page.screenshot({ path: testresult.png, fullPage: true }) await browser.close() console.log(All done, check the screenshot. ✨) })puppeteer-extra及其绝大多数插件都用 TypeScript 编写因此 TypeScript 用户可以直接获得完整的类型提示import puppeteer from puppeteer-extra import StealthPlugin from puppeteer-extra-plugin-stealth puppeteer .use(StealthPlugin()) .launch({ headless: true }) .then(async browser { const page await browser.newPage() await page.goto(https://bot.sannysoft.com) await page.waitForTimeout(5000) await page.screenshot({ path: stealth.png, fullPage: true }) await browser.close() })对应的类型声明可在 index.d.ts 中查看StealthPlugin继承自puppeteer-extra-plugin包的PuppeteerExtraPlugin基类并暴露defaults、availableEvasions、enabledEvasions等成员。官方文档还提供了一个基于 intoli 测试页的经典示例用于快速验证效果const puppeteer require(puppeteer-extra) // 启用带全部 evasions 的 stealth 插件 puppeteer.use(require(puppeteer-extra-plugin-stealth)()) ;(async () { // 以 headless 模式启动浏览器并创建页面 const browser await puppeteer.launch({ args: [--no-sandbox], headless: true }) const page await browser.newPage() // 导航到执行检测的测试页面 const testUrl https://intoli.com/blog/ not-possible-to-block-chrome-headless/chrome-headless-test.html await page.goto(testUrl) // 截图保存测试结果 const screenshotPath /tmp/headless-test-result.png await page.screenshot({ path: screenshotPath }) console.log(have a look at the screenshot:, screenshotPath) await browser.close() })()三、为什么需要 stealth无头浏览器的常见检测点插件文档明确指出目标网站有多种方式可以轻易识别 puppeteer 的使用其中把HeadlessChrome加进 user-agent 只是最显而易见的一种。除此之外从插件源码可以归纳出几个经典暴露面navigator.webdriver属性headless 下该属性会被设为truewindow.chrome对象缺失headful Chrome 存在chrome.app、chrome.runtime等对象而 headless 下通常不存在navigator.plugins与navigator.mimeTypes为空数组headless 下插件列表为空与真实浏览器差异明显UA 字符串含HeadlessChrome/、navigator.platform恒为宿主平台值如 LinuxWebGL 的 vendor/renderer 恒为Google Inc./Google SwiftShaderiframe.contentWindow.chrome在srcdociframe 中缺失源于 Chromium 的 puppeteer#1106 所描述的行为等。文档对该插件的定位表述是成为 puppeteer 反检测的常备伴侣并在新检测技术出现时持续补充新的 evasion。同时文档也坦诚地说明了边界——完全阻止所有 headless 检测方式几乎不可能但可以让检测变得成本高昂、误报频发从而在实际中不可行并提醒这是开发者与检测方之间的一场猫鼠游戏。四、插件架构与模块化设计从 插件主入口 的源码可以看到StealthPlugin是一个典型的PuppeteerExtraPlugin子类name为stealthdefaults中维护了全部可用 evasion 的集合availableEvasions与默认启用集合enabledEvasions默认启用全部 16 项dependencies动态生成它把每个启用的 evasion 名称映射为stealth/evasions/名称依赖交给puppeteer-extra的依赖系统按需加载只有被启用的 evasion 才会被 require从而保持模块化与效率onBrowser钩子会把浏览器实例的监听器上限提升到 30browser.setMaxListeners(30)避免多个 evasion 同时注册监听导致MaxListenersExceededWarning警告。关键的设计理念是stealth 插件本身只是一个便利包装器它自动 require 多个独立的 evasion 插件并提供默认值。文档给出了绕过主模块、单独引入某个 evasion 插件的写法// 绕过主模块直接使用某个独立的 stealth 插件 puppeteer.use( require(puppeteer-extra-plugin-stealth/evasions/console.debug)() )说明console.debug仅是官方文档 API 章节中的示意示例当前仓库 evasions 目录 中实际包含的插件以其实际列出的目录为准见下文引入时请使用实际存在的模块路径。这些 evasion 插件彼此独立、各自继承PuppeteerExtraPlugin可以脱离 stealth 主模块单独注册使用这正是插件体系即插即用的体现。五、内置隐身技术evasions全览在 插件主入口 的defaults中当前版本默认启用的 16 项 evasion 如下evasion 名称作用依据各插件源码chrome.app在 headless 下 mockwindow.chrome.app对象isInstalled、getDetails等见 chrome.app/index.jschrome.csi处理chrome.csi相关检测evasions/chrome.csi/chrome.loadTimes处理chrome.loadTimes相关检测evasions/chrome.loadTimes/chrome.runtime在安全源https上 mock 完整的chrome.runtime对象含sendMessage、connect及扩展 ID 校验逻辑见 chrome.runtime/index.jsdefaultArgs从启动参数中剥离--disable-extensions、--disable-default-apps、--disable-component-extensions-with-background-pages等暴露自动化身份的参数见 defaultArgs/index.jsiframe.contentWindow修复srcdociframe 下contentWindow.chrome缺失导致的HEADCHR_IFRAME检测见 iframe.contentWindow/index.jsmedia.codecs让 Chromium 对avc1.42E01E等专有编解码器返回probablyChromium 本身不支持专有编码仅 Chrome 支持见 media.codecs/index.jsnavigator.hardwareConcurrency将navigator.hardwareConcurrency固定为 4可通过hardwareConcurrency参数配置见 navigator.hardwareConcurrency/index.jsnavigator.languages修正navigator.languages列表evasions/navigator.languages/navigator.permissions修正权限 API 的检测差异evasions/navigator.permissions/navigator.plugins用功能性 mock 完整模拟navigator.plugins与navigator.mimeTypes二者互相引用需同时处理见 navigator.plugins/readme.mdnavigator.webdriver删除/规避navigator.webdriver属性并在启动参数中追加--disable-blink-featuresAutomationControlled见 navigator.webdriver/index.jssourceurl处理页面源码 URL 相关的暴露点evasions/sourceurl/user-agent-override以 CDPNetwork.setUserAgentOverride方式设置完整的 UA含语言、平台与 UA hints见 user-agent-override/index.jswebgl.vendor将 WebGL 的UNMASKED_VENDOR_WEBGL37445与UNMASKED_RENDERER_WEBGL37446替换为真实硬件常见值见 webgl.vendor/index.jswindow.outerdimensions修复 headless 下缺失的window.outerWidth/outerHeight与 viewportevasions/window.outerdimensions/值得一提的是evasions 目录 中还包含navigator.vendor插件用于改写navigator.vendor默认值为Google Inc.可通过vendor参数自定义但从当前主入口的defaults看它不在默认启用集合中属于可按需单独引入的独立插件。若需自定义先移除默认集合中的某项、再单独引入并配置即可具体写法见下一节。5.1 典型实现拆解navigator.webdriver 与 user-agent-overridenavigator.webdriver源码展示了两类典型手段的配合页面级在onPageCreated中通过page.evaluateOnNewDocument注入逻辑——Chrome 89 之后navigator.webdriver已是false无需处理旧版本则通过delete Object.getPrototypeOf(navigator).webdriver删除该属性启动级在beforeLaunch中向options.args追加--disable-blink-featuresAutomationControlled若已存在--disable-blink-features参数则用逗号追加从根上关闭自动化控制特性。源码注释还提到该参数在部分版本会在 Chrome 上显示使用了不受支持的命令行标志信息条Linux 下可通过写入 managed policies 配置{ CommandLineFlagSecurityWarningsEnabled: false }消除。user-agent-override源码则是当前版本中 UA 处理的核心方案值得单独说明默认取browser.userAgent()并把HeadlessChrome/替换为Chrome/maskLinux: true默认时会把 UA 括号内的平台部分替换为Windows NT 10.0; Win64; x64用于隐藏 Linux 宿主身份Android UA 因同样含Linux会被跳过同步推导navigator.platform、userAgentMetadatabrands、platform、platformVersion、architecture、model、mobile 等完整的 Client Hints 数据并通过 CDPNetwork.setUserAgentOverride一次性下发headless 模式下额外设置Accept-Language默认en-US,enheadful 模式则通过user-preferences插件写入intl.accept_languages偏好。源码注释解释了原因page.setExtraHTTPHeaders会把请求头全部转成小写可被检测而--lang启动参数并非处处可用。六、按需定制启用、禁用与参数配置6.1 通过enabledEvasions动态增删默认启用全部 evasion但可以随时按需裁剪。插件 API 提供availableEvasions与enabledEvasions两个集合属性// 获取全部可用 evasions const pluginStealth require(puppeteer-extra-plugin-stealth)() console.log(pluginStealth.availableEvasions) // 文档示例输出为 Set { user-agent, console.debug }仅为示意 puppeteer.use(pluginStealth)// 从启用集合中动态移除某项 evasion const pluginStealth require(puppeteer-extra-plugin-stealth)() pluginStealth.enabledEvasions.delete(console.debug) puppeteer.use(pluginStealth)从 插件源码 可以看到enabledEvasions本质是this.opts.enabledEvasions的读写访问器dependencies会随其变化实时重建index.test.js 中的测试用例也验证了改动enabledEvasions后 dependencies 同步更新的行为。也可以直接在构造时通过opts指定const puppeteer require(puppeteer-extra) const StealthPlugin require(puppeteer-extra-plugin-stealth) const stealth StealthPlugin({ enabledEvasions: new Set([navigator.webdriver, user-agent-override]) }) puppeteer.use(stealth)6.2 独立引入某个 evasion 并传参所有 evasion 都是独立的puppeteer-extra插件因此可以绕过主模块单独使用并传入各自的专属参数。文档与各插件 readme 提供了完整的组合示例const puppeteer require(puppeteer-extra) const StealthPlugin require(puppeteer-extra-plugin-stealth) const stealth StealthPlugin() // 先从默认集合中移除该项避免重复注册 stealth.enabledEvasions.delete(user-agent-override) puppeteer.use(stealth) // evasion 插件本身就是普通的 puppeteer-extra 插件可以直接注册 const UserAgentOverride require(puppeteer-extra-plugin-stealth/evasions/user-agent-override) // 自定义 UA 与语言环境 const ua UserAgentOverride({ userAgent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1), locale: de-DE,de }) puppeteer.use(ua)user-agent-override支持的参数见 源码注释 与 readmeuserAgentstring默认browser.userAgent()去除 Headless 部分localestring默认en-US,en同时作用于Accept-Language请求头与navigator.languagesmaskLinuxboolean默认true是否把 Linux 平台伪装为 Windows。类似的navigator.vendor插件支持vendor参数默认Google Inc.navigator.hardwareConcurrency支持hardwareConcurrency参数默认4webgl.vendor支持vendor与renderer参数默认Intel Inc.与Intel Iris OpenGL Engine。例如const puppeteer require(puppeteer-extra) const StealthPlugin require(puppeteer-extra-plugin-stealth) const stealth StealthPlugin() stealth.enabledEvasions.delete(navigator.vendor) puppeteer.use(stealth) const NavigatorVendorPlugin require(puppeteer-extra-plugin-stealth/evasions/navigator.vendor) const nvp NavigatorVendorPlugin({ vendor: Apple Computer, Inc. }) // 自定义 vendor puppeteer.use(nvp)七、底层实现原理无痕改写浏览器 API大多数 evasion 之所以能做到难以被发现依赖的是 evasions/_utils/index.js 提供的一套共享工具函数其设计目标明确写在文件头部注释中为修改原生浏览器 API 而不留痕迹而设计。几个关键机制Proxy 封装replaceWithProxy/replaceGetterWithProxy/mockWithProxy用 JS Proxy 替换目标 API如WebGLRenderingContext.prototype.getParameter、navigator原型上的 getter通过陷阱traps拦截调用并返回伪装值。工具库会在替换后同步处理两个露馅点toString伪装patchToString/redirectToString原生函数调用fn.toString()会返回function xxx() { [native code] }而 Proxy 包裹的函数会暴露差异。工具库通过缓存原生Function.prototype.toString的结果preloadCache中的nativeToStringStr把被替换函数的toString结果重定向为原生格式错误堆栈清洗stripProxyFromErrorsJS Proxy 的陷阱一旦抛错Proxy 本身会出现在错误堆栈里例如at Object.newHandler.computed [as get]。工具库用锚点行 黑名单两种策略把堆栈中与 Proxy 相关的行剥离防止检测方通过堆栈特征识破上下文传递stringifyFns/materializeFnspage.evaluateOnNewDocument的序列化机制只支持原始类型因此工具库把函数序列化为字符串传进浏览器上下文再物化执行配合 withUtils.js 对page.evaluate/page.evaluateOnNewDocument的封装让每个 evasion 都能在注入脚本里直接使用上述工具。以webgl.vendor为例源码它通过utils.replaceWithProxy分别代理WebGLRenderingContext.prototype.getParameter与WebGL2RenderingContext.prototype.getParameter当参数为37445UNMASKED_VENDOR_WEBGL或37446UNMASKED_RENDERER_WEBGL时返回自定义值其余参数照常转发给原生实现。chrome.runtime的 mock 则更逼真源码它不仅注入静态数据还完整模拟了sendMessage/connect的参数校验逻辑——例如扩展 ID 必须为 32 个字符且仅由a~p组成、参数过多或类型不符时抛出与真实 Chrome 一致的TypeError文案甚至connect失败后返回的 Port 对象含postMessage、onMessage、onDisconnect等也被逐层伪装且全部嵌套函数都经过patchToString处理。八、效果验证公开测试与对比结果8.1 官方测试脚本与结果插件仓库在 stealthtests 目录下提供了 8 个测试脚本覆盖 Chrome/Chromium × headless/headful 四种组合 × 是否启用 stealth 的交叉验证如 headless-chrome-stealth.js启动 headless Chrome、访问 bot.sannysoft.com 检测页、等待 5 秒后整页截图保存到_results目录。官方文档展示了 vanilla puppeteer 与启用 stealth 后的对比截图图片均保存在 stealthtests/_results/_thumbs以 Chromium headless 为例未启用 stealth 时检测页大面积标红暴露项多启用 stealth 插件后同一检测页面绝大多数检测项转绿官方文档对该测试的结论是启用 stealth 后可通过当时全部公开 bot 测试并注明检测站点上的MQ_SCREEN项本身存在问题普通 Chrome 也会失败。需要说明的是文档同时强调这属于一场友好的猫鼠游戏竞争——检测方仍可能有其他手段识别 headless Chromium项目会在后续版本持续跟进。8.2 对 reCAPTCHA v3 评分的间接改善官方文档还提到使用 stealth 有助于维持正常的 reCAPTCHA v3 分数原文档附有 Regular Puppeteer 与 Stealth Puppeteer 的评分对比截图。同时文档给出提醒reCAPTCHA v3 官方演示页的分数仅供粗略参考因为评分是按站点独立计算并受历史行为、IP 地址等多项因素影响属于经验性观察而非保证。若在 reCAPTCHA 处理上遇到问题官方建议关注同仓库的 recaptcha 插件。九、版本演进速览由于 changelog 的自动化尚未覆盖 markdown 文档官方文档中的 changelog 以手动维护为主并提示最新动态以公告渠道为准。从文档可梳理出几个关键节点v2.4.7新增user-agent-override用更可靠的方式设置 UA、语言与平台修复此前通过请求拦截设置Accept-Language的问题新增navigator.vendornavigator.webdriver改用 ES6 Proxy 以通过instanceof检测移除已过时的user-agent、accept-language两项 evasion。v2.4.2/v2.4.1iframe.contentWindow改为代理原始 window 对象并智能重定向暴露身份的调用accept-language支持自定义 locale通过 headless-cat-n-mouse 测试。v2.4.0所有 evasion 增加独立的 before/after 测试新增media.codecs伪装专有编解码器支持修复srcdociframe 检测且不破坏 reCAPTCHA 弹窗等场景新增accept-language正确大小写的Accept-Language头chrome.runtime的 mock 更完整当时 fpscanner、intoli 与 areyouheadless 测试全部通过。v2.1.2navigator.plugins完整模拟插件与 MIME 类型新增webgl.vendor与window.outerdimensions修复navigator.webdriver应返回undefined而非false的细节。从当前仓库的 package.json 看插件版本为2.11.2依赖puppeteer-extra-plugin^3.2.3与puppeteer-extra-plugin-user-preferences^2.4.1运行时要求 Node 8。十、注意事项与使用边界避免与page.setUserAgent()混用user-agent-override的文档明确指出如果在业务代码里调用 puppeteer 的page.setUserAgent()会重置插件设置好的语言与平台值破坏伪装一致性参数传递的序列化限制注入脚本只能携带原始类型数据这是_utils中stringifyFns/materializeFns存在的原因自定义 evasion 时需遵循同样的约定runOnInsecureOrigins等高级开关chrome.runtime插件默认只在 https安全源下 mockchrome.runtime其defaults中暴露了runOnInsecureOrigins: false配置可在测试等场景按需覆盖声明与边界文档明确无法百分百阻止所有 headless 检测该插件的目标是让检测成本显著上升、误报增多直至实际不可行。本文所有功能描述均以当前仓库源码与文档为准不构成对任何检测站点结果的保证。十一、如何贡献新的 evasion文档欢迎以 PR 方式贡献新的 evasion 技术并建议以 evasions/_template 目录为模板起步——该模板是一个最小化的PuppeteerExtraPlugin子类骨架本身不启用仅供复制参考开发者复制该目录即可快速搭建新的独立 evasion 插件。仓库 readme.md 也再次确认了绕过主模块、单独 require 特定 evasion的用法。Licensepuppeteer-extra-plugin-stealth遵循 MIT License版权归 berstend 所有Copyright © 2018 - 2023。赞分享网页爬虫浏览器控制测试【免费下载链接】puppeteer-extra Teach puppeteer new tricks through plugins.项目地址https://gitcode.com/gh_mirrors/pu/puppeteer-extra点击查看免费下载相关推荐puppeteer-extra-plugin-stealth 反检测插件解析navigator.hardwareConcurrency 硬件并发数伪装原理与实战puppeteer extra plugin stealth 反检测插件解析navigator.hardwareConcurrency 硬件并发数伪装原理与实网页爬虫浏览器控制测试puppeteer-extra无头模式增强stealth插件如何模拟真实用户行为puppeteer extra无头模式增强stealth插件如何模拟真实用户行为 你是否曾遇到过这样的困境使用Puppeteer的无头模式Headless网页爬虫浏览器控制测试终极指南如何使用puppeteer-extra插件实现网页自动化反检测终极指南如何使用puppeteer extra插件实现网页自动化反检测 想要在网页自动化中绕过反爬虫检测puppeteer extra插件是您的最佳选择?网页爬虫浏览器控制测试创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考