Activepieces Browserless 件实战:在流程中调用无头浏览器完成截图、PDF 生成、网页抓取、BQL 脚本与性能审计
【免费下载链接】activepiecesAI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces
Activepieces 社区件目录中的 Browserless 件(位于 packages/pieces/community/browserless)把云端的完整 Chrome 会话接入了自动化流程,无需自建浏览器服务器或编写抓取代码。本文以该件的源码为准,完整拆解它的认证配置方式、统一的 HTTP 调用层,以及截图、PDF 生成、URL 抓取、BQL 查询、Lighthouse 性能分析五个 Action 的全部输入参数、请求体组装规则与返回结构,读完后可直接在 Activepieces 中配置该件并理解每个参数最终如何映射到 Browserless REST API。
件定位与注册入口
该件通过 src/index.ts 中的createPiece注册:
displayName: 'Browserless',分类为PieceCategory.DEVELOPER_TOOLS(开发者工具);minimumSupportedRelease: '0.36.1',即要求 Activepieces 发行版不低于 0.36.1;triggers: []——该件只提供动作(Actions),没有触发器;actions数组固定注册五个动作:captureScreenshot、generatePdf、scrapeUrl、runBqlQuery、getWebsitePerformance。
对应的 npm 包名为@activepieces/piece-browserless(当前仓库中版本 0.1.8),依赖 packages/pieces/common(@activepieces/pieces-common提供httpClient与HttpMethod)和 packages/pieces/framework(提供createPiece、Property等),见 package.json。
认证配置:API Token 加区域端点
Browserless 件使用PieceAuth.CustomAuth自定义认证,定义在 src/lib/common/auth.ts,包含三个属性:
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
apiToken | SecretText(密文文本) | 是 | Browserless 仪表盘中的 API Token,以密文保存 |
region | StaticDropdown | 是 | 选择就近的区域端点或Custom Endpoint |
customBaseUrl | ShortText | 否 | 仅当region选custom时填写,指向自建或专属实例的端点 URL |
源码中内置的三个区域端点为:
| 选项标签 | 端点值 |
|---|---|
| US West (San Francisco) | https://production-sfo.browserless.io |
| Europe UK (London) | https://production-lon.browserless.io |
| Europe (Amsterdam) | https://production-ams.browserless.io |
需要注意一个文档与源码的差异:README 中描述的接入方式是使用https://your-api-key.browserless.io形式的个人端点 URL;而从源码看,当前版本的认证 UI 已改为“区域下拉框 + 自定义端点”模式,个人端点应通过选择Custom Endpoint并填入customBaseUrl来使用。
认证信息最终如何生效,见下一节的统一调用层。
统一 HTTP 调用层:token 走查询参数,二进制响应走 ArrayBuffer
所有 Action 都不直接发请求,而是调用 src/lib/common/client.ts 中browserlessCommon.apiCall。从源码结构看,其请求组装逻辑是:
- BaseUrl 解析:
baseUrl = auth.region === 'custom' ? auth.customBaseUrl : auth.region,两者皆空时抛出Base URL is required错误; - 鉴权方式:Token 不作为请求头而是作为查询参数
token=*** 附加到 URL 上(queryParams: { token: auth.apiToken }`); - 请求头:
Content-Type: application/json、Accept: */*,body 用JSON.stringify序列化后以 POST 方式发送; - 响应类型判断:当资源路径包含
/screenshot或/pdf时,responseType设为arraybuffer,其余(/scrape、/chromium/bql、/performance)按json解析; - 底层由
@activepieces/pieces-common的httpClient.sendRequest发出。
同文件还导出了两个工具函数:convertBinaryToBase64(把ArrayBuffer/Buffer/字符串二进制数据转 Base64,供截图与 PDF 动作在返回结果中附带screenshotBase64/pdfBase64字段)和isBinaryResponse(按content-type判断是否为image/*、application/pdf或application/octet-stream)。
动作一:Capture Screenshot(页面截图)
实现见 src/lib/actions/capture-screenshot.ts,对 BrowserlessPOST /screenshot端点发起请求。
输入参数:
| 参数 | 类型/默认值 | 映射到请求体 |
|---|---|---|
| URL | 必填 | body.url |
| Image Type | 默认png,可选jpeg | options.type |
| Quality | 数字,仅对 JPEG 生效 | options.quality(源码仅在imageType === 'jpeg'时才写入) |
| Full Page | 默认false | options.fullPage |
| Viewport Width / Height | 数字 | 两者都填才组装viewport: { width, height } |
| Wait for Selector | CSS 选择器 | waitForSelector: { selector } |
| Delay (ms) | 数字 | waitForTimeout |
| Omit Background | 默认false | options.omitBackground(透明底截图) |
| Clip X / Y / Width / Height | 数字 | 四个值必须同时提供才组装options.clip |
一次最小请求体形如:
{ "url": "https://example.com", "options": { "type": "png", "fullPage": false } }返回处理是该动作的亮点:由于响应体是二进制,Action 会把ArrayBuffer/Buffer/字符串统一转成Buffer,再通过 Activepieces 的文件服务context.files.write落盘为screenshot.png(或screenshot.jpeg),最终返回:
success: true;file:写入的文件对象,可直接被流程中后续步骤引用;screenshotBase64:图片 Base64 字符串,方便直接嵌入邮件、消息等文本场景;metadata:包含url、type、fullPage、timestamp、contentType、fileName。
aiMetadata中明确标注该动作idempotent: false——每次调用都会执行一次全新的无头浏览器渲染,返回的是调用时刻的实时页面。
动作二:Generate PDF(网页转 PDF)
实现见 src/lib/actions/generate-pdf.ts,请求POST /pdf端点。入口校验两条硬规则:url与html必须提供其一,且不能同时提供(分别抛出Either URL or HTML content must be provided与Cannot provide both URL and HTML content. Choose one.)。
主要参数:
- 内容来源:
url或html(HTML 字符串直接渲染,适合把流程中生成的报表模板转 PDF); - 纸张格式
format:A0~A6、Letter、Legal、Ledger、Tabloid,默认A4;自定义纸张尺寸可用width/height(如8.5in、210mm); - 方向与背景:
landscape默认false;printBackground默认true;omitBackground可生成透明背景 PDF; - 页边距:
marginTop/marginRight/marginBottom/marginLeft(如10mm、0.4in),任一填写即组装options.margin; - 页眉页脚:
headerTemplate/footerTemplateHTML 模板,配合displayHeaderFooter(默认false)生效; - 缩放
scale:取值 0.1~2.0,源码中用Math.max(0.1, Math.min(2.0, scale))做了钳制; - 等待控制:
waitForSelector(可配timeout/visible默认 true /hidden)、waitForFunction(可配polling与timeout)、waitForTimeout、页面加载timeout; - 其他:
pageRanges(如1-5, 8, 11-13)、preferCSSPageSize(尊重页面 CSS@page尺寸)、tagged(无障碍标记 PDF)、outline(生成书签大纲)、userAgent、bestAttempt(等待事件失败或超时时仍尝试继续)。
默认请求体(只填了 URL 时):
{ "url": "https://example.com", "options": { "format": "A4", "landscape": false, "printBackground": true, "displayHeaderFooter": false } }返回结构与截图动作一致:PDF 二进制经context.files.write落盘为document.pdf,返回file、pdfBase64,metadata中标记source: 'url' | 'html'及纸张格式、时间戳等。该动作同样标注为非幂等(idempotent: false)。
动作三:Scrape URL(CSS 选择器抓取)
实现见 src/lib/actions/scrape-url.ts,请求POST /scrape端点,用 CSS 选择器从渲染后的 DOM 中提取文本与属性,而非返回整页 HTML。
关键参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
url | 必填 | 目标页面 |
elements | 必填,数组 | 每项含selector(必填)与可选的按选择器粒度timeout |
timeout | 30000 | 页面加载超时,写入gotoOptions.timeout |
waitUntil | networkidle2 | 导航完成判定:load/domcontentloaded/networkidle0/networkidle2,写入gotoOptions.waitUntil |
waitForSelector组 | — | selector+ 可选timeout/visible(默认 true)/hidden(默认 false) |
waitForEvent组 | — | 指定事件名 + 可选超时,如等待某网络请求或自定义事件 |
waitForFunction | — | 返回true时视为就绪的 JS 函数 |
viewportWidth/viewportHeight | 1920/1080 | 两者同时有值才写入viewport |
cookies | — | 抓取前预置的 Cookie 数组(name/value必填,domain可选) |
debugConsole/debugCookies/debugNetwork | 均默认false | 开启后组装debugOpts,在调试输出中包含控制台日志、Cookie 与网络请求 |
bestAttempt | false | 等待失败时仍尝试继续 |
userAgent | — | 自定义 UA |
一个典型请求体(提取所有商品标题,等待列表渲染完成):
{ "url": "https://shop.example.com/products", "elements": [{ "selector": ".product-title" }], "gotoOptions": { "timeout": 30000, "waitUntil": "networkidle2" }, "waitForSelector": { "selector": ".product-list", "timeout": 5000, "visible": true }, "viewport": { "width": 1920, "height": 1080 } }返回{ success: true, data: response.body, metadata: { url, elementsCount, timestamp } },data即 Browserless 返回的抽取结果。aiMetadata标注该动作幂等(相同输入重复抓取无副作用)。另有一个实现细节:elements[].selector在写入请求体前会尝试JSON.parse,以兼容用户误把 JSON 对象粘贴到选择器输入框的情况,解析失败则回退为原始字符串。
动作四:Run BQL Query(BQL 脚本化浏览器操作)
实现见 src/lib/actions/run-bql-query.ts,这是五个动作中唯一被标记为WRITE分类的动作——它请求POST /chromium/bql,执行 GraphQL 语法的 Browser Query Language 查询,可表达导航、点击、输入等多步交互,用于截图/抓取/PDF 这类结构化接口表达不了的自动化场景。
请求体只有三个字段:query(必填,例如mutation { goto(url: "https://example.com") { status } })、variables(GraphQL 变量对象)、operationName。
其余所有会话级选项都以查询参数拼在/chromium/bql之后,由源码逐段组装:
| 参数 | 默认值 | 查询参数形式 |
|---|---|---|
timeout | 30000 | timeout=30000 |
stealth | true | stealth=true/false(反检测模式,默认开启) |
headless | true | headless=true/false(关闭则为有 GUI 会话) |
humanlike | false | humanlike=true(拟人化鼠标/键盘/延迟) |
proxy | — | 支持residential/none;选住宅代理时可追加proxyCountry(国家码)与proxySticky=true |
blockAds | false | blockAds=true(uBlock Origin 拦截) |
blockConsentModals | false | blockConsentModals=true(自动关闭 Cookie 同意弹窗) |
record | false | record=true(会话录像) |
slowMo | — | slowMo=N(操作间加毫秒级延迟) |
ignoreHTTPSErrors | false | ignoreHTTPSErrors=true |
userAgent | — | userAgent=<encodeURIComponent 后的值> |
viewportWidth/viewportHeight | — | 同时有值时viewport=WxH |
cookies | — | 完整 Cookie 数组(含url/domain/path/secure/httpOnly/sameSite/expires)序列化后 URL 编码为cookies=<json> |
响应解析上,Action 会尝试把字符串响应体JSON.parse后拆出 GraphQL 标准结构,返回:
data:parsedResult.data;errors:parsedResult.errors;result:完整解析结果;metadata:browserType: 'chromium'、executionTime(取自响应头x-response-time)、timestamp、stealth。
aiMetadata强调该动作非幂等:BQL 查询可能执行有状态、带副作用的浏览器操作,重复执行不保证相同结果。
动作五:Get Website Performance(Lighthouse 性能审计)
实现见 src/lib/actions/get-website-performance.ts,请求POST /performance,本质是让 Browserless 在云端浏览器中跑一次 Lighthouse 并返回完整报告。
输入参数与默认值:
url(必填);categories:可选performance/accessibility/best-practices/seo/pwa,写入 Lighthouse 配置settings.onlyCategories;device:desktop(默认)或mobile,映射为settings.formFactor;throttling:默认mobileSlow4G,源码中映射为具体的 Lighthouse 网络模拟参数:
| 选项 | rttMs | throughputKbps | cpuSlowdownMultiplier |
|---|---|---|---|
mobileSlow4G(默认) | 150 | 1638.4 | 4 |
mobileRegular4G | 100 | 2048 | 3 |
mobileFast4G | 50 | 4096 | 2 |
none | 不写入 throttling 配置 | — | — |
locale默认en-US;timeout默认60000;waitForSelector在审计前等待;emulateMediaType(screen/print,写入settings.emulatedFormFactor);onlyCategories:只返回五大类得分而不返回明细审计;budgets:性能预算数组,每项为资源类型(document/script/stylesheet/image/media/font/other/third-party)+ KB 数,源码中做了budget * 1024的 KB 转字节换算;stealth/blockAds作为查询参数附加。
组装出的 Lighthouse 配置以extends: 'lighthouse:default'为基础,与url一起构成POST /performance的请求体;勾选预算时budgets作为请求体顶层字段传入。
返回被加工为三层结构:
summary:url、formFactor、timestamp,加scores(五大类得分按 0~100 四舍五入)与metrics(FCP、LCP、FMP、Speed Index、TTI、TBT、CLS 七项核心指标,含displayValue与得分),以及opportunities(从unused-css-rules、unused-javascript、render-blocking-resources审计项中提取的优化机会及潜在节省量);fullReport:完整的 Lighthouse 报告对象(lhr等原始数据),供流程下游深入分析;metadata:analysisTime(响应头x-response-time)与lighthouseVersion。
使用建议与边界条件
结合源码可以归纳几条实操要点:
- 端点选择:优先选离你部署环境最近的区域端点;自建/专属实例选
Custom Endpoint并填customBaseUrl,否则调用层会直接抛错; - 二进制动作的文件落地:截图与 PDF 动作既写入文件对象又附带 Base64 字段,两条链路可分别对接需要“文件”和需要“内嵌字符串”的下游步骤;
- 参数联动约束:JPEG 的
quality仅在格式为jpeg时生效;截图裁剪要求 X/Y/宽/高四值齐全;PDF 的scale会被钳制到 0.1~2.0;抓取与 BQL 的viewport要求宽高同时填写; - 等待策略三件套:
waitForSelector、waitForTimeout、waitForFunction在所有渲染类动作中可用,bestAttempt则用于容忍等待失败继续执行,配合timeout(抓取/BQL 默认 30s,性能审计默认 60s)控制整体预算; - 幂等性判断:抓取与性能审计是只读幂等动作,截图、PDF、BQL 均为非幂等动作,在流程重试设计(如失败重跑)中需考虑重复渲染与副作用成本。
以上所有行为均可在 packages/pieces/community/browserless/src 下逐文件核对:认证定义、调用层、五个动作实现,以及 README 中的接入前置条件(注册 Browserless 账号、在仪表盘获取 Token 与端点)。
【免费下载链接】activepiecesAI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents项目地址: https://gitcode.com/GitHub_Trending/ac/activepieces
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考