浏览器自动化

lsbot 内置完整的浏览器自动化能力,基于 Chrome DevTools Protocol (CDP)go-rod,采用**快照-操作(Snapshot-then-Act)**模式,让 AI 能够像人一样操作浏览器。

📋 AI agent 操作规则(搜索行为、弹窗处理、批量操作、连接模式等):浏览器 AI 操作规则


核心能力

  • 控制真实 Chrome/Brave/Edge 浏览器(有界面或无头模式)
  • 连接已有 Chrome — 无需新开窗口,直接接管正在使用的浏览器
  • 读取页面无障碍树(Accessibility Tree),精准定位元素
  • 点击、输入、按键、滚动、拖拽
  • 多标签页管理
  • 截图(视口或整页)
  • 执行任意 JavaScript
  • 批量点击(适合爬取、批量操作)

连接已有 Chrome(推荐工作流)

默认情况下,每次触发浏览器时 lsbot 会启动一个新的独立 Chrome 窗口。通过以下配置,可以让 bot 直接在你正在使用的 Chrome 里开新标签页操作,实现人机共享浏览器。

第一步:用调试端口启动 Chrome

Chrome 必须以 --remote-debugging-port 参数启动,才能接受 CDP 连接。

macOS:

# 新开一个带调试端口的 Chrome 窗口(不影响已有进程)
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
  --remote-debugging-port=9222 \
  --user-data-dir="$HOME/.lsbot/chrome-profile"

推荐: 使用独立的 --user-data-dir,避免与个人 Chrome 账号/扩展产生冲突。

Linux:

google-chrome \
  --remote-debugging-port=9222 \
  --user-data-dir="$HOME/.lsbot/chrome-profile"

验证端口已开放:

curl http://localhost:9222/json/version

成功响应示例:

{
  "Browser": "Chrome/121.0.6167.160",
  "Protocol-Version": "1.3",
  "webSocketDebuggerUrl": "ws://localhost:9222/devtools/browser/..."
}

第二步:配置 lsbot

~/.lingti.yaml 中添加:

browser:
  cdp_url: "127.0.0.1:9222"

之后所有 browser_navigatebrowser_click 等操作都会在这个 Chrome 里执行,不再另开新窗口。

配置优先级

EnsureRunning() 按以下顺序决定使用哪个浏览器:

1. cfg.Browser.CDPURL  (~/.lingti.yaml 中的 cdp_url)
2. 127.0.0.1:9222      (well-known 默认调试端口,无需配置)
3. 启动新 Chrome 实例   (fallback)

快速上手

"打开知乎首页"                        → browser_navigate url="https://www.zhihu.com"
"看看页面上有什么"                    → browser_snapshot
"点击搜索框并搜索 Go 语言"           → browser_type ref=3 text="Go 语言" submit=true
"截图保存"                            → browser_screenshot
"打开新标签页看看微博"                → browser_tab_open url="https://www.weibo.com"

工具完整参考

生命周期管理

browser_start — 启动或连接浏览器

参数类型说明
headlessbool无头模式(无界面),默认 false
urlstring启动后立即导航的 URL
executable_pathstringChrome 可执行文件路径(留空自动检测)
cdp_urlstring连接已有 Chrome 的 CDP 地址(如 127.0.0.1:9222
# 启动有界面浏览器
browser_start headless=false

# 无头模式
browser_start headless=true

# 连接已有 Chrome(需已用 --remote-debugging-port 启动)
browser_start cdp_url="127.0.0.1:9222"

# 启动并直接导航
browser_start url="https://www.zhihu.com"

browser_stop — 关闭浏览器

如果是连接到已有 Chrome(cdp_url 模式),只断开连接,不关闭浏览器

browser_status — 查看浏览器状态

返回:

{
  "running": true,
  "headless": false,
  "connected": true,
  "pages": 3,
  "active_url": "https://www.zhihu.com"
}

connected: true 表示当前是连接到已有 Chrome(不是 bot 自己启动的)。


导航与内容

browser_navigate — 导航到 URL

browser_navigate url="https://www.baidu.com"
  • 自动等待页面加载完成(load 事件)
  • 如果浏览器未启动,自动按优先级连接/启动

browser_snapshot — 获取页面无障碍快照

返回页面的可交互元素列表,每个元素带数字编号(ref):

[1] link "首页"
[2] link "发现"
[3] textbox "搜索"
[4] button "搜索"
[5] heading "今日推荐"
  [6] link "为什么 Go 语言这么流行?"
  [7] link "深度学习入门指南"

ref 规则:

  • 每次 snapshot 重新编号,导航后必须重新 snapshot
  • 只包含可交互元素和重要内容节点
  • 缩进表示层级关系

browser_screenshot — 截图

参数类型说明
pathstring保存路径,默认 ~/Desktop/browser_screenshot_<时间戳>.png
full_pagebooltrue = 整页截图,false = 当前视口,默认 false
browser_screenshot
browser_screenshot path="/tmp/result.png" full_page=true

元素交互

所有交互工具都需要先执行 browser_snapshot 获取 ref 编号。

browser_click — 点击元素

browser_click ref=4
  • 自动滚动到元素可见位置
  • 等待元素可交互
  • ref 失效时自动重新 snapshot 并重试一次

browser_type — 输入文本

参数类型说明
refnumber必需,元素 ref 编号
textstring必需,输入内容
submitbooltrue = 输入后按 Enter,默认 false
browser_type ref=3 text="lsbot"
browser_type ref=3 text="搜索内容" submit=true

browser_press — 按键

支持的按键:

按键名说明
Enter回车
Tab制表符 / 切换焦点
Escape取消
Backspace退格
Delete删除
Space空格
ArrowUp/Down/Left/Right方向键
Home / End行首 / 行尾
PageUp / PageDown翻页
browser_press key="Enter"
browser_press key="Tab"
browser_press key="Escape"

browser_execute_js — 执行 JavaScript

browser_execute_js script="return document.title"
browser_execute_js script="window.scrollTo(0, document.body.scrollHeight)"
browser_execute_js script="return document.querySelectorAll('a').length"

browser_click_all — 批量点击

适合批量操作(如全选、批量关闭通知等)。

参数类型说明
selectorstringCSS 选择器,匹配要点击的元素
delay_msnumber每次点击间隔毫秒数,默认 500
skip_selectorstring跳过匹配此选择器的元素(可选)
browser_click_all selector=".notification-item .close-btn" delay_ms=200

标签页管理

browser_tabs — 列出所有标签页

[
  {"target_id": "abc123", "url": "https://www.zhihu.com", "title": "知乎"},
  {"target_id": "def456", "url": "https://www.weibo.com", "title": "微博"}
]

browser_tab_open — 打开新标签页

browser_tab_open url="https://www.weibo.com"
browser_tab_open                              # 打开空白标签页

browser_tab_close — 关闭标签页

browser_tab_close target_id="abc123"
browser_tab_close                             # 关闭当前活跃标签页

典型使用场景

场景一:信息查询

用户: "帮我查一下今天的 BTC 价格"

bot:
1. browser_navigate url="https://www.coindesk.com"
2. browser_snapshot
   → [1] heading "Bitcoin Price" [2] text "$67,234.50" ...
3. 直接返回价格信息,无需截图

场景二:登录并操作

用户: "帮我登录知乎并关注 xxx"

bot:
1. browser_navigate url="https://www.zhihu.com/signin"
2. browser_snapshot
   → [1] textbox "手机号或邮箱" [2] textbox "密码" [3] button "登录"
3. browser_type ref=1 text="your@email.com"
4. browser_type ref=2 text="yourpassword"
5. browser_click ref=3
6. browser_navigate url="https://www.zhihu.com/people/xxx"
7. browser_snapshot
   → [N] button "关注"
8. browser_click ref=N

场景三:网页内容提取

用户: "抓取这个页面所有文章标题"

bot:
1. browser_navigate url="https://example.com/blog"
2. browser_snapshot
   → 看到所有 heading 和 link 元素
3. 直接从快照中提取标题信息,返回列表

场景四:表单填写

用户: "帮我填写这个报名表"

bot:
1. browser_navigate url="https://example.com/register"
2. browser_snapshot
3. browser_type ref=1 text="张三"          # 姓名
4. browser_type ref=2 text="138xxxx1234"   # 手机
5. browser_type ref=3 text="example@qq.com" # 邮箱
6. browser_click ref=10                     # 提交按钮
7. browser_screenshot                       # 截图确认

场景五:批量操作

用户: "把我邮箱里所有营销邮件全部删除"

bot:
1. browser_navigate url="https://mail.example.com"
2. browser_snapshot → 找到邮件列表
3. browser_click_all selector=".email-item.marketing input[type=checkbox]"
4. browser_click ref=<删除按钮>

场景六:监控页面变化

用户: "每隔5分钟截一张这个页面的图"

bot:
1. browser_navigate url="https://example.com/dashboard"
2. browser_screenshot path="/tmp/monitor_1.png"
3. (等待)
4. browser_screenshot path="/tmp/monitor_2.png"

配置参考

~/.lingti.yaml 中的 browser 配置节:

browser:
  # 连接已有 Chrome(推荐)
  # Chrome 需以 --remote-debugging-port=9222 启动
  cdp_url: "127.0.0.1:9222"

  # 浏览器窗口大小
  # "fullscreen" = 全屏(默认)
  # "1920x1080"  = 指定分辨率
  screen_size: "1920x1080"

技术架构

用户自然语言指令
      ↓
  AI Agent(理解意图,规划工具调用序列)
      ↓
MCP Tools (internal/tools/browser.go)
      ↓
Browser Manager (internal/browser/browser.go)
  ├── EnsureRunning()   → cdp_url > :9222 > 新启动
  ├── Start()           → 启动或连接
  └── ActivePage()      → 获取当前活跃页面
      ↓
Snapshot Engine (internal/browser/snapshot.go)
  └── CDP Accessibility.getFullAXTree → ref 映射
      ↓
Action Engine (internal/browser/actions.go)
  └── ref → BackendDOMNodeID → DOM 元素 → 交互
      ↓
go-rod/rod(Chrome DevTools Protocol)
      ↓
Chrome / Brave / Edge(有界面 或 无头)

为什么用无障碍树而不是 CSS 选择器?

无障碍树(本项目)CSS 选择器
稳定性不受样式重构影响类名变化即失效
AI 可读性role + name 语义清晰需要理解 DOM 结构
简洁度[3] button "登录".login-form > div > button.btn-primary
跨站通用标准 ARIA 规范每个网站不同

Ref 生命周期

browser_snapshot      →  生成 ref 映射(存储在内存)
browser_click ref=3   →  通过 BackendDOMNodeID 定位 DOM 元素
browser_navigate      →  页面变化,旧 ref 全部失效
browser_snapshot      →  必须重新获取

故障排除

找不到浏览器

failed to launch browser: no chrome executable found

解决: 安装 Chrome、Brave 或 Edge,或用 executable_path 指定路径:

browser_start executable_path="/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"

CDP 连接失败

failed to resolve CDP address 127.0.0.1:9222

解决: Chrome 未以调试端口启动。执行:

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
  --remote-debugging-port=9222 \
  --user-data-dir="$HOME/.lsbot/chrome-profile"

验证:curl http://localhost:9222/json/version


ref 失效

ref 5 not found in snapshot

原因: 页面内容已变化(导航、动态加载等),旧 ref 不再有效。

解决: 重新执行 browser_snapshot 获取新 ref 编号。


快照为空

原因: 页面还在加载,或为纯 canvas/WebGL 应用(无障碍树为空)。

解决:

  1. 等待页面稳定后重试 browser_snapshot
  2. 对于无障碍树为空的页面,改用 browser_execute_js 提取内容

无头模式下页面渲染异常

部分网站会检测 headless 并显示验证码或重定向。改用有界面模式:

browser_start headless=false

Linux 服务器无 GUI

确保使用 headless 模式并安装浏览器依赖:

# Ubuntu/Debian
apt-get install -y chromium-browser

# 启动 bot 时浏览器会自动以 headless 模式运行

与其他方案对比

lsbotPlaywright/Node.jsSelenium
语言Go(单二进制)Node.jsJava/Python
依赖仅需 ChromeNode.js + 浏览器驱动JVM + 驱动
部署复制一个文件npm install配置复杂
AI 集成原生 MCP需要额外封装需要额外封装
无障碍树原生支持支持有限支持
连接已有浏览器✅ cdp_url✅ connectOverCDP