mooncat-browser
v0.4.1
Published
浏览器自动化工具包:可独立启动的本地服务(browserd)+ JS/TS client。双路由(WebPlater 扩展 / CDP),不依赖 mooncat 总发行体。
Maintainers
Readme
@mooncat/browser
浏览器自动化工具包:可独立启动的本地服务(browserd)+ JS/TS client。 双路由(WebPlater 扩展 / CDP),控制宿主 Chrome(用户看得见的本地 Chrome,不是无头集群)。
@mooncat/browser 是从 mooncat 总发行体中拆出的浏览器能力,
不依赖 mooncat 总发行体、MOONCAT_DIST、workspace 结构或 PM2。
它只管 browser 自己。
它是什么
你的代码 (BrowserClient)
│ HTTP JSON-RPC (:17322)
▼
browserd (常驻服务,持有会话)
│ 双路由自动选择
├── WebPlater 扩展路(无 CDP 端口,对高危平台更安全)
└── CDP 路(Playwright connectOverCDP 直连宿主 Chrome)- browserd 是真正持有 Chrome 的常驻进程。open 一次,跨多步复用 handle,满意前不 close。
- handle 是纯数据:拿到
pageHandle就直接用,所有页面动作走operate({ pageHandle, action, params })。 绝不判断路由(extension/CDP 是 browserd 内部的事)。 - CDP 路用
playwright-core:通过connectOverCDP连接你机器上的 Chrome, 从不下载自带浏览器(install 不会拉几百 MB 的 chromium)。
安装
全局服务
npm i -g @mooncat/browser
mooncat-browser start --port 17322 --profile D:\browser-profile项目内 client
npm i @mooncat/browser快速开始
import { BrowserClient } from "@mooncat/browser";
const browser = new BrowserClient({ baseUrl: "http://127.0.0.1:17322" });
// 1. 探测服务是否就绪
const h = await browser.health();
if (!h?.browserOpen) await browser.open({ headless: false });
// 2. 打开页面(newTab 返回 TabInfo,operate 传 tab.pageHandle)
const tab = await browser.newTab({ url: "https://example.com" });
// 3. 页面动作(40+ 个 action:click/fill/goto/snapshot/evaluate/...)
await browser.operate({
pageHandle: tab.pageHandle,
action: "click",
params: { selector: "button" },
});
// 4. 满意后再 close(保留登录态)
await browser.close();CLI
mooncat-browser start [--port 17322] [--profile D:\p] [--chrome path] [--health-port 17440]
mooncat-browser health [--port 17322]
mooncat-browser stop [--port 17322]
mooncat-browser open --url <url> [--port 17322]
mooncat-browser install-extension| 命令 | 说明 |
| --- | --- |
| start | 启动 browser 服务(wrapper + browserd 常驻;browserd 崩溃自动重启) |
| health | 探测 browserd 是否就绪 + 是否已 open |
| stop | graceful 停止(关闭 Chrome + 退出 wrapper,不重启;保留登录态) |
| open | 连接已运行的服务,打开/复用浏览器并导航到 URL |
| install-extension | 打印 WebPlater 扩展路径 + Chrome "Load unpacked" 指引 |
配置
优先级(高 → 低):CLI 参数 > 环境变量 > 配置文件 > 默认值。
环境变量
| 变量 | 含义 | 默认 |
| --- | --- | --- |
| MOONCAT_BROWSERD_PORT | browserd RPC 端口(client 连这里) | 17322 |
| MOONCAT_BROWSER_PORT | wrapper health 端口 | 17440 |
| MOONCAT_BROWSER_PROFILE | Chrome user-data-dir | <appData>/mooncat-browser/profile |
| MOONCAT_BROWSER_CHROME | Chrome 可执行文件路径 | 自动探测 |
| MOONCAT_BROWSER_CONFIG | 配置文件路径 | <appData>/mooncat-browser/config.json |
配置文件(JSON)
- Windows:
%LOCALAPPDATA%\mooncat-browser\config.json - macOS:
~/Library/Application Support/mooncat-browser/config.json - Linux:
$XDG_DATA_HOME/mooncat-browser/config.json(默认~/.local/share/...)
{
"rpcPort": 17322,
"healthPort": 17440,
"profile": "D:\\browser-profile",
"chromePath": "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
}端口语义
--port/MOONCAT_BROWSERD_PORT(默认 17322)= RPC 端口,browserd 监听这里, 也是BrowserClient连接的端口。mooncat-browser start --port 17322后, client 用baseUrl: "http://127.0.0.1:17322"。--health-port/MOONCAT_BROWSER_PORT(默认 17440)= wrapper health 端口, 供mooncat-browser health(探测 wrapper)/stop(POST /shutdown)/ 外部监控用。
公开 API(BrowserClient)
health() 探测 browserd(返回 /health 或 null)
open(options?) 打开浏览器(双路由自动选择 extension/cdp)
newTab(options?) 新建/复用标签页(同 host 默认复用)
listTabs() 列出所有标签页
operate(params) 在页面上执行动作(40+ 个 action)
getCookies(filter?) 获取 cookies
setCookies(cookies) 设置 cookies
clearCookies(filter?) 清除 cookies
close() 关闭浏览器(graceful)
reuseTab(options) 按 url 复用 tab(高危平台避免重开)
listDownloads(limit?) 列出最近下载(仅 extension 模式)
getDownload(id) 查单个下载(仅 extension 模式)
waitForDownload(opts) 轮询等下载完成(仅 extension 模式)
waitFor(opts) 通用等待 selector/text 出现(带刷新重试)类型契约见 src/protocol.ts,JSON Schema 草稿见 schemas/。
测试分层、action 有效性验证、iframe/frameId 与 evaluate 使用边界见 docs/TESTING.md。
operate 的 action 清单
operate({ pageHandle, action, params }) 支持 40+ 个 action,覆盖导航 / 交互 / 读取 / 等待 / 存储 / 截图。
完整清单见 browser-op/backend/browserd.cjs 的 rpcOperate。常用:
- 导航:
gotogoBackgoForwardreloadstatuswaitForLoadStatewaitForURL - 交互:
clickfilltypepresshoverfocuscheckuncheckselectOptiondblclickdragToclickAtclickByText - 读取:
innerHTMLinnerTexttextContentgetAttributeinputValueboundingBoxcountsnapshot - 等待:
waitForSelectorwaitForFunctionwaitForTimeout - 存储:
getLocalStoragesetLocalStorageremoveLocalStorageclearLocalStorage - 截图:
screenshot - 进阶:
evaluateoperateSequencelocateVisibleTextsetInputFilessetDialogHandler
selector 语法:CSS / aria-ref=eN(来自 snapshot 的 ref)/ .cls>>nth(n) / .cls>>last。
路由(extension / cdp)
open({ routeMode }) 自动探测:
- WebPlater 扩展已装且活 →
mode: "extension"(不暴露 CDP 端口,对淘宝/京东等高危平台更安全) - 未装 / 被禁用 / 不响应 →
mode: "cdp"(带调试端口,用playwright-core连)
装扩展后需重启浏览器(close() + open())才会切到 extension 路。
要安装扩展:mooncat-browser install-extension(Load unpacked 指向包内 browser-op/webplater/dist/chrome-mv3)。
目录结构
mooncat-browser/
package.json @mooncat/browser
tsconfig.json
src/ TypeScript 源码(编译到 dist/)
cli.ts mooncat-browser 命令
server.ts 服务包装层(spawn browserd + health 代理 + graceful shutdown)
client.ts BrowserClient(HTTP JSON-RPC client)
protocol.ts 公共类型契约
config.ts 配置解析(CLI > env > file > default)
browser-op/ 双路由核心(CJS,原样来自 mooncat libs/browser)
backend/browserd.cjs 常驻 daemon(HTTP RPC :17322)
index.cjs BrowserOp 双路由总入口
cdp/ extension/ web/ 各路由实现
webplater/ WebPlater Chrome 扩展(wxt 构建)
schemas/ browser.* JSON Schema(API 草稿)
scripts/clean.mjs
tests/ 单元/集成测试(vitest)开发
npm install # 装根依赖(含 playwright-core,不下载浏览器)
npm run build:ts # 编译 src/ -> dist/
npm run build:extension # 构建 WebPlater 扩展(需 pnpm + 网络)
npm run build # = build:ts + build:extension
npm test # vitest(不依赖真实 Chrome)
npm run typecheck
build:extension需要pnpm。若只改 TS 层(client/server/cli/config),npm run build:ts即可。 扩展构建产物在browser-op/webplater/dist/chrome-mv3,随包发布以便install-extension开箱即用。
设计原则
- handle 是纯数据——绝不
if (ph.mode === 'cdp'),路由不泄漏。 - 会话长生命周期——
open()一次跨多步复用,满意前不close()(启动 Chrome 慢,反复开关丢登录态)。 - 步进式 co-work——一步一确认,中间产物落盘。
- 出错就 STOP——报告具体错误,等指示;绝不强杀 Chrome(丢登录态/留僵尸端口)。
License
MIT
