
Civitai Browser Automation Skill 实战指南基于 HTTP 服务与 Playwright 的多会话浏览器自动化【免费下载链接】civitaiA repository of models, textual inversions, and more项目地址: https://gitcode.com/GitHub_Trending/ci/civitai本指南以 civitai 仓库内置的 browser-automation SKILL 文档 为主线完整讲解这套通过 HTTP 服务器驱动 Playwright 的浏览器自动化方案如何启动服务、创建多个并发会话、用 profile 持久化登录态、录制可复用 flow以及结合真实页面与 mockup 做视觉对比。读完你可以在本地复现这套「一人多角色」的交互式探索与回归验证工作流并理解其底层实现服务端逻辑见 server.mjs。一、设计目标与核心思路browser-automation skill 的核心价值在于把浏览器自动化封装成一个常驻的 HTTP 服务而不是一段一次性脚本。这样带来的能力包括交互式探索随时对当前页面执行一小段代码chunk观察页面状态而不是把整个流程写成一个难以调试的大脚本多用户场景同时维护多个浏览器会话session每个会话使用不同的登录身份profile可以验证「创作者发布 → 普通用户可见」这类跨角色流程登录态持久化profile 基于 Playwright 的storageState保存 cookie 与本地存储会话关闭后身份不丢失可复用流程把稳定的操作序列保存为 flow 脚本随时重放。整个 skill 的目录结构如下.claude/skills/browser-automation/ ├── SKILL.md # 使用说明本文主体 ├── server.mjs # HTTP 服务实现 ├── package.json # 依赖与脚本playwright ^1.40.0 └── package-lock.json依赖极其精简——只有 package.json 中声明的playwright并提供了setup脚本npx playwright install chromium用于安装 Chromium 内核。二、快速开始启动服务并跑通第一个会话1. 安装依赖并启动服务器# 首次使用先安装 Playwright 的 chromium cd .claude/skills/browser-automation npm run setup # 启动服务默认端口 9222可加 --port 指定 node .claude/skills/browser-automation/server.mjs 从 server.mjs 的参数解析 可以看到默认端口为9222仅支持--port一个参数。服务启动后会先确保.browser/profiles、.browser/sessions、.browser/flows三个目录存在server.mjs L37-L47并在 stdout 输出一条{type:server_ready,port:9222,...}就绪信号供外部程序解析。2. 核心操作五连# 查看当前可用的登录 profile curl http://localhost:9222/profiles # 创建一个会话指定名字、起始 URL、使用的 profile curl -X POST http://localhost:9222/sessions \ -d {name: test, url: http://localhost:3000, profile: member} # 检查当前页面状态含截图 curl http://localhost:9222/inspect # 在当前页面执行一段代码 curl -X POST http://localhost:9222/chunk \ -d {label: Click button, code: await page.click(\button.submit\);} # 关闭服务器会先关闭所有会话 curl -X POST http://localhost:9222/exit/sessions的请求体支持{ name, url, profile?, headless? }四个字段name缺省为defaulturl必填否则返回 400headless缺省为false即有头模式方便观察。3. 会话路由规则?sessionname当多个会话同时活跃时会话级接口/status、/inspect、/chunk、/navigate、/save-auth、/review必须通过查询参数?sessionname指定目标。其底层选择逻辑见 getSessionOrDefault优先级为显式传入的?sessionname若当前只有一个活跃会话直接使用它若存在名为default的会话使用它否则返回 400并提示Multiple sessions active. Specify which with ?sessionname。也就是说单会话场景下可以省略?session多会话场景必须显式指定否则请求会被拒绝。三、完整端点清单SKILL 文档给出了完整端点表这里补充每个端点的实现要点响应均为 JSON服务端设置了Access-Control-Allow-Origin: *并支持 CORS 预检端点方法描述实现要点server.mjs/profilesGET列出 auth profile 及描述读取.browser/profiles/*.json从 cookie 中提取域名L84-L111/sessionsGET列出活跃会话遍历 session Map返回状态快照/sessionsPOST创建会话{ name, url, profile?, headless? }同名会话存在时先关闭旧会话/sessions/:nameDELETE关闭指定会话关闭浏览器并保存 auth若使用 profile/flowsGET列出已保存的 flow从脚本注释中解析Start URL与Generated/flows/:name/runPOST运行 flow{ profile?, startUrl?, headless? }独立启动浏览器执行L135-L206/statusGET会话状态返回 URL、profile、chunk 数、截图数等/inspectGET页面状态 截图?fullPagetrue截全页触发页面内 evaluate 收集 DOM 摘要/chunkPOST执行代码{ label, code }new Function包装执行并截图留痕/navigatePOST导航{ url, fullPage? }导航后按路径自动命名截图/save-authPOST保存 auth{ profile, description }新 profile 必须带 description/reviewGET回看已记录的 chunk返回会话内全部 chunk 的 index/label/code/exitPOST关闭服务器依次关闭全部会话后退出进程/chunk与/navigate的执行细节值得注意/chunk请求体为{ label, code }label缺省为Chunk N。代码通过new Function(page, return (async () { ... })())包装成异步函数执行L722执行成功后会等待 500ms 再截图并把该 chunk 记录进会话的chunks数组执行失败则捕获异常返回chunk_failed并附带失败时刻的页面截图。/navigate使用waitUntil: domcontentloaded、超时 60s导航后等待 1s再根据 URL path 生成截图名如/models对应navigate-models。四、多用户测试并发会话模拟真实交互多用户场景是这套 skill 的杀手级用例——每个用户一个会话、一个 profile各自保持独立登录态互不干扰。SKILL 文档中的示例是「创作者发布内容普通用户能看到」# 创建两个不同身份的会话 curl -X POST http://localhost:9222/sessions \ -d {name: creator, url: http://localhost:3000, profile: creator} curl -X POST http://localhost:9222/sessions \ -d {name: viewer, url: http://localhost:3000, profile: member} # 创作者执行发布操作指定 sessioncreator curl -X POST http://localhost:9222/chunk?sessioncreator \ -d {label: Publish, code: await page.click(\button.publish\);} # 观众侧跳转并确认内容可见指定 sessionviewer curl -X POST http://localhost:9222/navigate?sessionviewer \ -d {url: http://localhost:3000/models}从实现层面看会话管理由BrowserSession类承担L365-L482每个会话拥有独立的 Playwrightbrowser、context、page实例会话 ID 由randomBytes(4).toString(hex)生成对应.browser/sessions/{id}/目录sessions是一个Map以会话名为 key 保存。创建会话时若同名会话已存在会先关闭旧会话再创建新会话避免端口与资源泄漏。此外会话关闭时会自动把登录态写回 profileL430-L458只要会话启动时指定了profilestop()就会调用context.storageState({ path: profilePath })保存 cookie 与本地存储实现「用完即存、下次即用」。五、Profile 机制登录态的保存与复用1. 管理命令# 列出所有 profile curl http://localhost:9222/profiles # 创建新 profile新 profile 必须带 description curl -X POST http://localhost:9222/save-auth \ -d {profile: moderator, description: User with mod permissions} # 刷新已有 profile 的登录态可省略 description curl -X POST http://localhost:9222/save-auth \ -d {profile: moderator}新 profile 强制要求description的服务端校验见 save-auth 处理逻辑若目标 profile 的元数据不存在且未提供description返回 400 并提示Description required for new profiles已存在的 profile 则可以只传profile字段做登录态刷新。/save-auth会同时更新会话当前使用的 profile并调用context.storageState将登录态落盘。2. 仓库内置的默认 profile 约定SKILL 文档定义了四类测试身份供多角色场景直接引用Profile描述moderator具有内容审核权限的版主creator已发布过内容的成熟创作者member标准登录用户new-user用于新用户引导流程的新账号3. 底层存储结构登录态.browser/profiles/{name}.json即 Playwright 的storageState文件已 gitignore不入库元数据.browser/profiles/profiles.meta.json记录每个 profile 的description、createdAt、updatedAtsetProfileMeta 保证 createdAt 只写一次域名提取/profiles列表会尝试解析 storageState 中第一条 cookie 的domain字段直观显示该 profile 属于哪个站点。六、Flows把稳定操作序列固化为可复用脚本Flow 是保存下来的可复用 Playwright 脚本存放在.browser/flows/*.js。# 列出所有 flow会解析脚本注释中的 Start URL / Generated 元信息 curl http://localhost:9222/flows # 运行 flow指定身份 curl -X POST http://localhost:9222/flows/my-flow/run \ -d {profile: member} # 运行 flow 并覆盖起始 URL curl -X POST http://localhost:9222/flows/my-flow/run \ -d {profile: member, startUrl: http://localhost:3000}从 runFlow 实现 可以看出 flow 的完整执行语义起始 URL 解析优先使用请求中的startUrl否则从脚本注释// Start URL: ...提取两者都拿不到时报错No start URL specified...独立浏览器实例每次运行 flow 都会chromium.launch({ headless })默认有头viewport 固定为1280x720profile 注入若指定了 profile 且文件存在则以storageState方式加载到 context执行方式page.goto(startUrl, { waitUntil: domcontentloaded, timeout: 120000 })后等待 1s再用new Function(page, ...)执行脚本内容page.setDefaultTimeout(30000)兜底页面等待结果返回无论成功失败都会对最终页面做一次 inspect返回{ status: passed | failed, flowName, startUrl, profile, error?, inspection }方便自动化判断。flow 脚本里可以直接使用任意 Playwright 的pageAPI与/chunk的代码片段写法完全一致。七、Playwright 代码片段chunk 的可用 API/chunk与 flow 脚本均在page可用且已默认创建的上下文里执行常用操作await page.click(button.submit); await page.fill(input[nameemail], testexample.com); await page.waitForSelector(h1); await page.goto(https://example.com); const title await page.textContent(h1);一个重要限制服务端通过new Function(page, ...)执行 chunk返回值会被丢弃。因此需要在页面内做断言时建议把结果console.log出来或借助配套的 feature-walkthrough skill 的 capture.mjs——后者把 chunk 包装一层将脚本的返回值写入script.js.out.json并打印从而支持「截图 断言文本」的完整验证。inspect 的智能选择器生成/inspect不只是截图它会在页面内运行一段 evaluate产出结构化的 DOM 摘要inspectPage包括URL 与标题、最多 5 个可见标题、最多 15 个可见按钮、最多 15 个可见链接、最多 10 个可见输入框。每个元素还会附带一个自动生成的可复现选择器生成优先级为#id→[data-testid...]→[name...]链接a[href...]跳过javascript:与#按钮button:has-text(...)文本 30 字符兜底取前两个 class 拼接的tag.class1.class2最后才是裸标签名。可见性判定综合了offsetParent、getBoundingClientRect尺寸以及display/visibility/opacity三个计算样式L291-L297viewport 内判定则比较元素矩形与窗口边界。这套输出可以直接指导下一步page.click(selector)的编写形成「先 inspect 摸清页面再 chunk 精准操作」的探索闭环。八、Mockup 对比设计稿与线上页面逐屏比对前端开发中常见的需求是「把本地 HTML mockup 与真实页面逐屏对比」。由于会话可以加载file://URL这套 skill 直接支持该工作流# 1. 用 file:// 打开本地 mockup截全页 curl -X POST http://localhost:9222/sessions \ -d {name: compare, url: file:///C:/path/to/mockup.html} curl http://localhost:9222/inspect?sessioncomparefullPagetrue # 2. 导航到线上页面同样截全页 curl -X POST http://localhost:9222/navigate?sessioncompare \ -d {url: http://localhost:3000/page, fullPage: true} # 3. 到会话目录下对比两张截图fullPagetrue会传给page.screenshot({ fullPage: true })L257-L260生成整页长图。截图文件统一落在会话目录的 screenshots 子目录中命名规则为{三位序号}-{安全化名称}.png其中名称中的非字母数字字符会被替换为-并截断到 50 字符getScreenshotPath。九、文件位置与数据布局所有运行时产物都收敛在仓库根目录的.browser/下SKILL 文档明确列出了各文件的职责路径内容是否入库.browser/flows/*.js可复用的 Playwright flow 脚本是.browser/profiles/profiles.meta.jsonprofile 元数据描述、创建/更新时间是.browser/profiles/*.json各 profile 的登录态storageState否gitignored.browser/sessions/{id}/screenshots/每个会话的截图否运行时产物十、与周边 skill 的协作browser-automation 不是孤岛仓库内多个 skill 都以它为底座feature-walkthrough skill用 browser-automation 的「一会话一用户」能力驱动功能遍历每个关键状态并截图拼装成可供评审的 walkthrough 页面。它明确提示服务端执行 chunk 会丢弃返回值因此配套的 capture.mjs 负责把脚本返回值落盘同时建议每个脚本开头显式page.goto目标 URL会话会保留上一次 chunk 的页面位置并在导航后先清除粘性横幅sticky banner 会拦截点击导致 Playwright 重试 30 秒后报subtree intercepts pointer eventscomponent-preview skill同样调用 browser-automation 来截取组件裁剪图说明这套服务在仓库内已被视为通用的「截图与页面驱动」基础设施。十一、常见问题与使用建议多会话报 400报错信息会列出当前活跃会话名按提示在请求上加?sessionname即可新 profile 保存失败/save-auth创建新 profile 必须携带description这是服务端强校验不是可选项截图命名截图序号从 1 递增、按 3 位补零001-...同一会话内保证顺序稳定便于按时间轴回放超时配置页面初始导航超时 120s创建会话/ 60snavigate元素等待默认 30s长加载页面可在 chunk 里显式waitForSelector等待关键节点身份隔离profile 的 storageState 文件已 gitignore切勿手动提交避免泄露真实登录态涉及真实账号的截图也应谨慎分享feature-walkthrough skill 对此有专门提醒。这套「HTTP 服务 Playwright profile flow」的组合把浏览器自动化从「一次性脚本」升级为「可交互、可复用、可多角色并行」的工程化工具是 civitai 仓库中值得直接借鉴的自动化基础设施。进一步研究可直接阅读 SKILL.md 与 server.mjs 源码全文。【免费下载链接】civitaiA repository of models, textual inversions, and more项目地址: https://gitcode.com/GitHub_Trending/ci/civitai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考