晓晓的个人博客Logo
晓晓的个人博客
《Chrome Extension 和 Puppeteer 如何获取 closed 状态的 Shadow Root》封面
Chrome Extension 和 Puppeteer 如何获取 closed 状态的 Shadow Root
Shadow Root 有 open 和 closed 两种状态,以在封装性和可访问性间提供不同权衡。标准规范中,closed 状态的 Shadow Root 初始化后无法改为 open,也不能用 element.shadowRoot 直接访问。如在示例的 my - component 组件中就无法直接获取。但在 Chrome Extension 或 Puppeteer 自动化框架抓取数据时会遇到这种情况。幸运的是,Chrome Extension 官方提供了相关 API,Puppeteer 也有方法强制开启 Shadow Root。其中,Chrome Extension 可利用 chrome.dom.openOrClosedShadowRoot API,让 Content Script 绕过 Web Component 封装特性访问 closed 状态的 Shadow Root,文中还给出了极简插件示例;Puppeteer 虽无等效 API,但其可通过劫持 Element.prototype.attachShadow 方法,将 closed 模式强制改为 open 来获取数据。
365
1
2025-10-10 12:55
《page.waitForResponse 和 page.on('response', fn) 的资源开销对比》封面
page.waitForResponse 和 page.on('response', fn) 的资源开销对比
本文聚焦于 page.waitForResponse 和 page.on('response', fn) 在不同场景下从资源开销角度的优劣势分析。在面对不确定返回时间的单个响应时,两者资源占用相似,因都需 Promise 对象、超时定时器和事件监听器,且正确处理超时与监听器清理后无本质区别。而获取多个符合条件响应时,page.on('response', fn) 内存损耗低于 page.waitForResponse。page.on('response', fn) 可用一个 Promise 和监听器收集响应,特定条件满足时处理并移除监听器,资源开销固定;page.waitForResponse 为获取多个响应需多次调用或使用 Promise.all,每次都创建新 Promise 实例和监听器,获取 N 个响应就需 N 个 Promise 和监听器,内存与 CPU 开销更大。最后提到结合前文内容汇总成表格,辅助在不同场景选择合适监听器。
252
1
2025-10-02 22:31
《page.on('response',fn) 的最佳实践之等待响应》封面
page.on('response',fn) 的最佳实践之等待响应
本文聚焦于 Puppeteer 中处理 “长时间等待或者捕获多个响应” 的场景。鉴于 page.waitForResponse 只适用于短时间响应场景,文章提出借助 page.on ('response', fn) 事件监听器来实现上述复杂场景,并建议将其封装成通用异步函数以确保代码健壮性和职责分离。接着,文中给出了监听单个响应和多个响应的通用函数代码示例,详细展示了如何设置超时机制、定义响应处理器以及添加监听器等关键步骤。同时,介绍了封装函数的调用方式,强调使用 Promise.all () 解决竞态条件。随后,阐述了封装函数在超时管理、资源清理和 Promise 生命周期管理方面的优势。最后,提醒调用方在使用时要注意解决竞态条件和精准设置 predicate 函数,并说明文章存在场景单一、错误处理武断等问题,实际应用需结合业务场景调整。
217
0
2025-09-28 09:39
《page.on('response',fn) 的竞态条件》封面
page.on('response',fn) 的竞态条件
在 Puppeteer 中运用 page.on('response', fn) 监听页面响应时,会遭遇监听器注册时序竞态与处理顺序竞态这两种问题。监听器注册时序竞态是指在调用如 page.goto() 等触发网络请求操作后才注册监听器,可能错过早期响应,解决办法是在执行此类操作前就注册监听器。处理顺序竞态是由于多个网络响应几乎同时到达时,监听器处理顺序不确定,可能导致计数错误、处理顺序混乱等问题,解决方法包括使用异步队列确保按序处理并配合原子性操作介质,以及通过同时监听 page.on('request', fn) 和 page.on('response', fn) 建立请求和响应的关联。本文通过示例代码阐述问题及解决方案,但强调代码仅为部分场景的粗略示范,实际需根据具体问题分析处理。
189
0
2025-09-24 23:00
《page.on('response',fn) 适用于“对响应顺序不敏感”的场景》封面
page.on('response',fn) 适用于“对响应顺序不敏感”的场景
本文详细阐述了 page.on('response', fn) 的特性、适用及不适用场景。该方法只要浏览器页面收到任意网络响应(HTTP/HTTPS)就会触发,无论响应来自何种资源,其触发顺序取决于响应实际完成顺序,具有不确定性。这使其适合监听所有网络活动、记录所有响应数据、处理独立请求等对响应顺序不敏感的场景。但对于有严格顺序要求,如请求响应存在依赖关系的场景则不太适用,这种情况通常需用 await page.waitForResponse 或结合 page.on('request', fn) 与状态管理来确保请求和响应的配对。总之,page.on('response', fn) 如同不分先后的 “接收器”,适用于仅处理已收到响应的场景。
121
1
2025-09-22 07:39
《说说page.on('response',fn)》封面
说说page.on('response',fn)
本文聚焦 Puppeteer 中 page.waitForResponse 和 page.on('response', fn) 的对比,二者虽都用于监听网络请求响应,执行环境均为 Node.js 且底层基于对 Network.responseReceived 事件监听,但在特性、适用场景和实现机制上差异显著。文中着重剖析了 page.on('response', fn) 的底层原理,从 Puppeteer 启动浏览器创建与 Chromium 的 WebSocket 通信通道,到设置监听时发送 Network.enable 消息(按需发送以避免不必要调用),再到 Chromium 发送 Network.responseReceived 事件,Puppeteer 封装 HttpResponse 对象并触发回调函数的全过程。同时说明了响应体出于性能考虑未在该事件中直接传递,而是在特定方法调用时才获取并填充到 Response 对象。
135
0
2025-09-20 22:53
《page.once('response',fn) 的竞态条件》封面
page.once('response',fn) 的竞态条件
page.once('response', fn)的适用场景及存在的竞态问题。该方法适用于不关心具体响应,只要首个响应出现,或确定要等待的响应是首个返回的情况,其核心是只监听一次,触发后自动移除。但当一个操作触发多个网络请求时,会出现竞态问题,它只会捕获首个返回响应,而不管是否为所需响应,如点击按钮触发多个请求,可能先捕获到非关键请求的响应。针对此问题,可使用page.waitForResponse()等待所有符合条件响应,或用page.on('response', fn)监听所有响应并自行实现数据返回和错误处理机制。
65
0
2025-09-16 06:28
《为什么 page.waitForResponse 只适合“短时间内返回响应”的场景?》封面
为什么 page.waitForResponse 只适合“短时间内返回响应”的场景?
page.waitForResponse () 旨在为可预测、短时完成的网络请求提供简洁等待方案,其实现机制与之契合。一是 “一次性” 等待模式,返回 Promise,找到首个符合条件响应即 resolve 并停止监听,适用于 “只关心第一个” 场景。二是严格超时限制,默认 30 秒,超时则 Promise 被 reject 并抛 TimeoutError,避免资源耗尽或程序卡死。所以该方法适合明确且短时间返回的请求,若需长时间监控或捕获多个响应,使用事件监听器如 page.on ('response', fn) 更佳。
93
0
2025-09-12 23:19
《page.waitForResponse 的竞态条件与最佳实践》封面
page.waitForResponse 的竞态条件与最佳实践
尽管官方文档未详细阐述 page.waitForResponse 的竞态条件,但从官方代码示例、github issue 讨论及实际使用可知存在时间序列竞态和匹配条件竞态两种情况。时间序列竞态是因 waitForResponse 作为事件监听器,在注册前无法监听事件,而触发网络请求的操作延迟不定,在触发操作与监听器实际注册间的短暂窗口内,若请求完成,响应将无法被捕获,导致等待超时。匹配条件竞态是由于 waitForResponse 接受的判断函数若匹配条件宽泛,会匹配到多个响应,仅返回首个匹配的,可能并非期望的响应。文中分别给出了两种竞态的正确使用姿势,还强调出于性能考虑,不要在判断函数中进行如 response.json () 这样的繁重操作,应先快速过滤,再按需读取。
250
0
2025-09-11 22:28
《page.waitForResponse 执行环境:页面还是 Node.js?》封面
page.waitForResponse 执行环境:页面还是 Node.js?
文章聚焦 Puppeteer 中page.waitForResponse方法,指出该方法虽监听页面网络请求,但执行上下文环境是 Node.js 环境。接着详细剖析其底层原理,从 Node.js 层设置监听开始,到获取符合条件的HttpResponse对象,历经多步流程。包括启动浏览器时创建与 Chromium 的 WebSocket 通信通道,设置page.waitForResponse方法时,Puppeteer 先确认是否已开启网络监控,未开启则通过 WebSocket 向 Chromium 发送Network.enable消息(CDP 命令)启用网络监控并返回 Promise;Chromium 接收网络原始数据后,通过 WebSocket 发送Network.responseReceived CDP 事件;Puppeteer 将原始数据封装成HttpResponse对象并传递给 Node.js 层的predicate函数判断,符合条件则page.waitForResponse的 Promise 被 resolve,返回HttpResponse对象,同时停止监听并清理内部消息处理程序
262
1
2025-09-11 00:01
1 页 / 共 2