
🎯 学什么:在云服务器、Docker 容器、CI/CD 环境等"没有显示器"的沙箱环境中操控浏览器。还能多个人/多个 AI 共享同一个浏览器,各自操作互不干扰,并且自动管理登录状态不会互相踢下线。核心洞察:(1) remote-browser 的命令和 L5-18 本地 CLI 100% 相同——这是刻意设计的接口统一,你在 Mac 上写的脚本放到 Linux 云服务器上一行不改;(2) 标签页锁定机制:写操作锁定、读操作不锁定——最常踩的坑是"读了 state 以为页面已经独占了",但 state 是读操作不锁定;(3) 隧道(tunnel)的幂等性让多步骤脚本无需手动管理隧道状态。 💡 难易度:⭐⭐⭐ | ⏱️ 预计时间:30 分钟
1. 课程概览
💡 白话小课堂:想象你需要在云服务器上操控浏览器——但云服务器没有显示器、没有桌面、没有图形界面。就像你让一个盲人在一个没有窗户的房间里操作电脑。remote-browser 解决的就是这个问题——在沙箱中安装无头浏览器,通过 CDP 协议操控,CLI(CLI:命令行接口)接口与本地完全一致。
来源:browser-use 团队 / https://github.com/browser-use/browser-use
2. 沙箱浏览器问题
2.1 沙箱的挑战
很多 AI Agent 运行在沙箱环境中:
→ 云 VM(阿里云 ECS / AWS EC2)——无显示器、无 GUI
→ CI/CD 环境(GitHub Actions Runner)——容器化、无桌面
→ Coding Agent(Docker 容器)——最小化系统
→ 无 GUI 的 Linux 服务器——没有 X11/显示服务器
沙箱的"毛坯房"处境:
→ 只有水泥墙和电线——没有任何家具
→ 普通浏览器需要:显示器 + 桌面环境 + 图形驱动
→ 在沙箱里开普通浏览器 → "cannot open display" 错误
remote-browser 的解决方案:
→ 在沙箱中安装无头 Chromium(不需要显示器)
→ 通过 CDP 协议操控(不需要图形界面)
→ CLI 接口不变——与本地使用完全一致
2.2 三种沙箱浏览器模式
模式 1:默认无头 Chromium(Most Common)
→ 在沙箱内直接运行无头浏览器
→ 零外部依赖——Chromium 自带
→ 适合:大多数沙箱场景
→ browser-use open <url>(默认无头)
模式 2:cloud connect(云端代理)
→ 从沙箱连接云端浏览器,无需本地浏览器
→ 适合:沙箱资源非常有限(内存 < 512MB)
→ browser-use cloud connect
模式 3:CDP 直连(连接到已有 Chrome)
→ 通过 --cdp-url ws://localhost:9222/... 连接已有的 Chrome 实例
→ 适合:已有 Chrome 进程在运行
→ browser-use --cdp-url ws://... open <url>
3. 接口统一:本地和沙箱同一套命令
3.1 设计的精妙之处
接口统一是 browser-use 设计最优雅的地方:
本地开发(Mac/Windows with GUI):
browser-use --headed open https://example.com
browser-use state
browser-use click 5
→ 你能看到浏览器窗口在操作——方便调试
沙箱部署(Linux server without GUI):
browser-use open https://example.com
browser-use state
browser-use click 5
→ 命令完全相同——只是去掉了 --headed 和浏览器窗口
实际好处:
→ 本地写好脚本、用 --headed 调试、验证一切正常
→ scp 到 ECS 服务器上
→ 一行命令都不需要改
→ 直接运行
没有"本地能跑、服务器报错"的适配痛苦:
→ 不需要把 CLI 命令翻译成 SDK 调用
→ 不需要把命令翻译成 API 参数
→ 同一个命令在两种环境下完全一致
3.2 Python 持久会话
在沙箱中运行 Python 代码时,持久会话的核心价值:
browser 对象在调用间持久化:
→ 不需要每次重新创建 browser 实例
→ 不需要每次重新定义函数和变量
CLI 命令 ↔ Python 方法对应关系:
browser-use open <url> ↔ browser.goto(url)
browser-use click 5 ↔ browser.click(index=5)
browser-use screenshot p ↔ browser.screenshot(path)
browser-use get title ↔ browser.title
browser-use state ↔ browser.get_state()
4. 标签页锁定机制
4.1 机制详解
多代理共享浏览器时,标签页锁定机制防止相互干扰:
写操作锁定标签页:
✍️ click、input、type、select、upload、keys
→ 执行这些操作后 → 该标签页归当前代理独占
→ 其他代理只能对该标签页执行读操作
读操作不锁定标签页:
👁️ state、screenshot、get text、get value、eval(只读 JS)
→ 执行这些操作后 → 标签页仍然开放给其他代理
→ 其他代理也可以在这个标签页上执行读操作
4.2 最容易踩的坑
❌ 经典踩坑场景:
代理 A:
browser-use state # 读取当前页面
# 看到第 3 个元素是"确认"按钮 ← state 不锁定
# [此时代理 B 介入——修改了同一个标签页]
browser-use click 3 # 点击——但索引 3 可能已经不是"确认"了!
# 因为代理 B 在 state 和 click 之间改了页面
为什么出错?
→ state 是读操作 → 不锁定标签页
→ 代理 A 读完后,以为页面没变
→ 但代理 B 可以在 state 和 click 之间做写操作
→ 因为代理 A 还没做写操作——标签页没被锁定
✅ 正确做法:
1. 如果需要独占标签页:第一个操作就用写操作锁定它
2. 或者给每个代理分配独立的标签页
3. 或者在脚本设计中不依赖"读操作后页面不变"的假设
代理会话管理:
→ 代理 5 分钟不活跃后自动过期
→ 过期后其锁定的标签页释放
5. 隧道与故障排查
5.1 隧道幂等性
# 隧道暴露本地开发服务器
browser-use tunnel 3000
# → https://abc.trycloudflare.com
# 幂等性:同一端口重复调用返回已有 URL
browser-use tunnel 3000
# → 返回相同的 https://abc.trycloudflare.com(不是新隧道)
幂等性的重要性:在多步骤脚本中,不需要手动检查"隧道是否已经存在"——直接调用即可。注意:隧道独立于浏览器会话——browser-use close 后隧道仍然存在。
5.2 故障排查
# 如果 browser-use 命令失败,按以下顺序排查:
# Step 1:清理卡死的浏览器进程
browser-use close
# Step 2:重试命令
# Step 3:如果还失败,运行诊断
browser-use doctor
# 检查:Chromium 是否安装、CDP 是否可用、依赖是否完整
# Step 4:根据诊断结果修复
# 常见问题:Chromium 未安装 → apt install chromium-browser
# CDP 端口被占用 → 换个端口
6. 结构拆解:远程浏览器 Skill 模板
远程浏览器型 Skill 模板
核心特征
→ 管理对象 = 沙箱/云端/Docker 等无 GUI 环境中的浏览器 → 核心原则 = 接口统一(本地沙箱同一套命令)+ 标签页锁定 → 关键设计 = 三种沙箱模式 + 隧道幂等性 + 故障排查流程
通用结构
Sandbox Modes(三种沙箱模式)
- 默认无头 Chromium:沙箱内直接运行
- cloud connect:连接云端浏览器(资源受限)
- CDP 直连:连接已有 Chrome 实例
Interface Unity(接口统一)
- 本地和沙箱 100% 相同命令
- 开发流程:本地 --headed 调试 → scp → 沙箱直接运行
- Python 持久会话:CLI 命令 ↔ Python 方法映射
Tab Locking(标签页锁定)
- 写操作锁定:click/input/type/select/upload/keys
- 读操作不锁定:state/screenshot/get/eval
- 常见踩坑:读操作后页面可能被其他代理修改
- 代理 5 分钟不活跃自动过期
Troubleshooting(故障排查)
- 先 close 清理 → 重试 → doctor 诊断 → 修复
7. 电商案例:抖音精选联盟达人建联自动化
某抖音电商运营团队(主营女士内衣,日均通过精选联盟合作的达人 30 位)的达人运营每天需要完成一组重复操作:登录抖音商家后台→进入精选联盟→筛选「未合作」达人→按粉丝量和带货评分排序→向排名前 20 的达人逐一发送合作邀约(含样品申请链接)。手工操作每天 1.5 小时,运营想把这套流程部署在公司的阿里云 ECS(Linux 无 GUI)上自动执行。
部署方案:
# 在 ECS 上安装(无 GUI Linux)
apt-get install -y chromium-browser
uv pip install browser-use
# 编写脚本(运营在 Mac 上用 --headed 调试通过后 scp 到 ECS)
cat > /scripts/daren_outreach.sh << 'EOF'
#!/bin/bash
# 达人建联自动化:每天上午 10:00 运行
browser-use --profile "ShopOwner" open https://fxg.jinritemai.com/ # 抖音商家后台
browser-use wait text "精选联盟" # 确认登录成功(Cookie 持久化)
# 进入精选联盟达人广场
browser-use click 5 # 左侧菜单「达人合作」
browser-use wait text "达人广场"
browser-use state
# 筛选条件设置
browser-use click 12 # 「未合作」筛选
browser-use select 8 "粉丝量" # 排序方式下拉
browser-use wait selector "div.daren-list"
browser-use state
# 逐一发送合作邀约(前 20 个达人)
for i in $(seq 1 20); do
CARD_INDEX=$((i * 3 + 5)) # 每个达人卡片的第一项可交互元素
# S: State —— 确认卡片信息
browser-use state
daren_name=$(browser-use get text $((CARD_INDEX + 1))) # 达人名称
daren_fans=$(browser-use get text $((CARD_INDEX + 2))) # 粉丝数
# 跳过粉丝 < 1 万的达人
if echo "$daren_fans" | grep -q "万"; then
# I: Interact —— 点击「邀请合作」按钮
browser-use click $((CARD_INDEX + 4)) # 邀请合作按钮
browser-use wait text "寄样申请"
# 选择样品(固定:新品无钢圈内衣 L 码)
browser-use select 3 "新品无钢圈内衣 L码"
# 发送邀约
browser-use click 6 # 确认发送
browser-use wait text "已发送"
# A: Again State —— 返回列表确认
browser-use state
echo "[$(date)] 已邀约:$daren_name ($daren_fans)" >> /var/log/daren_outreach.log
fi
# 间隔 2 秒(防止操作过快被限流)
sleep 2
done
browser-use screenshot /reports/daren_outreach_$(date +%Y%m%d).png --full
browser-use close
echo "[$(date)] 今日达人建联完成:20 位" >> /var/log/daren_outreach.log
EOF
# 设置 cron job:每天上午 10:00 自动运行
# 0 10 * * * /scripts/daren_outreach.sh
多品类并行(内衣/家居服/袜子各跑一个 session):
# 按品类并行建联
browser-use --session underwear open <内衣达人广场URL> &
browser-use --session lounge open <家居服达人广场URL> &
browser-use --session socks open <袜子达人广场URL> &
wait
echo "3 品类达人建联全部完成"
效果:
- 建联耗时:从 1.5 小时/天(人工登录→筛选→逐位点击→发送→记录)→ 10 分钟(脚本自动执行 + 人工查看日志确认)
- 月建联量:从日均 20 位 → 日均 60 位(3 品类并行 × 各 20 位)
- 达人合作转化率(建联→确认合作):保持 12%(与人工建联持平——邀约内容质量取决于模板话术,而非发送方式)
- Cookie 持久化:一次登录后,cron job 每日自动续期,沙箱无需显示器——ECS 年费 ¥800 覆盖全部自动化需求
🔑 启示:达人建联的自动化关键在于「一致性和节奏控制」——人工建联到第 15 个达人时开始疲劳→漏看粉丝数据→误邀低质量达人。脚本每条邀约前都会 state 确认达人数据(S-I-A-V),不会被疲劳影响判断。此外,每次操作间隔 2 秒的 sleep 不是「低效」而是「伪装」——抖音商家后台对高频操作的检测阈值约为 0.5 秒,2 秒间隔远低于触发限流的频率。
8. 掌握检验
Q1:沙箱环境中操控浏览器的三种模式是什么?
- A) GUI 模式、CLI 模式、API 模式
- B) 默认无头 Chromium、cloud connect、CDP 直连
- C) 本地模式、远程模式、混合模式
- D) 读模式、写模式、管理模式
Q2:隧道(tunnel)的"幂等性"意味着什么?
- A) 每次调用都会创建新隧道
- B) 同一端口重复调用返回已有的 URL,不会创建重复隧道
- C) 隧道在 browser-use close 后自动关闭
- D) 隧道只能用一次
Q3:多代理共享浏览器时的标签页锁定机制如何工作?以下哪种操作会锁定标签页?
- A)
browser-use state - B)
browser-use screenshot - C)
browser-use get text 5 - D)
browser-use input 3 "hello@example.com"
Q4:remote-browser 的命令与 L5-18 本地 CLI 100% 相同——这种一致性带来了什么实际好处?
Q5:Python 持久会话的核心价值是什么?举 3 对 CLI 命令与 Python 方法的对应关系。
Q6:如果你在云服务器(阿里云 ECS Linux,无 GUI)上运行 browser-use open <url> 失败——你应该使用哪两个命令进行故障排查?
Q7:以下哪种场景最容易违反标签页锁定机制导致 bug?
- A) 代理 A 和代理 B 各有自己的独立标签页
- B) 代理 A 正在向一个表单输入数据,代理 B 在另一个标签页截图
- C) 代理 A 在标签页 X 上做了 state 读取后,认为"这个页面我可以独占",然后开始做 input 操作——但在 state 和 input 之间,代理 B 可能已经修改了同一个标签页
- D) 代理 A 的会话过期
Q8:请设计一个沙箱部署方案:在阿里云 ECS(无 GUI Linux)上运行 4 个浏览器实例,每天定时抓取 80 个主播的选品数据。
9. 答案
点击查看答案
Q1:B — (1) 默认无头 Chromium:沙箱内直接运行;(2) cloud connect:连接云端浏览器;(3) CDP 直连:连接已有 Chrome 实例。
Q2:B — 同一端口重复调用返回已有的 URL,不需要手动管理隧道状态。注意隧道独立于浏览器会话——close 后隧道仍存在。
Q3:D — browser-use input 是写操作,会锁定标签页。A、B、C 都是读操作,不锁定。
Q4:参考答案 — 本地开发和云端部署使用完全相同的一套命令——本地 --headed 调试通过后,scp 到服务器一行不改直接运行。没有"本地能跑、服务器报错"的适配痛苦。
Q5:参考答案 — 核心价值:变量在调用间持久化,不需要每次重新创建。对应关系:(1) browser.goto(url) ↔ browser-use open <url>;(2) browser.click(index) ↔ browser-use click <index>;(3) browser.screenshot(path) ↔ browser-use screenshot [path]。
Q6:参考答案 — browser-use close(清理卡死进程后重试)和 browser-use doctor(运行诊断检查)。顺序:先 close → 重试 → 如果还失败 → doctor → 根据结果修复。
Q7:C — state 是读操作不会锁定标签页。从 state 到 input 之间,另一个代理可能已经修改了同一个标签页。正确做法:不要依赖"读操作后页面不变"的假设,或者第一个操作就用写操作锁定。
Q8:参考答案 — (1) 选择默认无头 Chromium 模式。(2) 4 个浏览器实例按品类分配——每个品类浏览器注册 20 个代理(80 主播/4 品类)。(3) 登录态管理:cookies export → cookies import 恢复,cron job 每天 4 次自动运行(6:00/12:00/18:00/22:00)。
(6/8 通过)
10. 延伸阅读
- [[L5-20-开源浏览器自动化|上一课:开源浏览器自动化]]
- [[L5-22-编程式视频生成|下一课:编程式视频生成]]

评论区
共 0 条评论