Cloudflare Browser Rendering 技能参考:在 Cloudflare 全球网络驱动无头 Chrome 完成截图、PDF 与自动化抓取

Cloudflare Browser Rendering 技能参考:在 Cloudflare 全球网络驱动无头 Chrome 完成截图、PDF 与自动化抓取 Cloudflare Browser Rendering 技能参考在 Cloudflare 全球网络驱动无头 Chrome 完成截图、PDF 与自动化抓取【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skillsCloudflare Browser Rendering 是 Cloudflare 平台提供的浏览器自动化服务允许你在其全球边缘网络上控制无头 Chrome用于网页截图、PDF 生成、网页抓取、Web 应用测试与内容生成。本文以本仓库cloudflare-deploy技能中browser-rendering参考集为核心完整覆盖技术选型决策树、配额限制、部署配置、REST API 与 Workers Bindings 双入口、常见实战模式与避坑要点读完即可在 Workers 中落地一套可运行的浏览器自动化方案。一、这是什么技能在仓库中的定位在cloudflare-deploy技能的总入口 SKILL.md 中我需要媒体/内容决策树将Browser automation/screenshots → browser-rendering/列为唯一答案与图片优化images/、视频流stream/并列而在 bindings 参考 中Browser Rendering 被定义为以env.BROWSER.fetch(url)形式暴露的Headless Chrome绑定。也就是说它是面向需要在边缘执行真实浏览器行为这一类任务的权威参考。该技能参考的适用场景非常明确任何涉及 Cloudflare Browser Rendering 的任务包括截图、PDF 生成、网页抓取、浏览器自动化、Web 应用测试、结构化数据提取、页面指标采集以及自动化的浏览器交互。无论你是第一次接触该服务还是已有 Workers 经验本文都以原文档为骨架、以同级四篇深度文档为血肉给出可复制的完整方案。二、技术选型决策树两条主干路线原文档给出的第一个关键决策是如何接入 Browser Rendering走REST API还是Workers Bindings以及用什么库驱动Puppeteer还是Playwright。REST API 与 Workers Bindings 怎么选场景推荐路线理由一次性、无状态任务截图、PDF、内容抓取REST API无需部署 Workers一次调用即得结果尚无 Workers 基础设施REST API从外部服务即可简单集成需要快速原型验证、不想经历部署流程REST APIcurl 即可完成验证复杂的浏览器自动化工作流Workers Bindings可编排多步骤交互需要会话复用以获得性能Workers Bindings复用 keep-alive 会话避免冷启动单次请求内多个页面交互Workers Bindings同一 Browser 实例内操作多个 Page需要自定义脚本与业务逻辑Workers Bindings完整 TypeScript 编程环境构建生产级应用Workers Bindings可结合 KV、队列等平台能力简单记忆REST 适合测一下、用一次Workers 适合做产品、持续跑。Puppeteer 与 Playwright 怎么选特性PuppeteerPlaywrightAPI 风格Chrome DevTools ProtocolCDP高层抽象选择器CSS、XPathCSS、text、role、test-id最适合高级控制、直接 CDP 访问快速自动化、测试学习曲线较陡较平缓选Puppeteer需要 CDP 协议级访问、使用 Chrome 特有功能、或从既有 Puppeteer 代码迁移。选Playwright需要现代选择器 APIgetByRole/getByText/getByTestId、跨浏览器风格的写法、追求更快的开发速度。三、配额限制总览成文前必读原文档在 Tier Limits Summary 中给出了免费版与付费版的核心配额这是所有方案设计的硬约束限制项免费版付费版每日浏览器时长10 分钟无限*并发会话数330每分钟请求数6180* 受公平使用政策fair-use policy约束。此外gotchas.md 补充了一项对所有层级一致的约束会话 keep-alive 上限均为 10 分钟。这意味着免费版每天累计只有 10 分钟的浏览器执行时间并发会话最多 3 个——架构上必须围绕单会话多页面而非多会话来设计详见第六节的并发优化。四、配置与部署从安装到第一个截图本节完整继承 configuration.md 的配置内容并补充参数注释。4.1 安装必须使用 Cloudflare 专用包npm install cloudflare/puppeteer # 或 cloudflare/playwright关键前提标准puppeteer/playwright包在 Workers 中无法工作必须使用 Cloudflare 维护的专用发行版二者 API 与官方版本保持一致但针对 Workers 运行时做了适配。4.2 wrangler.json两个必需项{ name: browser-worker, main: src/index.ts, compatibility_date: 2025-01-01, compatibility_flags: [nodejs_compat], browser: { binding: MYBROWSER } }两个必需配置项compatibility_flags: [nodejs_compat]启用 Node.js 兼容层Puppeteer/Playwright 依赖它运行browser.binding: MYBROWSER声明 Browser Rendering 绑定绑定名可自定义如BROWSER后续代码通过env.MYBROWSER访问。在 pulumi 参考 中还可以看到以 IaC 方式声明同一绑定的等价写法browserBinding: {name: BROWSER}。4.3 TypeScript 类型声明interface Env { MYBROWSER: Fetcher; } export default { async fetch(request: Request, env: Env): PromiseResponse { // 使用 env.MYBROWSER 启动浏览器 } } satisfies ExportedHandlerEnv;4.4 本地开发必须--remotewrangler dev --remote # --remote 是使用 browser binding 的硬性要求本地模式local mode不支持 Browser Rendering——绑定只能在远程边缘环境真实生效这是调试时最常见的坑之一务必牢记。4.5 不走 Workers纯 REST 方式如果选择 REST API 路线则无需任何 wrangler 配置只需在 Cloudflare 控制台创建一个带Browser Rendering - Edit权限的 API Tokencurl -X POST \ https://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering/screenshot \ -H Authorization: Bearer TOKEN \ -d {url: https://example.com} --output screenshot.png4.6 环境要求清单要求取值Node.js 兼容性nodejs_compat兼容标志Compatibility date2023-03-01 及以上模块格式仅 ES modules浏览器Chromium 119不支持 Firefox/Safari明确不支持WebGL、WebRTC、浏览器扩展、file://协议、Service Worker 语法。4.7 常见故障排查表错误解决方案MYBROWSER is undefined使用wrangler dev --remote运行nodejs_compat not enabled在compatibility_flags中添加该标志Module not found执行npm install cloudflare/puppeteerBrowser Rendering not available在 Cloudflare 控制台启用该服务五、API 参考REST 端点与 Workers Bindings本节完整继承 api.md 的内容。5.1 REST API 概览Basehttps://api.cloudflare.com/client/v4/accounts/{accountId}/browser-rendering认证Authorization: Bearer token需 Browser Rendering - Edit 权限端点清单端点说明关键选项/content获取渲染后的 HTMLurl、waitUntil/screenshot捕获图片screenshotOptions: {type, fullPage, clip}/pdf生成 PDFpdfOptions: {format, landscape, margin}/snapshotHTML 内联资源url/scrape按选择器提取selectors: [h1, .price]/jsonAI 结构化提取schema: {name: string, price: number}/links获取所有链接url/markdown转换为 Markdownurl完整截图调用示例curl -X POST .../browser-rendering/screenshot \ -H Authorization: Bearer $TOKEN \ -d {url:https://example.com,screenshotOptions:{fullPage:true}}5.2 Workers Binding 声明// wrangler.jsonc { browser: { binding: MYBROWSER } }5.3 Puppeteer 完整用法import puppeteer from cloudflare/puppeteer; const browser await puppeteer.launch(env.MYBROWSER, { keep_alive: 600000 }); const page await browser.newPage(); await page.goto(https://example.com, { waitUntil: networkidle0 }); // 内容 const html await page.content(); const title await page.title(); // 截图/PDF await page.screenshot({ fullPage: true, type: png }); await page.pdf({ format: A4, printBackground: true }); // 交互 await page.click(#button); await page.type(#input, text); await page.evaluate(() document.querySelector(h1)?.textContent); // 会话管理 const sessions await puppeteer.sessions(env.MYBROWSER); const limits await puppeteer.limits(env.MYBROWSER); await browser.close();5.4 Playwright 完整用法import { launch, connect } from cloudflare/playwright; const browser await launch(env.MYBROWSER, { keep_alive: 600000 }); const page await browser.newPage(); await page.goto(https://example.com, { waitUntil: networkidle }); // 现代选择器 await page.locator(.button).click(); await page.getByText(Submit).click(); await page.getByTestId(search).fill(query); // 上下文隔离 const context await browser.newContext({ viewport: { width: 1920, height: 1080 }, userAgent: custom }); await browser.close();5.5 会话管理三件套// 列出当前会话 await puppeteer.sessions(env.MYBROWSER); // 连接既有会话复用 await puppeteer.connect(env.MYBROWSER, sessionId); // 检查配额 await puppeteer.limits(env.MYBROWSER); // 返回形如 { remaining: ms, total: ms, concurrent: n }5.6 关键选项速查选项可选值waitUntilload、domcontentloaded、networkidle0、networkidle2keep_alive最大 600000ms10 分钟screenshot.typepng、jpegpdf.formatA4、Letter、Legal六、实战模式可直接复制的代码骨架本节完整继承 patterns.md 的全部模式。6.1 最简 Worker抓取页面 HTMLimport puppeteer from cloudflare/puppeteer; export default { async fetch(request, env) { const browser await puppeteer.launch(env.MYBROWSER); try { const page await browser.newPage(); await page.goto(https://example.com); return new Response(await page.content()); } finally { await browser.close(); // 必须放在 finally 中 } } };6.2 会话复用用 KV 存 sessionId会话复用的核心价值在于性能冷启动约 12 秒而热连接仅约 100200 毫秒。将 sessionId 存入 KV 即可实现跨请求复用let sessionId await env.SESSION_KV.get(browser-session); if (sessionId) { browser await puppeteer.connect(env.MYBROWSER, sessionId); } else { browser await puppeteer.launch(env.MYBROWSER, { keep_alive: 600000 }); await env.SESSION_KV.put(browser-session, browser.sessionId(), { expirationTtl: 600 }); } // 注意此处不要关闭浏览器以保持会话存活6.3 常用操作速查表任务代码截图await page.screenshot({ type: png, fullPage: true })PDFawait page.pdf({ format: A4, printBackground: true })提取数据await page.evaluate(() document.querySelector(h1).textContent)填写表单await page.type(#input, value); await page.click(button)等待导航await Promise.all([page.waitForNavigation(), page.click(a)])6.4 并行抓取单浏览器多页面const pages await Promise.all(urls.map(() browser.newPage())); await Promise.all(pages.map((p, i) p.goto(urls[i]))); const titles await Promise.all(pages.map(p p.title()));6.5 Playwright 现代选择器import { launch } from cloudflare/playwright; const browser await launch(env.MYBROWSER); await page.getByRole(button, { name: Sign in }).click(); await page.getByLabel(Email).fill(userexample.com); await page.getByTestId(submit-button).click();6.6 隐身上下文无需多个浏览器即可隔离会话const ctx1 await browser.createIncognitoBrowserContext(); const ctx2 await browser.createIncognitoBrowserContext(); // 每个上下文拥有独立的 cookies 与存储6.7 配额检查提前熔断const limits await puppeteer.limits(env.MYBROWSER); if (limits.remaining 60000) return new Response(Quota low, { status: 429 });6.8 错误处理模板try { await page.goto(url, { timeout: 30000, waitUntil: networkidle0 }); } catch (e) { if (e.message.includes(timeout)) return new Response(Timeout, { status: 504 }); if (e.message.includes(Session limit)) return new Response(Too many sessions, { status: 429 }); } finally { if (browser) await browser.close(); }七、避坑指南配额、生命周期与性能本节完整继承 gotchas.md 的全部要点。7.1 完整配额表与配额自检限制项免费版付费版每日浏览器时长10 分钟无限*并发会话330每分钟请求6180会话 keep-alive上限 10 分钟上限 10 分钟* 受公平使用政策约束。代码自检配额const limits await puppeteer.limits(env.MYBROWSER); // 返回形如 { remaining: 540000, total: 600000, concurrent: 2 }7.2 务必关闭浏览器生命周期差异是最大的坑const browser await puppeteer.launch(env.MYBROWSER); try { const page await browser.newPage(); await page.goto(https://example.com); return new Response(await page.content()); } finally { await browser.close(); // 始终放在 finally }Workers 与 REST 的生命周期差异REST API 会在超时后自动关闭会话而 Workers 必须显式调用close()否则会话会一直存活到keep_alive过期——既消耗配额又占用并发会话额度。7.3 并发优化用页面代替会话免费版只有 3 个并发会话因此// ❌ 3 个会话直接触顶免费版上限 const browser1 await puppeteer.launch(env.MYBROWSER); const browser2 await puppeteer.launch(env.MYBROWSER); // ✅ 1 个会话、多个页面 const browser await puppeteer.launch(env.MYBROWSER); const page1 await browser.newPage(); const page2 await browser.newPage();7.4 常见错误速查错误原因修复Session limit exceeded并发会话过多关闭未使用的浏览器多用页面少用浏览器Page navigation timeout页面加载慢或忙碌页面上等待networkidle增大 timeout改用waitUntil: loadSession not found会话已过期捕获异常后启动新会话Evaluation failedDOM 元素缺失使用?.可选链Protocol error: Target closed关闭前仍在执行操作关闭前先 await 全部操作7.5page.evaluate()作用域陷阱// ❌ 外部作用域不可用——selector 在 Worker 作用域回调在浏览器作用域 const selector h1; await page.evaluate(() document.querySelector(selector)); // ✅ 必须作为参数传入 await page.evaluate((sel) document.querySelector(sel)?.textContent, selector);7.6 性能优化三板斧1. 按需选择waitUntil从快到慢domcontentloaded- DOM 就绪即可load- load 事件默认networkidle0- 网络空闲 500ms2. 拦截并阻断非必要资源await page.setRequestInterception(true); page.on(request, (req) { if ([image, stylesheet, font].includes(req.resourceType())) { req.abort(); } else { req.continue(); } });3. 会话复用冷启动约 12 秒热连接约 100200 毫秒用 KV 持久化 sessionId见 6.2 节可显著降低延迟。八、按角色推荐的阅读路径原文档给出了清晰的学习路径转换为仓库内全局相对路径后如下第一次接触 Browser Renderingconfiguration.md - 安装与部署patterns.md - 常见用例与示例代码api.md - API 参考gotchas.md - 常见坑与规避按任务直达安装/部署 → configuration.mdAPI 参考/端点 → api.md示例代码/模式 → patterns.md调试/排障 → gotchas.mdREST API 用户从 api.md 的 REST API 章节开始再查看 gotchas.md 了解速率限制。Workers 用户先读 configuration.md再对照 patterns.md 掌握会话管理最后以 api.md 的 Workers Bindings 部分为准。九、小结围绕 Cloudflare Browser Rendering决策的关键可以浓缩为三点按任务性质选入口REST 一次即用Workers 长期编排、按自动化需求选库Puppeteer 走 CDP 深度控制Playwright 走现代选择器快速开发、按配额上限设计架构免费版 10 分钟/天、3 并发会话、6 请求/分钟务必单会话多页面 会话复用。在此基础上把finally { browser.close() }、keep_alive上限 10 分钟、page.evaluate参数传值这三条铁律内化为肌肉记忆即可在 Cloudflare 边缘稳定跑通截图、PDF、抓取与自动化测试。继续深入可阅读本技能目录下的 api.md 与 gotchas.md或在cloudflare-deploy技能总入口 SKILL.md 中探索 KV、D1、Queues 等周边服务组合出完整的边缘应用。【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考