@xbrowser/cli 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +858 -0
- package/dist/admin-6UTU2RZ2.js +281 -0
- package/dist/admin-MDGF4CET.js +285 -0
- package/dist/admin-RPJJ5CAF.js +282 -0
- package/dist/browser-GWBH6OJK.js +46 -0
- package/dist/browser-I2HJZ7IP.js +48 -0
- package/dist/browser-R7B255ML.js +46 -0
- package/dist/chunk-2ONMTDLK.js +2050 -0
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/chunk-43VX3TYN.js +83 -0
- package/dist/chunk-ATFTAKMN.js +267 -0
- package/dist/chunk-DESA2KMG.js +77 -0
- package/dist/chunk-DTJRVA76.js +206 -0
- package/dist/chunk-F3ZWFCJJ.js +2051 -0
- package/dist/chunk-FF5WHQHN.js +135 -0
- package/dist/chunk-HINTG75P.js +77 -0
- package/dist/chunk-KDYXFLAC.js +1503 -0
- package/dist/chunk-KTSQU4QT.js +29 -0
- package/dist/chunk-L53IDAWK.js +68 -0
- package/dist/chunk-M7CMBPCA.js +100 -0
- package/dist/chunk-NFGO7J2I.js +29 -0
- package/dist/chunk-OLB6UJ25.js +438 -0
- package/dist/chunk-OPRXFZVE.js +52 -0
- package/dist/chunk-RS6YYWTK.js +685 -0
- package/dist/chunk-VEDJ5XSQ.js +196 -0
- package/dist/chunk-VEKPHQBR.js +47 -0
- package/dist/chunk-VUJDJCIN.js +437 -0
- package/dist/chunk-YEN2ODUI.js +14 -0
- package/dist/chunk-ZZ2TFWIV.js +1382 -0
- package/dist/cli.js +11012 -0
- package/dist/convert-4DUWZIKH.js +205 -0
- package/dist/convert-EKQVHKB4.js +11 -0
- package/dist/daemon-client-3IJD6X4B.js +59 -0
- package/dist/daemon-client-GX2UYIW4.js +241 -0
- package/dist/daemon-client-XWSSQBEA.js +58 -0
- package/dist/daemon-main.js +9910 -0
- package/dist/extract-EGRXZSSK.js +67 -0
- package/dist/extract-JUOQQX4V.js +11 -0
- package/dist/filter-OLAE26HN.js +51 -0
- package/dist/filter-VID2GGZ7.js +9 -0
- package/dist/human-interaction-QPHNDD76.js +8 -0
- package/dist/index.d.ts +2313 -0
- package/dist/index.js +13839 -0
- package/dist/marketplace-FCVN5OTZ.js +706 -0
- package/dist/marketplace-FPT5YLKB.js +351 -0
- package/dist/marketplace-W545W4FR.js +706 -0
- package/dist/network-store-2S5HATEV.js +194 -0
- package/dist/network-store-BN6QEZ7R.js +196 -0
- package/dist/network-store-YAF5OIBH.js +12 -0
- package/dist/parse-action-dsl-DRSPBALP.js +72 -0
- package/dist/parse-action-dsl-T3DYC33D.js +74 -0
- package/dist/proxy-WKGUCH2C.js +7 -0
- package/dist/session-recorder-ILSSV2UC.js +6 -0
- package/dist/session-recorder-XET3DNML.js +7 -0
- package/package.json +111 -0
package/README.md
ADDED
|
@@ -0,0 +1,858 @@
|
|
|
1
|
+
# xbrowser
|
|
2
|
+
|
|
3
|
+
> Self-contained browser automation CLI — navigate, click, fill forms, screenshot, web scraping, record & replay. A Playwright/Puppeteer alternative for CLI-first workflows.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/dyyz1993/xbrowser/actions)
|
|
6
|
+
[](https://codecov.io/gh/dyyz1993/xbrowser)
|
|
7
|
+
[](https://www.npmjs.com/package/@xbrowser/cli)
|
|
8
|
+
[](https://opensource.org/licenses/MIT)
|
|
9
|
+
|
|
10
|
+
## 特性
|
|
11
|
+
|
|
12
|
+
- **35+ 浏览器命令** — 导航、交互、查询、存储、截图,覆盖常见自动化场景
|
|
13
|
+
- **命令链** — 用 `&&`、`,`、`+`、`->`、`;` 串联多个命令,一行搞定复杂流程
|
|
14
|
+
- **管道 & Heredoc** — 支持 stdin 管道和 heredoc 批量执行
|
|
15
|
+
- **录制 / 回放** — 录制浏览器操作为 YAML,随时回放,可转换为 JS/Python/Bash 脚本
|
|
16
|
+
- **插件系统** — 基于 `@dyyz1993/xcli-core`,用 TypeScript 编写站点插件
|
|
17
|
+
- **CDP 连接** — 连接已运行的 Chrome/Chromium,无需重新启动浏览器
|
|
18
|
+
- **会话管理** — 多会话并行,独立上下文
|
|
19
|
+
- **Daemon 模式** — 后台常驻,快速响应
|
|
20
|
+
|
|
21
|
+
## 快速开始
|
|
22
|
+
|
|
23
|
+
### 安装
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g @xbrowser/cli
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 最低要求
|
|
30
|
+
|
|
31
|
+
- Node.js >= 18
|
|
32
|
+
- Chromium 浏览器(默认路径 `/Applications/Chromium.app/Contents/MacOS/Chromium`,可通过环境变量 `XBROWSER_CHROMIUM_PATH` 自定义)
|
|
33
|
+
|
|
34
|
+
### 第一次使用
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# 打开浏览器,导航到页面
|
|
38
|
+
xbrowser session open https://example.com
|
|
39
|
+
|
|
40
|
+
# 获取页面标题
|
|
41
|
+
xbrowser title
|
|
42
|
+
# 输出: Example Domain
|
|
43
|
+
|
|
44
|
+
# 获取页面文本
|
|
45
|
+
xbrowser text
|
|
46
|
+
|
|
47
|
+
# 截图(保存到当前目录)
|
|
48
|
+
xbrowser screenshot
|
|
49
|
+
|
|
50
|
+
# 关闭会话
|
|
51
|
+
xbrowser session close
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 单行命令链
|
|
55
|
+
|
|
56
|
+
不需要先 `session open`,命令链会自动启动浏览器并在执行完毕后关闭:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# 用逗号分隔
|
|
60
|
+
xbrowser "goto https://example.com , title , text"
|
|
61
|
+
|
|
62
|
+
# 用 + 分隔
|
|
63
|
+
xbrowser "goto https://example.com + screenshot"
|
|
64
|
+
|
|
65
|
+
# 用 -> 分隔
|
|
66
|
+
xbrowser "goto https://example.com -> title -> click '#more'"
|
|
67
|
+
|
|
68
|
+
# 用 && 分隔(前一步失败则停止)
|
|
69
|
+
xbrowser "goto https://example.com && title && screenshot"
|
|
70
|
+
|
|
71
|
+
# 用 || 分隔(前一步成功则跳过后续)
|
|
72
|
+
xbrowser "goto https://example.com || goto https://fallback.com"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 管道
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
echo "goto https://example.com" | xbrowser
|
|
79
|
+
echo "title" | xbrowser
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Heredoc
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
xbrowser <<EOF
|
|
86
|
+
goto https://example.com
|
|
87
|
+
title
|
|
88
|
+
click "a"
|
|
89
|
+
text
|
|
90
|
+
EOF
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 从文件执行
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# 创建脚本文件 commands.txt
|
|
97
|
+
cat > commands.txt << 'EOF'
|
|
98
|
+
goto https://example.com
|
|
99
|
+
title
|
|
100
|
+
text
|
|
101
|
+
screenshot
|
|
102
|
+
EOF
|
|
103
|
+
|
|
104
|
+
# 执行
|
|
105
|
+
xbrowser run commands.txt
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### -e / --eval 模式
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
xbrowser -e "goto https://example.com" -e "title"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### CDP 连接(连接已运行的浏览器)
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# 通过 WebSocket URL 连接
|
|
118
|
+
xbrowser --cdp ws://localhost:9222 "goto https://example.com , title"
|
|
119
|
+
|
|
120
|
+
# 通过端口号连接
|
|
121
|
+
xbrowser --cdp 9222 "goto https://example.com , title"
|
|
122
|
+
|
|
123
|
+
# 自动发现
|
|
124
|
+
xbrowser --cdp auto "goto https://example.com , title"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 所有命令
|
|
128
|
+
|
|
129
|
+
### 全局参数
|
|
130
|
+
|
|
131
|
+
| 参数 | 说明 |
|
|
132
|
+
|------|------|
|
|
133
|
+
| `--json` | JSON 格式输出 |
|
|
134
|
+
| `--yaml` | YAML 格式输出 |
|
|
135
|
+
| `--session <name>` | 指定会话名称(默认 `default`) |
|
|
136
|
+
| `--cdp <endpoint>` | CDP 连接地址 |
|
|
137
|
+
| `-e, --eval <cmd>` | 执行命令(可多次使用) |
|
|
138
|
+
| `-h, --help` | 显示帮助 |
|
|
139
|
+
| `-v, --version` | 显示版本 |
|
|
140
|
+
|
|
141
|
+
### 会话管理
|
|
142
|
+
|
|
143
|
+
| 命令 | 说明 | 示例 |
|
|
144
|
+
|------|------|------|
|
|
145
|
+
| `session open <url>` | 打开浏览器并创建会话 | `xbrowser session open https://example.com` |
|
|
146
|
+
| `session open <url> --name work` | 以指定名称创建会话 | `xbrowser session open https://example.com --name work` |
|
|
147
|
+
| `session close` | 关闭当前会话 | `xbrowser session close` |
|
|
148
|
+
| `session close --name work` | 关闭指定会话 | `xbrowser session close --name work` |
|
|
149
|
+
| `session close --all` | 关闭所有会话 | `xbrowser session close --all` |
|
|
150
|
+
| `session list` | 列出所有活跃会话 | `xbrowser session list` |
|
|
151
|
+
| `session kill [--name <n>]` | 强制终止会话 | `xbrowser session kill --name work` |
|
|
152
|
+
|
|
153
|
+
### 页面导航
|
|
154
|
+
|
|
155
|
+
| 命令 | 说明 | 示例 |
|
|
156
|
+
|------|------|------|
|
|
157
|
+
| `goto <url>` | 导航到指定 URL | `xbrowser goto https://example.com` |
|
|
158
|
+
| `goto <url> --waitUntil networkidle` | 指定等待条件 | `xbrowser goto https://example.com --waitUntil networkidle` |
|
|
159
|
+
| `back` | 浏览器后退 | `xbrowser back` |
|
|
160
|
+
| `forward` | 浏览器前进 | `xbrowser forward` |
|
|
161
|
+
| `refresh` | 刷新当前页面 | `xbrowser refresh` |
|
|
162
|
+
| `title` | 获取页面标题 | `xbrowser title` |
|
|
163
|
+
| `url` | 获取当前 URL | `xbrowser url` |
|
|
164
|
+
|
|
165
|
+
`goto` 的 `--waitUntil` 可选值:`load`、`domcontentloaded`(默认)、`networkidle`。
|
|
166
|
+
|
|
167
|
+
### 元素交互
|
|
168
|
+
|
|
169
|
+
| 命令 | 说明 | 示例 |
|
|
170
|
+
|------|------|------|
|
|
171
|
+
| `click <selector>` | 点击元素 | `xbrowser click "#btn"` |
|
|
172
|
+
| `click <selector> --button right` | 右键点击 | `xbrowser click "#btn" --button right` |
|
|
173
|
+
| `click <selector> --clickCount 2` | 多次点击 | `xbrowser click "#btn" --clickCount 2` |
|
|
174
|
+
| `fill <selector> <value>` | 填写输入框(清空后输入) | `xbrowser fill "#input" "hello"` |
|
|
175
|
+
| `type <selector> <text>` | 逐字输入文本 | `xbrowser type "#search" "关键词"` |
|
|
176
|
+
| `type <selector> <text> --delay 50` | 按键间隔 50ms | `xbrowser type "#search" "关键词" --delay 50` |
|
|
177
|
+
| `press <selector> <key>` | 按下按键 | `xbrowser press body Enter` |
|
|
178
|
+
| `select <selector> <value>` | 选择下拉选项 | `xbrowser select "#dropdown" "option1"` |
|
|
179
|
+
| `check <selector>` | 勾选复选框 | `xbrowser check "#agree"` |
|
|
180
|
+
| `hover <selector>` | 鼠标悬停 | `xbrowser hover "#menu"` |
|
|
181
|
+
| `dblclick <selector>` | 双击元素 | `xbrowser dblclick "#item"` |
|
|
182
|
+
|
|
183
|
+
**选择器语法**:支持 CSS 选择器(`#id`、`.class`、`div > p`)和文本选择器(`text=登录`)。
|
|
184
|
+
|
|
185
|
+
### 鼠标控制
|
|
186
|
+
|
|
187
|
+
| 命令 | 说明 | 示例 |
|
|
188
|
+
|------|------|------|
|
|
189
|
+
| `mouse move <x> <y>` | 移动鼠标到坐标 | `xbrowser "mouse move 100 200"` |
|
|
190
|
+
| `mouse move <x> <y> --steps 10` | 分步移动 | `xbrowser "mouse move 100 200 --steps 10"` |
|
|
191
|
+
| `mouse click <x> <y>` | 在坐标处点击 | `xbrowser "mouse click 100 200"` |
|
|
192
|
+
| `mouse click <x> <y> --button right` | 右键点击坐标 | `xbrowser "mouse click 100 200 --button right"` |
|
|
193
|
+
| `mouse dblclick <x> <y>` | 在坐标处双击 | `xbrowser "mouse dblclick 100 200"` |
|
|
194
|
+
|
|
195
|
+
### 滚动
|
|
196
|
+
|
|
197
|
+
| 命令 | 说明 | 示例 |
|
|
198
|
+
|------|------|------|
|
|
199
|
+
| `scroll down` | 向下滚动(默认 500px) | `xbrowser scroll down` |
|
|
200
|
+
| `scroll up` | 向上滚动 | `xbrowser scroll up` |
|
|
201
|
+
| `scroll left` | 向左滚动 | `xbrowser scroll left` |
|
|
202
|
+
| `scroll right` | 向右滚动 | `xbrowser scroll right` |
|
|
203
|
+
| `scroll down --distance 1000` | 自定义距离 | `xbrowser scroll down --distance 1000` |
|
|
204
|
+
| `scroll down --selector "#container"` | 滚动指定元素 | `xbrowser scroll down --selector "#container"` |
|
|
205
|
+
|
|
206
|
+
### 等待
|
|
207
|
+
|
|
208
|
+
| 命令 | 说明 | 示例 |
|
|
209
|
+
|------|------|------|
|
|
210
|
+
| `wait <selector>` | 等待元素出现(默认 30s) | `xbrowser wait "#content"` |
|
|
211
|
+
| `wait <selector> --timeout 5000` | 自定义超时 | `xbrowser wait "#content" --timeout 5000` |
|
|
212
|
+
| `wait <selector> --state hidden` | 等待元素消失 | `xbrowser wait "#loading" --state hidden` |
|
|
213
|
+
| `waitForTimeout <ms>` | 等待指定时间 | `xbrowser waitForTimeout 2000` |
|
|
214
|
+
|
|
215
|
+
`wait` 的 `--state` 可选值:`visible`(默认)、`hidden`、`attached`、`detached`。
|
|
216
|
+
|
|
217
|
+
### 页面查询
|
|
218
|
+
|
|
219
|
+
| 命令 | 说明 | 示例 |
|
|
220
|
+
|------|------|------|
|
|
221
|
+
| `html` | 获取页面 HTML | `xbrowser html` |
|
|
222
|
+
| `html --selector "#main"` | 获取指定元素 HTML | `xbrowser html --selector "#main"` |
|
|
223
|
+
| `text` | 获取页面文本 | `xbrowser text` |
|
|
224
|
+
| `text --selector "#article"` | 获取指定元素文本 | `xbrowser text --selector "#article"` |
|
|
225
|
+
| `getProperty <selector> <property>` | 获取元素属性 | `xbrowser getProperty "#link" href` |
|
|
226
|
+
|
|
227
|
+
### 截图与快照
|
|
228
|
+
|
|
229
|
+
| 命令 | 说明 | 示例 |
|
|
230
|
+
|------|------|------|
|
|
231
|
+
| `screenshot` | 截取页面截图 | `xbrowser screenshot` |
|
|
232
|
+
| `screenshot --full-page` | 全页截图 | `xbrowser screenshot --full-page` |
|
|
233
|
+
| `screenshot --type jpeg` | 指定格式 | `xbrowser screenshot --type jpeg` |
|
|
234
|
+
| `snapshot` | 获取页面元素快照(Accessibility tree) | `xbrowser snapshot` |
|
|
235
|
+
| `snapshot --interactive-only` | 仅交互元素 | `xbrowser snapshot --interactive-only` |
|
|
236
|
+
|
|
237
|
+
### DOM 结构
|
|
238
|
+
|
|
239
|
+
| 命令 | 说明 | 示例 |
|
|
240
|
+
|------|------|------|
|
|
241
|
+
| `structure` | 获取 DOM 树(默认 5 层) | `xbrowser structure` |
|
|
242
|
+
| `structure --depth 3` | 自定义深度 | `xbrowser structure --depth 3` |
|
|
243
|
+
| `structure --selector "#nav"` | 从指定元素开始 | `xbrowser structure --selector "#nav"` |
|
|
244
|
+
|
|
245
|
+
### 执行 JavaScript
|
|
246
|
+
|
|
247
|
+
| 命令 | 说明 | 示例 |
|
|
248
|
+
|------|------|------|
|
|
249
|
+
| `eval <expression>` | 执行 JS 表达式 | `xbrowser eval "document.title"` |
|
|
250
|
+
| `eval "1 + 2"` | 计算表达式 | `xbrowser eval "1 + 2"` |
|
|
251
|
+
| `evaluateFn <fn> --args 1 2` | 执行带参数的函数 | `xbrowser evaluateFn "return args[0] + args[1]" --args 1 2` |
|
|
252
|
+
|
|
253
|
+
### 存储
|
|
254
|
+
|
|
255
|
+
| 命令 | 说明 | 示例 |
|
|
256
|
+
|------|------|------|
|
|
257
|
+
| `getCookies` | 获取所有 Cookie | `xbrowser getCookies` |
|
|
258
|
+
| `setCookie <name> <value>` | 设置 Cookie | `xbrowser setCookie session abc123` |
|
|
259
|
+
| `setCookie <name> <value> --domain .example.com` | 指定域名 | `xbrowser setCookie session abc123 --domain .example.com` |
|
|
260
|
+
| `clearCookies` | 清除所有 Cookie | `xbrowser clearCookies` |
|
|
261
|
+
| `getLocalStorage` | 获取所有 localStorage | `xbrowser getLocalStorage` |
|
|
262
|
+
| `getLocalStorage --key token` | 获取指定 key | `xbrowser getLocalStorage --key token` |
|
|
263
|
+
| `setLocalStorage <key> <value>` | 设置 localStorage | `xbrowser setLocalStorage token "abc"` |
|
|
264
|
+
| `clearLocalStorage` | 清除 localStorage | `xbrowser clearLocalStorage` |
|
|
265
|
+
|
|
266
|
+
### 帧操作
|
|
267
|
+
|
|
268
|
+
| 命令 | 说明 | 示例 |
|
|
269
|
+
|------|------|------|
|
|
270
|
+
| `frames` | 列出所有 iframe | `xbrowser frames` |
|
|
271
|
+
| `frame --index 0` | 切换到指定索引的帧 | `xbrowser frame --index 0` |
|
|
272
|
+
| `frame --name iframe-name` | 切换到指定名称的帧 | `xbrowser frame --name content` |
|
|
273
|
+
|
|
274
|
+
### 视口控制
|
|
275
|
+
|
|
276
|
+
| 命令 | 说明 | 示例 |
|
|
277
|
+
|------|------|------|
|
|
278
|
+
| `setViewport <width> <height>` | 设置视口大小 | `xbrowser setViewport 1920 1080` |
|
|
279
|
+
| `setViewport 375 812 --isMobile true` | 移动设备模式 | `xbrowser setViewport 375 812 --isMobile true` |
|
|
280
|
+
|
|
281
|
+
### Daemon 进程
|
|
282
|
+
|
|
283
|
+
| 命令 | 说明 | 示例 |
|
|
284
|
+
|------|------|------|
|
|
285
|
+
| `daemon start` | 启动 daemon | `xbrowser daemon start` |
|
|
286
|
+
| `daemon start --port 9223` | 指定端口启动 | `xbrowser daemon start --port 9223` |
|
|
287
|
+
| `daemon stop` | 停止 daemon | `xbrowser daemon stop` |
|
|
288
|
+
| `daemon status` | 查看 daemon 状态 | `xbrowser daemon status` |
|
|
289
|
+
|
|
290
|
+
### 配置管理
|
|
291
|
+
|
|
292
|
+
| 命令 | 说明 | 示例 |
|
|
293
|
+
|------|------|------|
|
|
294
|
+
| `config list` | 列出所有配置 | `xbrowser config list` |
|
|
295
|
+
| `config get <key>` | 获取配置值 | `xbrowser config get browser.executablePath` |
|
|
296
|
+
| `config set <key> <value>` | 设置配置值 | `xbrowser config set browser.executablePath /usr/bin/chromium` |
|
|
297
|
+
|
|
298
|
+
配置文件位置:`~/.xbrowser/config.json`
|
|
299
|
+
|
|
300
|
+
### 录制与回放
|
|
301
|
+
|
|
302
|
+
| 命令 | 说明 | 示例 |
|
|
303
|
+
|------|------|------|
|
|
304
|
+
| `record start --url <url>` | 开始录制 | `xbrowser record start --url https://example.com` |
|
|
305
|
+
| `record stop --output recording.yaml` | 停止并保存 | `xbrowser record stop --output recording.yaml` |
|
|
306
|
+
| `record status` | 查看录制状态 | `xbrowser record status` |
|
|
307
|
+
| `replay <file>` | 回放录制 | `xbrowser replay recording.yaml` |
|
|
308
|
+
| `replay <file> --slow-mo 100` | 慢速回放 | `xbrowser replay recording.yaml --slow-mo 100` |
|
|
309
|
+
|
|
310
|
+
### 录制后处理
|
|
311
|
+
|
|
312
|
+
| 命令 | 说明 | 示例 |
|
|
313
|
+
|------|------|------|
|
|
314
|
+
| `convert <rec.yaml> <output>` | 转换录制为脚本 | `xbrowser convert recording.yaml out.js` |
|
|
315
|
+
| `convert <rec.yaml> <output.py>` | 生成 Python 脚本 | `xbrowser convert recording.yaml replay.py` |
|
|
316
|
+
| `convert <rec.yaml> <output.sh>` | 生成 Bash 脚本 | `xbrowser convert recording.yaml replay.sh` |
|
|
317
|
+
| `extract <rec.yaml>` | 提取 LLM 摘要 | `xbrowser extract recording.yaml` |
|
|
318
|
+
| `filter <in.yaml> <out.yaml>` | 过滤录制事件 | `xbrowser filter raw.yaml clean.yaml` |
|
|
319
|
+
| `filter <in.yaml> <out.yaml> --exclude scroll,navigate` | 排除事件类型 | `xbrowser filter raw.yaml clean.yaml --exclude scroll,navigate` |
|
|
320
|
+
|
|
321
|
+
### 插件管理
|
|
322
|
+
|
|
323
|
+
| 命令 | 说明 | 示例 |
|
|
324
|
+
|------|------|------|
|
|
325
|
+
| `plugin search <query>` | 搜索 npm 上的插件 | `xbrowser plugin search scraper` |
|
|
326
|
+
| `plugin search <query> --tag <tag>` | 按标签搜索 | `xbrowser plugin search ecommerce --tag scraper` |
|
|
327
|
+
| `plugin search <query> --site <site>` | 按站点搜索 | `xbrowser plugin search amazon --site amazon.com` |
|
|
328
|
+
| `plugin install <path>` | 安装插件 | `xbrowser plugin install xbrowser-plugin-scraper` |
|
|
329
|
+
| `plugin install <path> --name my-plugin` | 指定名称安装 | `xbrowser plugin install ./my-plugin --name my-plugin` |
|
|
330
|
+
| `plugin install <path> --force` | 强制重新安装 | `xbrowser plugin install ./my-plugin --force` |
|
|
331
|
+
| `plugin uninstall <name>` | 卸载插件 | `xbrowser plugin uninstall my-plugin` |
|
|
332
|
+
| `plugin list` | 列出已安装插件 | `xbrowser plugin list` |
|
|
333
|
+
| `plugin list --json` | JSON 格式输出 | `xbrowser plugin list --json` |
|
|
334
|
+
| `plugin reload <name>` | 重新加载插件 | `xbrowser plugin reload my-plugin` |
|
|
335
|
+
|
|
336
|
+
**插件搜索**:
|
|
337
|
+
|
|
338
|
+
使用 `xbrowser plugin search` 在 npm registry 中搜索 xbrowser 兼容插件:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
# 搜索所有插件
|
|
342
|
+
xbrowser plugin search
|
|
343
|
+
|
|
344
|
+
# 按关键词搜索
|
|
345
|
+
xbrowser plugin search scraper
|
|
346
|
+
|
|
347
|
+
# 按标签过滤
|
|
348
|
+
xbrowser plugin search --tag ecommerce
|
|
349
|
+
|
|
350
|
+
# 按站点过滤
|
|
351
|
+
xbrowser plugin search --site amazon.com
|
|
352
|
+
|
|
353
|
+
# 组合搜索
|
|
354
|
+
xbrowser plugin search scraper --tag data-extraction --limit 10
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
搜索结果会显示插件名称、描述、版本、作者、标签、主页和 npm 链接。
|
|
358
|
+
|
|
359
|
+
### 创建插件
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
# 从模板创建
|
|
363
|
+
xbrowser create my-plugin --template static
|
|
364
|
+
xbrowser create my-plugin --template dynamic
|
|
365
|
+
xbrowser create my-plugin --template login
|
|
366
|
+
xbrowser create my-plugin --template api
|
|
367
|
+
|
|
368
|
+
# 强制覆盖已有目录
|
|
369
|
+
xbrowser create my-plugin --template static --force
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
可用模板:
|
|
373
|
+
|
|
374
|
+
| 模板 | 说明 | 适用场景 |
|
|
375
|
+
|------|------|----------|
|
|
376
|
+
| `static` | 静态页面采集插件 | 简单页面数据提取 |
|
|
377
|
+
| `dynamic` | 动态交互插件 | 导航 + 交互的复杂场景 |
|
|
378
|
+
| `login` | 带登录/登出的插件 | 需要登录才能访问的站点 |
|
|
379
|
+
| `api` | API 集成插件 | 调用外部 API |
|
|
380
|
+
|
|
381
|
+
## 命令链语法
|
|
382
|
+
|
|
383
|
+
命令链是 xbrowser 的核心特性,允许在一行中串联多个命令:
|
|
384
|
+
|
|
385
|
+
| 分隔符 | 语义 | 示例 |
|
|
386
|
+
|--------|------|------|
|
|
387
|
+
| `&&` | 前一步成功才继续 | `goto https://example.com && title && screenshot` |
|
|
388
|
+
| `,` | 顺序执行 | `goto https://example.com , title , text` |
|
|
389
|
+
| `+` | 顺序执行 | `goto https://example.com + title + screenshot` |
|
|
390
|
+
| `->` | 顺序执行 | `goto https://example.com -> title -> click '#btn'` |
|
|
391
|
+
| `;` | 分割管线(前一个完成后开始下一个) | `goto https://example.com ; goto https://other.com` |
|
|
392
|
+
| `\|\|` | 前一步成功则跳过后续 | `goto https://example.com \|\| goto https://fallback.com` |
|
|
393
|
+
|
|
394
|
+
**注意**:命令链中如果包含特殊字符(如 `#`、`>`),需要用引号包裹整个命令链或对单个参数加引号。
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
# 正确 — 整体引号
|
|
398
|
+
xbrowser "goto https://example.com , click '#btn'"
|
|
399
|
+
|
|
400
|
+
# 正确 — 参数引号
|
|
401
|
+
xbrowser goto https://example.com , click '#btn'
|
|
402
|
+
|
|
403
|
+
# 错误 — # 在 shell 中是注释
|
|
404
|
+
xbrowser goto https://example.com , click #btn
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## Scope 体系
|
|
408
|
+
|
|
409
|
+
xbrowser 使用四级 Scope 控制命令的执行上下文:
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
project > browser > page > element
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
| Scope | 说明 | 需要的条件 | 典型命令 |
|
|
416
|
+
|-------|------|------------|----------|
|
|
417
|
+
| **project** | 项目级别 | 无 | config, daemon, plugin |
|
|
418
|
+
| **browser** | 浏览器级别 | 浏览器实例 | setViewport, session |
|
|
419
|
+
| **page** | 页面级别 | 活跃页面 | goto, wait, scroll, screenshot |
|
|
420
|
+
| **element** | 元素级别 | 页面中的元素 | click, fill, type, hover |
|
|
421
|
+
|
|
422
|
+
命令执行前会自动检查 Scope 是否满足。不满足时会提示:
|
|
423
|
+
|
|
424
|
+
```
|
|
425
|
+
Error: 需要活跃的页面,请先执行 xbrowser session open <url>
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
## 插件系统
|
|
429
|
+
|
|
430
|
+
### 插件加载顺序
|
|
431
|
+
|
|
432
|
+
xbrowser 按以下顺序扫描插件目录:
|
|
433
|
+
|
|
434
|
+
1. `./.xcli/plugins/` — 当前目录
|
|
435
|
+
2. `../.xcli/plugins/` — 父目录
|
|
436
|
+
3. `~/.xcli/plugins/` — 用户全局目录
|
|
437
|
+
4. `~/.xbrowser/plugins/` — xbrowser 专属全局目录
|
|
438
|
+
|
|
439
|
+
同名插件:本地优先于全局,后加载覆盖先加载。
|
|
440
|
+
|
|
441
|
+
### 插件结构
|
|
442
|
+
|
|
443
|
+
```
|
|
444
|
+
.xcli/plugins/<plugin-name>/
|
|
445
|
+
├── index.ts # 插件入口(必须)
|
|
446
|
+
├── package.json # 包配置(必须,至少含 name)
|
|
447
|
+
└── README.md # 说明文档(推荐)
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### 插件入口示例
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
import { z } from 'zod';
|
|
454
|
+
import type { XCLIAPI } from '@dyyz1993/xcli-core';
|
|
455
|
+
|
|
456
|
+
export default function (xcli: XCLIAPI): void {
|
|
457
|
+
const site = xcli.createSite({
|
|
458
|
+
name: 'my-plugin',
|
|
459
|
+
url: 'https://example.com',
|
|
460
|
+
description: '我的第一个插件',
|
|
461
|
+
requiresLogin: false,
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
site.command('scrape', {
|
|
465
|
+
description: '采集页面数据',
|
|
466
|
+
scope: 'browser',
|
|
467
|
+
parameters: z.object({
|
|
468
|
+
selector: z.string().optional().default('body'),
|
|
469
|
+
}),
|
|
470
|
+
examples: [
|
|
471
|
+
{ cmd: 'xbrowser my-plugin scrape', description: '采集页面内容' },
|
|
472
|
+
],
|
|
473
|
+
handler: async (params, ctx) => {
|
|
474
|
+
const page = (ctx as Record<string, unknown>).page as import('playwright').Page;
|
|
475
|
+
if (!page) throw new Error('需要浏览器页面');
|
|
476
|
+
|
|
477
|
+
const text = await page.evaluate(
|
|
478
|
+
(sel: string) => document.querySelector(sel)?.textContent ?? '',
|
|
479
|
+
params.selector
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
return {
|
|
483
|
+
data: { text },
|
|
484
|
+
tips: ['采集完成'],
|
|
485
|
+
};
|
|
486
|
+
},
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
// 可选:登录/登出
|
|
490
|
+
site.login(async (ctx) => {
|
|
491
|
+
const page = (ctx as Record<string, unknown>).page as import('playwright').Page;
|
|
492
|
+
if (!page) return;
|
|
493
|
+
await page.goto('https://example.com/login');
|
|
494
|
+
await page.fill('#username', 'user');
|
|
495
|
+
await page.fill('#password', 'pass');
|
|
496
|
+
await page.click('#submit');
|
|
497
|
+
await ctx.storage.set('auth_token', { loggedIn: true, at: Date.now() });
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
site.logout(async (ctx) => {
|
|
501
|
+
await ctx.storage.delete('auth_token');
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### 内置插件
|
|
507
|
+
|
|
508
|
+
xbrowser 自带以下插件:
|
|
509
|
+
|
|
510
|
+
| 插件 | 命令 | 说明 |
|
|
511
|
+
|------|------|------|
|
|
512
|
+
| **baidu** | `search`, `hotsearch`, `suggest`, `news` | 百度搜索、热搜、建议词、新闻 |
|
|
513
|
+
| **douyin** | `ai-summary`, `user-info`, `video-info` | 抖音视频信息提取 |
|
|
514
|
+
| **github** | `update-profile`, `add-social-link`, `create-gist`, `get-profile` | GitHub 个人资料管理 |
|
|
515
|
+
| **web-automation** | `extract`, `paginate`, `fill-and-submit`, `screenshot` | 通用 Web 自动化工具 |
|
|
516
|
+
|
|
517
|
+
使用插件命令:
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
# 百度搜索
|
|
521
|
+
xbrowser session open https://www.baidu.com
|
|
522
|
+
xbrowser baidu search --query "AI 编程"
|
|
523
|
+
|
|
524
|
+
# 百度热搜
|
|
525
|
+
xbrowser baidu hotsearch
|
|
526
|
+
|
|
527
|
+
# GitHub 资料获取
|
|
528
|
+
xbrowser session open https://github.com
|
|
529
|
+
xbrowser github get-profile
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
## 录制与回放
|
|
533
|
+
|
|
534
|
+
### 录制
|
|
535
|
+
|
|
536
|
+
```bash
|
|
537
|
+
# 1. 打开会话
|
|
538
|
+
xbrowser session open https://example.com
|
|
539
|
+
|
|
540
|
+
# 2. 开始录制
|
|
541
|
+
xbrowser record start --url https://example.com
|
|
542
|
+
|
|
543
|
+
# 3. 在浏览器中手动操作...
|
|
544
|
+
|
|
545
|
+
# 4. 停止录制,保存为 YAML
|
|
546
|
+
xbrowser record stop --output recordings/my-session.yaml
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
录制文件格式(YAML):
|
|
550
|
+
|
|
551
|
+
```yaml
|
|
552
|
+
id: "abc-123"
|
|
553
|
+
name: "my-session"
|
|
554
|
+
startUrl: "https://example.com"
|
|
555
|
+
startTime: "2025-01-01T00:00:00.000Z"
|
|
556
|
+
duration: 15000
|
|
557
|
+
events:
|
|
558
|
+
- type: click
|
|
559
|
+
selector: "#button"
|
|
560
|
+
tagName: "button"
|
|
561
|
+
timestamp: 1000
|
|
562
|
+
pageState:
|
|
563
|
+
url: "https://example.com"
|
|
564
|
+
title: "Example"
|
|
565
|
+
- type: input
|
|
566
|
+
selector: "#search"
|
|
567
|
+
data:
|
|
568
|
+
value: "hello world"
|
|
569
|
+
timestamp: 3000
|
|
570
|
+
- type: scroll
|
|
571
|
+
data:
|
|
572
|
+
x: 0
|
|
573
|
+
y: 500
|
|
574
|
+
timestamp: 5000
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### 回放
|
|
578
|
+
|
|
579
|
+
```bash
|
|
580
|
+
# 正常速度回放
|
|
581
|
+
xbrowser replay recordings/my-session.yaml
|
|
582
|
+
|
|
583
|
+
# 慢速回放(每步间隔 100ms)
|
|
584
|
+
xbrowser replay recordings/my-session.yaml --slow-mo 100
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### 转换为脚本
|
|
588
|
+
|
|
589
|
+
录制文件可转换为独立的 JS/Python/Bash 脚本:
|
|
590
|
+
|
|
591
|
+
```bash
|
|
592
|
+
# 生成 Node.js + Playwright 脚本
|
|
593
|
+
xbrowser convert recordings/my-session.yaml replay.js
|
|
594
|
+
node replay.js
|
|
595
|
+
|
|
596
|
+
# 生成 Python + Playwright 脚本
|
|
597
|
+
xbrowser convert recordings/my-session.yaml replay.py
|
|
598
|
+
python3 replay.py
|
|
599
|
+
|
|
600
|
+
# 生成 Bash + curl 脚本(基于 CDP)
|
|
601
|
+
xbrowser convert recordings/my-session.yaml replay.sh
|
|
602
|
+
bash replay.sh
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### 提取摘要
|
|
606
|
+
|
|
607
|
+
```bash
|
|
608
|
+
# 分析录制文件,提取关键操作
|
|
609
|
+
xbrowser extract recordings/my-session.yaml
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
输出示例:
|
|
613
|
+
|
|
614
|
+
```
|
|
615
|
+
Analysis Results:
|
|
616
|
+
Start URL: https://example.com
|
|
617
|
+
Total events: 42
|
|
618
|
+
Key events: 8
|
|
619
|
+
|
|
620
|
+
Event type stats:
|
|
621
|
+
click: 5
|
|
622
|
+
input: 2
|
|
623
|
+
keydown: 1
|
|
624
|
+
|
|
625
|
+
Key operations:
|
|
626
|
+
1. click -> #search-box
|
|
627
|
+
2. input -> #search-box
|
|
628
|
+
3. keydown -> Enter
|
|
629
|
+
4. click -> .result-item
|
|
630
|
+
...
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
### 过滤事件
|
|
634
|
+
|
|
635
|
+
```bash
|
|
636
|
+
# 排除滚动和导航事件
|
|
637
|
+
xbrowser filter raw.yaml clean.yaml --exclude scroll,navigate,page_load
|
|
638
|
+
|
|
639
|
+
# 排除悬停事件
|
|
640
|
+
xbrowser filter raw.yaml clean.yaml --exclude hover_enter,hover_leave
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
## 配置
|
|
644
|
+
|
|
645
|
+
### 环境变量
|
|
646
|
+
|
|
647
|
+
所有环境变量使用 `XBROWSER_` 前缀:
|
|
648
|
+
|
|
649
|
+
| 变量 | 说明 | 默认值 |
|
|
650
|
+
|------|------|--------|
|
|
651
|
+
| `XBROWSER_CHROMIUM_PATH` | Chromium 可执行文件路径 | `/Applications/Chromium.app/Contents/MacOS/Chromium` |
|
|
652
|
+
| `XBROWSER_DAEMON_PORT` | Daemon 端口 | `9222` |
|
|
653
|
+
|
|
654
|
+
### 命令行配置
|
|
655
|
+
|
|
656
|
+
```bash
|
|
657
|
+
xbrowser config list
|
|
658
|
+
xbrowser config get browser.executablePath
|
|
659
|
+
xbrowser config set browser.executablePath /usr/bin/chromium
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
配置文件位置:`~/.xbrowser/config.json`
|
|
663
|
+
|
|
664
|
+
## 程序化 API
|
|
665
|
+
|
|
666
|
+
xbrowser 可以作为 Node.js 库使用:
|
|
667
|
+
|
|
668
|
+
```typescript
|
|
669
|
+
import {
|
|
670
|
+
executeCommand,
|
|
671
|
+
executeChain,
|
|
672
|
+
openSession,
|
|
673
|
+
closeSession,
|
|
674
|
+
registerCommand,
|
|
675
|
+
} from '@xbrowser/cli';
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
### 执行单条命令
|
|
679
|
+
|
|
680
|
+
```typescript
|
|
681
|
+
import { openSession, executeCommand, closeAllBrowserSessions } from '@xbrowser/cli';
|
|
682
|
+
|
|
683
|
+
// 创建会话
|
|
684
|
+
await openSession('default', 'https://example.com');
|
|
685
|
+
|
|
686
|
+
// 执行命令
|
|
687
|
+
const result = await executeCommand('title', {}, 'default');
|
|
688
|
+
console.log(result);
|
|
689
|
+
// { success: true, data: { ok: true, title: 'Example Domain' }, duration: 42 }
|
|
690
|
+
|
|
691
|
+
// 清理
|
|
692
|
+
await closeAllBrowserSessions();
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### 执行命令链
|
|
696
|
+
|
|
697
|
+
```typescript
|
|
698
|
+
import { executeChain } from '@xbrowser/cli';
|
|
699
|
+
|
|
700
|
+
const result = await executeChain('goto https://example.com && title && screenshot');
|
|
701
|
+
console.log(result.success); // true
|
|
702
|
+
console.log(result.steps); // [{ command: 'goto', success: true, ... }, ...]
|
|
703
|
+
console.log(result.totalDuration); // 1523
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
### 自定义命令
|
|
707
|
+
|
|
708
|
+
```typescript
|
|
709
|
+
import { registerCommand } from '@xbrowser/cli';
|
|
710
|
+
import { z } from 'zod';
|
|
711
|
+
|
|
712
|
+
registerCommand({
|
|
713
|
+
name: 'countLinks',
|
|
714
|
+
description: 'Count all links on page',
|
|
715
|
+
scope: 'page',
|
|
716
|
+
handler: async (_params, ctx) => {
|
|
717
|
+
const count = await ctx.page.evaluate(() => document.querySelectorAll('a').length);
|
|
718
|
+
return { ok: true, count };
|
|
719
|
+
},
|
|
720
|
+
});
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
完整 API 文档见 [docs/api.md](docs/api.md)。
|
|
724
|
+
|
|
725
|
+
## 实战示例
|
|
726
|
+
|
|
727
|
+
### 示例 1:采集搜索结果
|
|
728
|
+
|
|
729
|
+
```bash
|
|
730
|
+
xbrowser "goto https://www.baidu.com/s?wd=playwright , html --selector '#content_left'"
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
### 示例 2:登录 + 操作
|
|
734
|
+
|
|
735
|
+
```bash
|
|
736
|
+
xbrowser <<EOF
|
|
737
|
+
goto https://example.com/login
|
|
738
|
+
fill "#username" "myuser"
|
|
739
|
+
fill "#password" "mypass"
|
|
740
|
+
click "#submit"
|
|
741
|
+
wait ".dashboard"
|
|
742
|
+
screenshot --full-page
|
|
743
|
+
EOF
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
### 示例 3:多页采集
|
|
747
|
+
|
|
748
|
+
```bash
|
|
749
|
+
xbrowser <<EOF
|
|
750
|
+
goto https://example.com/list
|
|
751
|
+
text --selector ".items"
|
|
752
|
+
scroll down
|
|
753
|
+
wait ".items .item:nth-child(20)"
|
|
754
|
+
text --selector ".items"
|
|
755
|
+
EOF
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
### 示例 4:连接远程浏览器
|
|
759
|
+
|
|
760
|
+
```bash
|
|
761
|
+
# 在远程机器启动 Chrome
|
|
762
|
+
google-chrome --remote-debugging-port=9222
|
|
763
|
+
|
|
764
|
+
# 本地连接并操作
|
|
765
|
+
xbrowser --cdp 9222 "goto https://example.com , title , screenshot"
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
### 示例 5:批量截图
|
|
769
|
+
|
|
770
|
+
```bash
|
|
771
|
+
for url in https://example.com https://github.com https://npmjs.com; do
|
|
772
|
+
xbrowser "goto $url , screenshot --full-page"
|
|
773
|
+
done
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### 示例 6:使用插件采集百度热搜
|
|
777
|
+
|
|
778
|
+
```bash
|
|
779
|
+
xbrowser session open https://www.baidu.com
|
|
780
|
+
xbrowser baidu hotsearch --category tech
|
|
781
|
+
xbrowser session close
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
## 开发
|
|
785
|
+
|
|
786
|
+
```bash
|
|
787
|
+
# 安装依赖
|
|
788
|
+
npm install
|
|
789
|
+
|
|
790
|
+
# 开发模式(监听文件变化)
|
|
791
|
+
npm run dev
|
|
792
|
+
|
|
793
|
+
# 构建
|
|
794
|
+
npm run build
|
|
795
|
+
|
|
796
|
+
# 类型检查
|
|
797
|
+
npm run typecheck
|
|
798
|
+
|
|
799
|
+
# 代码检查
|
|
800
|
+
npm run lint
|
|
801
|
+
|
|
802
|
+
# 运行测试
|
|
803
|
+
npm test
|
|
804
|
+
|
|
805
|
+
# 完整验证
|
|
806
|
+
npm run validate
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
## 技术栈
|
|
810
|
+
|
|
811
|
+
| 依赖 | 用途 |
|
|
812
|
+
|------|------|
|
|
813
|
+
| **@dyyz1993/xcli-core** | CLI 框架核心(命令注册、Scope、输出格式化、插件加载) |
|
|
814
|
+
| **playwright** | 浏览器自动化引擎(含 CDP 连接) |
|
|
815
|
+
| **zod** | 参数校验 Schema |
|
|
816
|
+
| **yaml** | 录制文件读写 |
|
|
817
|
+
|
|
818
|
+
## 项目结构
|
|
819
|
+
|
|
820
|
+
```
|
|
821
|
+
xbrowser/
|
|
822
|
+
├── src/
|
|
823
|
+
│ ├── commands/ # 35 个浏览器命令定义
|
|
824
|
+
│ ├── builtins/ # CLI 内置命令(config, plugin, session, create)
|
|
825
|
+
│ ├── recorder/ # 录制引擎(录制器 + 回放器)
|
|
826
|
+
│ ├── session/ # 会话管理
|
|
827
|
+
│ ├── plugin/ # 插件加载器 + 安装器
|
|
828
|
+
│ ├── daemon/ # 守护进程管理
|
|
829
|
+
│ ├── cli/ # CLI 路由与输出
|
|
830
|
+
│ ├── router.ts # 命令路由
|
|
831
|
+
│ ├── executor.ts # 命令执行器
|
|
832
|
+
│ ├── chain-parser.ts # 命令链解析器
|
|
833
|
+
│ ├── browser.ts # 浏览器管理(启动、CDP 连接)
|
|
834
|
+
│ ├── context.ts # 命令上下文(BrowserCommandContext)
|
|
835
|
+
│ ├── scope.ts # Scope 定义
|
|
836
|
+
│ └── config.ts # 配置管理
|
|
837
|
+
├── bin/
|
|
838
|
+
│ └── cli.ts # CLI 入口
|
|
839
|
+
├── .xcli/plugins/ # 内置插件(baidu, douyin, github, web-automation)
|
|
840
|
+
├── tests/ # 测试
|
|
841
|
+
└── docs/ # 文档
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
## 与相关项目的关系
|
|
845
|
+
|
|
846
|
+
| 项目 | 定位 | 关系 |
|
|
847
|
+
|------|------|------|
|
|
848
|
+
| **@dyyz1993/xcli-core** | 通用 CLI 框架 | xbrowser 依赖的核心框架 |
|
|
849
|
+
| **@dyyz1993/xpage (mpage)** | 浏览器自动化引擎 | 独立项目,xbrowser **不依赖** mpage |
|
|
850
|
+
| **xbrowser** | 浏览器自动化 CLI | 自包含,直接使用 Playwright |
|
|
851
|
+
|
|
852
|
+
## 🔑 Keywords
|
|
853
|
+
|
|
854
|
+
`browser automation` `web scraping` `playwright alternative` `puppeteer alternative` `selenium alternative` `web crawler` `headless browser` `CLI tool` `command line` `scrape` `crawl` `anti-detection` `CDP` `record replay` `SEO tool` `AI agent` `browser plugin`
|
|
855
|
+
|
|
856
|
+
## 许可证
|
|
857
|
+
|
|
858
|
+
MIT
|