资讯动态

puppeteer-extra 插件 block-resources 实战:按资源类型动态拦截与放行网络请求

发布时间:2026/10/15 11:34:03 来源:尧图企业网站定制
网页爬虫浏览器控制测试【免费下载链接】puppeteer-extra Teach puppeteer new tricks through plugins.项目地址https://gitcode.com/gh_mirrors/pu/puppeteer-extra点击查看免费下载本文围绕 puppeteer-extra 生态中的puppeteer-extra-plugin-block-resources插件展开它借助 puppeteer 的请求拦截能力按资源类型图片、样式表、脚本、媒体等精准屏蔽页面加载的次要资源支持在运行时动态增删拦截类型适用于爬虫提速、省流量、去广告图片、加速首屏渲染等场景。读完本文你将掌握该插件的安装方式、两种配置用法静态配置 运行时动态切换、13 种可拦截资源类型的完整清单以及其底层拦截实现原理与协作式拦截优先级的使用方法。插件定位为 puppeteer 加上按类型断流能力puppeteer-extra-plugin-block-resources是 puppeteer-extra 插件生态中的一员位于仓库 packages/puppeteer-extra-plugin-block-resources 目录包名puppeteer-extra-plugin-block-resources。它的核心能力在包描述中写得非常直白Block resources (images, media, etc.) in puppeteer.即在 puppeteer 中屏蔽图片、媒体等资源。它的完整特性由源码 JSDocindex.js给出支持所有资源类型从document到websocket共 13 种类型均可被拦截拦截可动态切换不必在启动前写死配置运行中随时通过add/delete增删要屏蔽的类型。典型应用场景包括抓取页面时屏蔽图片、字体、媒体等非必要资源显著降低带宽与耗时只关心 DOM 结构与脚本执行屏蔽 CSS 以加速渲染屏蔽 faviconother类型、弹窗广告图片等干扰资源与puppeteer-extra生态其他插件如 stealth、adblocker组合使用构建更完整的自动化浏览器方案。安装与依赖该插件通过 npm/yarn 安装详见 readme 与 package.jsonyarn add puppeteer-extra-plugin-block-resources # 或 npm i puppeteer-extra-plugin-block-resources从 package.json 可以看出它的依赖关系运行时依赖puppeteer-extra-plugin^3.2.3提供PuppeteerExtraPlugin基类和debug^4.1.1提供调试日志peer 依赖puppeteer-extra可选作为插件宿主框架开发依赖puppeteer^2.0.0、ava2.4.0测试框架、npm-run-all。注意要真正使用它你还需要在项目中安装puppeteer或puppeteer-core与puppeteer-extra本身。另外从实现细节看下文会展开插件拦截逻辑依赖 puppeteer 的**协作式拦截Cooperative Intercept Mode**相关 API因此建议在较新版本的 puppeteer 上使用以完整发挥拦截能力。快速上手一次配置全局生效最简单的方式是在注册插件时通过opts一次性指定要屏蔽的类型readme 中的官方示例const { DEFAULT_INTERCEPT_RESOLUTION_PRIORITY } require(puppeteer) const puppeteer require(puppeteer-extra) puppeteer.use(require(puppeteer-extra-plugin-block-resources)({ blockedTypes: new Set([image, stylesheet]), // 可选启用 Cooperative Mode支持多个请求拦截器协同工作 interceptResolutionPriority: DEFAULT_INTERCEPT_RESOLUTION_PRIORITY }))这段代码做了三件事require(puppeteer-extra-plugin-block-resources)拿到的是一个工厂函数调用它传入配置对象返回插件实例puppeteer.use(...)把插件注册进 puppeteer-extra之后每次puppeteer.launch()创建的浏览器、每个新页面都会自动带上拦截逻辑blockedTypes: new Set([image, stylesheet])声明屏蔽图片与样式表两种资源。注册完成后页面中的所有图片和 CSS 请求都会被直接中止abort页面 DOM 与脚本仍正常加载。API 详解一个构造函数、两个 Set、一个优先级该插件的公开 API 非常精简完整定义见 readme 与 TypeScript 声明文件 index.d.ts。Plugin 构造函数Plugin继承自PuppeteerExtraPlugin基类类型为function (opts)接受一个可选配置对象默认{}配置项类型默认值含义opts.blockedTypesSetstring空Set默认不拦截任何类型指定要屏蔽的 resourceTypesopts.interceptResolutionPrioritynumberundefined协作式拦截的解析优先级可选对应源码中defaultsgetterindex.jsget defaults() { return { availableTypes: new Set([ document, stylesheet, image, media, font, script, texttrack, xhr, fetch, eventsource, websocket, manifest, other ]), // Block nothing by default blockedTypes: new Set([]), interceptResolutionPriority: undefined } }值得一提的实现细节基类PuppeteerExtraPlugin的构造函数会用merge-deep把插件defaults与用户传入的opts深度合并合并结果通过this.opts访问见 packages/puppeteer-extra-plugin/src/index.ts。因此blockedTypes如果没传就会被defaults中的空Set兜底保证插件默认什么都不拦、随时可以开拦的语义。availableTypes获取全部可拦截的资源类型get availableTypes() { return this.defaults.availableTypes }availableTypes是一个只读 getterindex.js返回全部 13 种可用资源类型类型为Setstringdocument,stylesheet,image,media,font,script,texttrack,xhr,fetch,eventsource,websocket,manifest,otherblockedTypes读取/修改当前屏蔽集合get blockedTypes() { return this.opts.blockedTypes }blockedTypesindex.js返回当前被屏蔽的类型集合。正如 readme 所说它既可以通过opts初始化也可以在运行时直接修改这个属性因为 getter 直接引用了this.opts.blockedTypes这个 Set 对象外部add/delete会同步作用于插件内部逻辑——这正是动态切换能力的来源。interceptResolutionPriority协作式拦截优先级get interceptResolutionPriority() { return this.opts.interceptResolutionPriority }该 getterindex.js暴露协作式拦截的优先级数值同样支持配置时传入或运行时修改两种方式。关于它的作用见下文协作式拦截模式一节。13 种资源类型全清单availableTypes中的 13 种类型对应 Chromium 的资源类型分类含义如下这是 Chrome DevTools Protocol 中Network.resourceType的标准分类插件只是把它们原样暴露资源类型典型含义document主文档 / 顶层导航请求HTML 页面本身stylesheetCSS 样式表image图片资源media音视频媒体如video/audio源font字体文件如 woff2、ttfscriptJavaScript 脚本texttrack文本轨道如视频字幕 VTTxhrXMLHttpRequest 异步请求fetchFetch API 请求eventsourceServer-Sent EventsEventSource 长连接websocketWebSocket 连接manifestWeb App Manifest / 应用清单other其他类型例如 favicon拦截document意味着整页导航都会被中止实际使用中很少这么做最常见的组合是image、stylesheet、media、font这类非关键资源。示例代码注释里就专门标注了other的典型用例是 faviconexample.js。动态切换运行时随心所欲地开/关拦截该插件最突出的设计是运行时动态调整。readme 给出了完整示例readme仓库中的 example.js 与之几乎一致、可直接运行const { DEFAULT_INTERCEPT_RESOLUTION_PRIORITY } require(puppeteer) const puppeteer require(puppeteer-extra) const blockResourcesPlugin require(puppeteer-extra-plugin-block-resources)({ // 可选启用 Cooperative Mode支持多个请求拦截器协同工作 interceptResolutionPriority: DEFAULT_INTERCEPT_RESOLUTION_PRIORITY }) puppeteer.use(blockResourcesPlugin) ;(async () { const browser await puppeteer.launch({ headless: false }) const page await browser.newPage() // 第一站只屏蔽图片 blockResourcesPlugin.blockedTypes.add(image) await page.goto(http://www.msn.com/, { waitUntil: domcontentloaded }) // 第二站追加屏蔽样式表与 other如 favicon blockResourcesPlugin.blockedTypes.add(stylesheet) blockResourcesPlugin.blockedTypes.add(other) await page.goto(http://news.ycombinator.com, { waitUntil: domcontentloaded }) // 第三站移除样式表与 other改屏蔽媒体与脚本 blockResourcesPlugin.blockedTypes.delete(stylesheet) blockResourcesPlugin.blockedTypes.delete(other) blockResourcesPlugin.blockedTypes.add(media) blockResourcesPlugin.blockedTypes.add(script) await page.goto(http://www.youtube.com, { waitUntil: domcontentloaded }) console.log(all done) })()这段代码演示了三个关键点保留插件实例引用必须把blockResourcesPlugin实例存下来才能在运行时操作它的blockedTypesSet 的add/delete即改即生效因为拦截判断每次请求时都会实时读取blockedTypes见下文onRequest实现所以无需重建浏览器或页面按页面切换屏蔽策略同一浏览器进程内访问不同站点时采用不同的拦截组合比如访问 YouTube 时屏蔽脚本和媒体以大幅减少流量。源码级原理从注册到拦截的完整调用链了解了用法再看它是如何工作的。整个拦截流程分三步插件注册 → 页面创建时开启拦截 → 每个请求到来时按类型裁决。第一步注册插件钩入页面生命周期puppeteer.use(plugin)会把插件注册进 puppeteer-extra 的插件列表并调用plugin._register()记录其子类成员packages/puppeteer-extra/src/index.ts。随后在launch()/connect()时基类会为每个新建页面触发onPageCreated生命周期钩子浏览器targetcreated事件 → 基类的_onTargetCreated过滤出type page的目标 → 调用插件的onPageCreatedpackages/puppeteer-extra-plugin/src/index.ts。block-resources 插件正是利用这个钩子完成拦截装配。第二步onPageCreated开启请求拦截async onPageCreated(page) { this.debug(onPageCreated, { blockedTypes: this.blockedTypes }) await page.setRequestInterception(true) page.on(request, this.onRequest.bind(this)) }这段代码index.js做了两件事page.setRequestInterception(true)开启 puppeteer 的请求拦截开关让页面的每个网络请求都以request事件的形式交给 Node.js 侧裁决page.on(request, this.onRequest.bind(this))把裁决函数绑定到该页面的请求事件上。因为是每个新页面都会走一遍onPageCreated所以launch()之后browser.newPage()创建的任意页面包括弹窗页面都会被自动覆盖。第三步onRequest按资源类型裁决放行或中止onRequest(request) { const type request.resourceType() const shouldBlock this.blockedTypes.has(type) // Requests are immediately handled if not using Cooperative Intercept Mode const alreadyHandled request.isInterceptResolutionHandled ? request.isInterceptResolutionHandled() : true this.debug(onRequest, { type, shouldBlock, alreadyHandled }) if (alreadyHandled) return if (shouldBlock) { const abortArgs request.abortErrorReason ? [blockedbyclient, this.interceptResolutionPriority] : [] return request.abort(...abortArgs) } const continueArgs request.continueRequestOverrides ? [request.continueRequestOverrides(), this.interceptResolutionPriority] : [] return request.continue(...continueArgs) }这段核心逻辑index.js可以拆成四步理解取类型request.resourceType()拿到该请求的资源类型即上面 13 种之一查集合this.blockedTypes.has(type)判断它是否在当前屏蔽集合中——这里每次都实时读取所以动态add/delete立即生效防重复处理isInterceptResolutionHandled()是协作式拦截模式提供的查询 API用于确认该请求是否已被其他拦截器处理过若已被处理则直接返回避免多个拦截器互相覆盖。从注释 Requests are immediately handled if not using Cooperative Intercept Mode 可以看出在不具备该 API 的环境下插件选择保守跳过防止多拦截器冲突裁决动作命中屏蔽类型 →request.abort(blockedbyclient)中止请求若支持协作模式则带上错误原因与优先级未命中 →request.continue()放行若支持协作模式则合并覆盖项与优先级。补充说明request.resourceType()返回的document等类型与availableTypes一一对应这正是拦截判断的匹配依据。值得注意页面本身的主文档请求也会进入onRequest因此理论上也可以屏蔽document——但那样页面将无法加载实际场景中请谨慎使用。协作式拦截模式Cooperative Intercept Mode多个拦截器如何共存当你的 puppeteer-extra 同时注册了多个会拦截请求的插件例如 block-resources 与 adblocker 一起使用就会面临多个request监听器争抢同一个请求的问题。puppeteer 的Cooperative Intercept Mode协作式拦截就是为此设计的机制每个拦截器在调用request.abort()/request.continue()时附带一个优先级数值prioritypuppeteer 内部按优先级裁决由谁处理相同优先级下先到先得已处理isInterceptResolutionHandled()为true的请求后续拦截器不再干预DEFAULT_INTERCEPT_RESOLUTION_PRIORITY是 puppeteer 导出的默认优先级常量从require(puppeteer)中解构获取。插件对协作模式的支持体现在三处 API 的使用index.jsrequest.isInterceptResolutionHandled()查询请求是否已被更高/同优先级拦截器处理request.abortErrorReason/request.continueRequestOverrides读取已记录的裁决信息避免覆盖this.interceptResolutionPriority作为 abort/continue 的第三参数传入。因此当你在同一个 puppeteer-extra 实例里组合多个拦截型插件时建议像官方示例那样显式传入interceptResolutionPriority: DEFAULT_INTERCEPT_RESOLUTION_PRIORITY让各拦截器在同一优先级下公平协作而如果你希望 block-resources 的裁决优先级更高先于其他拦截器生效可以传入一个更大的数值——具体数值含义与 puppeteer 版本相关使用前请查阅你所安装 puppeteer 版本对协作式拦截的说明。测试与调试如何验证插件行为单元测试仓库为插件编写了基于 ava 的单元测试index.test.js覆盖了四类断言导出形态require(.)返回一个函数工厂类结构完整性实例名称是block-resources、具备_isPuppeteerExtraPlugin标记原型上应恰好包含 8 个成员constructor、name、defaults、availableTypes、blockedTypes、interceptResolutionPriority、onRequest、onPageCreated默认值opts.blockedTypes为空Set、availableTypes恰好 13 项、interceptResolutionPriority为undefined。# 在该包目录下运行测试 cd packages/puppeteer-extra-plugin-block-resources yarn test调试日志插件基于debug库输出调试信息命名空间为puppeteer-extra-plugin:block-resources基类this.debug的自动命名规则见 packages/puppeteer-extra-plugin/src/index.ts。开启方式见 example.js 头注释# 只看本插件的日志 DEBUGpuppeteer-extra-plugin:block-resources node example.js # 查看 puppeteer-extra 全家桶日志 DEBUGpuppeteer-extra,puppeteer-extra-plugin:* node example.js开启后会看到每次请求的裁决明细onRequest { type: image, shouldBlock: true, alreadyHandled: false }以及每个页面创建时的onPageCreated { blockedTypes: ... }非常适合排查为什么某个请求没被拦/被拦了。TypeScript 支持插件随包附带类型声明 index.d.tsTypeScript 用户开箱即用import blockResourcesPlugin from puppeteer-extra-plugin-block-resources puppeteer.use( blockResourcesPlugin({ blockedTypes: new Set([image, stylesheet]), interceptResolutionPriority: DEFAULT_INTERCEPT_RESOLUTION_PRIORITY }) )声明文件给出了完整的PluginOptions接口availableTypes?: SetResourceType、blockedTypes?: SetResourceType、interceptResolutionPriority?: number其中资源类型直接复用 puppeteer 导出的ResourceType联合类型与运行时行为完全一致Plugin类则暴露name、defaults、availableTypes、blockedTypes、interceptResolutionPriority等 getter 的类型签名。生态组合与 adblocker 等插件的配合block-resources 是按类型粗暴断流的通用插件而仓库中的 adblocker 插件puppeteer-extra-plugin-adblocker则基于 CLiqz 的 adblocker 引擎做基于规则的精细广告/跟踪器屏蔽。两者的典型分工是想彻底干掉图片、字体、媒体以极限提速 → 用 block-resources想精准屏蔽广告与跟踪器、同时保留图片和样式 → 用 adblocker两者可同时注册此时通过interceptResolutionPriorityadblocker 也支持该选项见 packages/puppeteer-extra-plugin-adblocker/src/index.ts协调拦截优先级即可。由于它们都基于 puppeteer-extra 的插件生命周期onPageCreatedrequest事件组合使用时遵循同一套协作式拦截规则不会互相覆盖裁决结果。注意事项与限制最后整理几个实操中值得留意的点拦截是全局生效于每个页面的插件在onPageCreated中对所有新页面开启拦截如果你只想对特定页面生效需要自行控制blockedTypes的增删时机开启请求拦截会改变请求行为page.setRequestInterception(true)是 puppeteer 的全局开关会让所有请求先经过 Node.js 侧事件循环对高并发页面会有一定性能开销屏蔽非必要资源带来的收益通常远大于此开销动态修改是进程内行为blockedTypes.add(...)修改的是当前 Node.js 进程内插件实例的 Set不影响已发出的请求只对修改之后的请求生效版本适配插件拦截逻辑依赖 puppeteer 的协作式拦截 APIisInterceptResolutionHandled、abortErrorReason、continueRequestOverrides、DEFAULT_INTERCEPT_RESOLUTION_PRIORITY请在支持这些 API 的 puppeteer 版本上使用包内 package.json 中puppeteer ^2.0.0仅为测试依赖当前测试只校验插件类结构与默认值并不依赖真实浏览器环境屏蔽document需谨慎会直接中止页面主文档导航一般只用于特殊场景如拦截 iframe 内的文档请求。小结puppeteer-extra-plugin-block-resources是一个小而美的请求拦截插件API 只有构造函数、availableTypes、blockedTypes和interceptResolutionPriority四个入口但借助 puppeteer 的请求拦截机制与 puppeteer-extra 的插件生命周期实现了覆盖 13 种资源类型、支持运行时动态切换的完整拦截能力。无论是爬虫提速、数据节省还是页面净化把它注册进 puppeteer-extra 后只需几行代码即可按类型精确控制浏览器加载哪些资源。如果想深入阅读源码或动手验证推荐按以下顺序查看仓库中的对应文件插件完整实现packages/puppeteer-extra-plugin-block-resources/index.js可运行示例packages/puppeteer-extra-plugin-block-resources/example.js单元测试packages/puppeteer-extra-plugin-block-resources/index.test.js类型声明packages/puppeteer-extra-plugin-block-resources/index.d.ts插件基类与生命周期packages/puppeteer-extra-plugin/src/index.ts插件注册与调度框架packages/puppeteer-extra/src/index.ts赞分享网页爬虫浏览器控制测试【免费下载链接】puppeteer-extra Teach puppeteer new tricks through plugins.项目地址https://gitcode.com/gh_mirrors/pu/puppeteer-extra点击查看免费下载相关推荐Puppeteer ResourceType 资源类型完全解读识别、过滤与拦截网络请求的基石Puppeteer ResourceType 资源类型完全解读识别、过滤与拦截网络请求的基石 在 Puppeteer 中每一个由页面发出的 HTTP 请求都浏览器控制测试网页爬虫开发工具提升Android应用交互体验Bubbles for Android最佳实践与技巧提升Android应用交互体验Bubbles for Android最佳实践与技巧 Bubbles for Android是一个强大的Android库为应用Puppeteer ActionResult 类型详解continue、abort、respond 三种请求拦截动作的实现与实战Puppeteer ActionResult 类型详解continue、abort、respond 三种请求拦截动作的实现与实战 导读 ActionResul浏览器控制测试网页爬虫开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑