mcpField
E
exploring-browser

exploring-browser

github.com/robomotionio开发5123 次安装5 天前更新
代码仓库

关于 exploring-browser

exploring-browser 是供 Claude Code 和其他 Agent 使用的浏览器探索与自动化技能。它将交互记录为 JSON 流程序列,供后续转换为 Robomotion SDK TypeScript,并设有只读探索规则。

主要功能

  1. 01交互式浏览器探索
  2. 02基于快照查找页面元素
  3. 03记录点击、输入和导航
  4. 04生成 JSON 流程序列
  5. 05捕获网络与控制台信息
  6. 06管理 Cookie 和会话

适用场景

  1. 01探索网站并梳理自动化流程
  2. 02通过快照定位交互元素
  3. 03检查网络流量以发现 API 端点
  4. 04利用捕获的控制台日志排查浏览器问题

MCP 相关

该技能使用 `robomotion-browser-mcp` 服务提供的浏览器工具进行导航、检查、交互和流程记录。MCP 用户在调用浏览器工具前,可能需要先加载延迟提供的工具架构。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/robomotionio/agent-skills --skill exploring-browser

安装后在 Claude Code 中输入/exploring-browser确认已加载。

附带文件config.jsondocs/patterns/browser.md

详细介绍

原文在翻译后有更新,译文可能不是最新。

浏览器探索技能

通过实时探索和流程录制实现交互式浏览器自动化。由 robomotion-browser-mcp 服务提供支持。

搭配使用: reversing-network — 捕获网络流量后,如果发现可用的 API,请从浏览器自动化切换到 HTTP。

概述

此技能支持你与 Claude 结对编程,共同探索网站、发现选择器并构建自动化流程。最后会生成一个JSON 流程序列,可直接映射到 Robomotion SDK TypeScript。

工作流

步骤 0 — 加载工具架构。 在 Claude Code 中,mcp__browser__* 工具会被延迟加载(目录中只有名称,需先获取其架构)。冷启动时调用 browser_open 会通过 stdio 发送空的/格式错误的 JSON,导致 robomotion-browser-mcp 崩溃,并在本次会话的剩余时间内将所有浏览器工具列入黑名单 — 此时,即使 claude mcp list 仍显示 ✓ Connected(这是一次新的探测,而非会话中已失效的管道),ToolSearch 也会返回“no matching deferred tools”。首次调用前,请运行:

ToolSearch query="select:mcp__browser__browser_open,mcp__browser__browser_navigate,mcp__browser__browser_snapshot,mcp__browser__browser_type,mcp__browser__browser_click,mcp__browser__browser_close,mcp__browser__browser_get_sequence,mcp__browser__browser_set_flow_name"

(如果需要,可添加 browser_wait、browser_select、browser_query、browser_start_network_capture 等。)服务失效后,只有重启 Claude Code 才能恢复 — 无法在会话内重新连接。使用其他运行时的 Agent 应替换为各自的 MCP 调用方式。

  1. 打开浏览器 - 使用 browser_open 启动(默认启用隐身模式)
  2. 导航 - 使用 browser_navigate 前往目标 URL
  3. 快照 - 使用 browser_snapshot 查看包含 refs 的页面结构(主要探索工具)
  4. 操作 - 使用快照中的 refs:browser_click @e3、browser_type @e5(会自动记录 XPath)
  5. 重新获取快照 - 页面发生变化后(点击、导航),获取新快照
  6. 关闭浏览器 - 探索完成后务必调用 browser_close — 这会返回流程序列 JSON 并释放浏览器
  7. 询问用户 - 展示计划/序列,并使用 AskUserQuestion 询问是否继续构建流程
  8. 转换 - 仅在用户批准后,才将 JSON 转换为 robomotion-sdk 的 TypeScript 代码

重要: 完成所有步骤的探索后,必须关闭浏览器(browser_close)。编写/修改代码时,不要让浏览器保持打开状态。并且,在开始编写或修改流程代码之前,必须使用 AskUserQuestion 询问用户。

探索期间只读

探索时,网站是用户正在使用的实时系统。只读取,不要更改。

  • 绝不要点击会更改数据的按钮:Merge、Approve、Deny、Delete、Remove、Pay、Send、Publish、Archive、Transfer、Confirm。统计这些按钮的数量,读取其标签及旁边的行,然后停在这里。
  • 只有在点击对话框的取消按钮将其关闭,且不进行其他操作时,才可以打开对话框。如果一次点击既打开又提交,请勿点击。
  • 更改操作应放在流程中:构建相应步骤,让机器人在用户运行流程时执行。这才是用户的要求 — 由机器人点击,而不是由你点击。
  • 如果需要查看这类按钮被点击后的情况(确认页面、后续状态),请在点击前使用 AskUserQuestion 询问用户,并明确说明这会更改他们的数据。如果脚本涉及此类操作,browser_eval 会拒绝一次;如果 browser_click 的快照 ref 对应的元素名称是上述操作之一,也会拒绝。用户同意后,请再次调用,并设置 confirmSideEffect: true。
  • 如果意外更改了任何内容,请在同一轮回复中,先告知用户具体更改了什么。

核心概念

优先使用快照进行探索(强制)

每次遇到新 URL 或页面变化时,你的首个操作必须是 browser_snapshot。 这是不可协商的。快照约占用 50-100 个 token,而截图约占用 500-2000 个 token。

GOOD: browser_navigate → browser_snapshot → read tree → browser_click @e3
BAD:  browser_navigate → browser_screenshot → browser_query → browser_query → ...
BAD:  browser_navigate → browser_query → browser_query → browser_query → ...

规则:

  • 每次导航后(browser_navigate、会加载新页面的 browser_click、browser_reload、browser_go_back),首次调用必须是 browser_snapshot
  • 使用快照中的引用(@e1、@e2……)作为操作工具中的选择器
  • 执行会导致页面变化的操作(点击、提交表单)后,立即获取一张新快照
  • 不要使用 browser_screenshot 来探索页面——它会多消耗 10-40 倍 token。只有在无法仅凭快照引用继续操作时,才将截图作为最后手段(例如,遇到视觉布局问题、需要验证图像)
  • 不要使用 browser_query 来探索页面——快照已显示所有交互元素。只对特定选择器进行有针对性的检查时才使用 query
  • 切勿连续多次调用 browser_query 来“探索”页面——这正是快照的用途
引用 — 轻量级元素引用

快照会为交互元素分配 @e1、@e2 等引用。这些引用可用作所有操作工具中的选择器:

browser_click selector=@e3          → clicks the element, records its XPath
browser_type selector=@e5 text=hello → types into the element, records its XPath

引用是临时的——导航、刷新或返回页面时会失效。页面变化后,获取新快照以取得新的引用。

录制内容始终保存解析后的 XPath/CSS 选择器,而不是引用。这意味着 RPA 机器人会获得稳定的选择器。

探索模式
  • explore=true(查询的默认值):不记录操作,仅用于探索
  • explore=false(操作的默认值):将操作记录到流程序列中
工具类型默认 explore 值行为
快照(browser_snapshot)—仅用于探索(永不记录)
查询(browser_query、browser_get_text)true用于探索,不记录
操作(browser_click、browser_type)false记录到流程中
导航(browser_navigate)false记录到流程中
截图true默认不记录
选择器

使用引用(优先)、XPath 或 CSS 选择器:

# Refs (from browser_snapshot) — PREFERRED
@e1, @e2, @e3

# XPath examples
//button[@id='submit']
//input[@name='email']

# CSS examples
#submit
input[name='email']

可用工具

生命周期
  • browser_open - 启动浏览器(传入 headless: false 以便用户查看;支持 stealth、视口选项)
  • browser_close - 关闭浏览器并返回流程序列 JSON
导航
  • browser_navigate - 前往 URL
  • browser_reload - 刷新页面
  • browser_go_back - 返回上一页
探索
  • browser_snapshot - 始终优先使用——包含引用(@e1、@e2……)的无障碍树。每次导航后都必须使用。
  • browser_screenshot - 仅作为最后手段——视觉截图。只有在无法继续操作,且快照引用不足以完成操作时才使用。
  • browser_query - 有针对性地检查元素(谨慎使用——快照已显示所有内容)
  • browser_get_text - 获取元素的文本内容
  • browser_get_value - 获取输入框的值
  • browser_get_attr - 获取属性值
操作(自动录制)
  • browser_click - 点击元素
  • browser_type - 在输入框中输入
  • browser_select - 选择下拉选项
  • browser_wait - 等待元素
  • browser_scroll - 滚动到元素
  • browser_hover - 将鼠标悬停在元素上
上下文
  • browser_switch_iframe - 进入 iframe
  • browser_switch_main - 返回主页面
会话
  • browser_get_sequence - 获取当前 JSON 序列
  • browser_clear_sequence - 开始新序列
  • browser_set_flow_name - 设置流程名称
Cookies
  • browser_get_cookies - 获取 cookies(可按域名筛选)
  • browser_set_cookie - 设置单个 cookie
  • browser_set_cookies - 设置多个 cookies
  • browser_clear_cookies - 清除 cookies(可按域名筛选)
网络捕获(API 发现)
  • browser_start_network_capture - 开始捕获请求/响应
  • browser_get_requests - 获取已捕获的请求(按方法/URL 筛选)
  • browser_get_responses - 获取已捕获的响应(按状态码/URL 筛选)
  • browser_get_request_response - 按 ID 获取请求-响应对
  • browser_stop_network_capture - 停止捕获
  • browser_clear_network_capture - 清除已捕获的数据
控制台捕获(调试)
  • browser_start_console_capture - 开始捕获控制台日志
  • browser_get_console_logs - 获取已捕获的日志(按类型筛选)
  • browser_clear_console_logs - 清除已捕获的日志
  • browser_stop_console_capture - 停止捕获
会话持久化
  • browser_export_session - 将 Cookie、localStorage 和 URL 导出为 JSON
  • browser_import_session - 导入之前导出的会话
  • browser_save_session - 将会话保存到文件
  • browser_load_session - 从文件加载会话
元素选择器(交互式选择)
  • browser_start_element_picker - 启动交互式元素选择器(悬停时以红色高亮)
  • browser_get_picked_element - 获取用户通过 Ctrl+X 选中的元素
  • browser_stop_element_picker - 停止选择器并移除高亮

示例会话

User: Automate login to example.com

Claude: I'll open a browser and explore the login page.
[browser_open stealth=true]
[browser_navigate url="https://example.com/login"]
[browser_snapshot]
// Returns:
//   - textbox "Email" [ref=e1]
//   - textbox "Password" [ref=e2] [type=password]
//   - button "Sign In" [ref=e3]

Now I'll perform the login actions using refs:
[browser_type selector=@e1 text="[email protected]"]
[browser_type selector=@e2 text="secret123"]
[browser_click selector=@e3]

// Page changed — take a new snapshot to see what happened
[browser_snapshot]

// Done exploring — CLOSE THE BROWSER to get the flow sequence
[browser_close]
// Returns flow sequence JSON with resolved XPath selectors (not refs)

Claude: Here's the plan I recorded:
1. Open Browser → Navigate to login page
2. Type email → Type password → Click Sign In

[AskUserQuestion: "Should I build the TypeScript flow from this sequence?"]

// Only after user says yes:
Here's the TypeScript flow:
// ... generated code ...

提示

  1. 始终先获取快照 — 一次 browser_snapshot 会显示所有带有 refs 的交互式元素。
  2. 页面变化后重新获取快照 — 导航/点击会使 refs 失效。
  3. 完成后关闭浏览器 — 始终调用 browser_close。编写代码时绝不要让浏览器保持打开状态。

将录制的 JSON 转换为 TypeScript 属于 creating-flow 的工作;此技能的任务到序列 JSON 为止。有关浏览器专用 SDK 模式(代理配置、选择器提示),请参阅 ./docs/patterns/browser.md。


结对编程工作流

找不到元素时——使用元素选择器!

多次尝试后仍找不到元素时,请使用交互式元素选择器,而不是让用户手动检查:

1. Take a screenshot to see current state
2. Try 2-3 different selector strategies
3. Check if element is in an iframe (browser_switch_iframe)
4. If still not found, START THE ELEMENT PICKER:
   [browser_start_element_picker]
   "I can't find the element. I've enabled the element picker -
    please hover over the element you want and press Ctrl+X to select it.
    Press Escape to cancel."
5. Wait for user, then retrieve the element:
   [browser_get_picked_element]
6. Use the recommended selectors from the result

示例工作流:

Claude: I'm looking for the login button but can't find it with the usual selectors.
        Let me enable the element picker so you can show me exactly which element you mean.

[browser_start_element_picker]

Result: Element picker started. User should hover over elements (red highlight)
        and press Ctrl+X to select.

Claude: Please hover over the button you want me to click and press Ctrl+X.
        You'll see a red highlight around elements as you hover.

--- User hovers and presses Ctrl+X ---

[browser_get_picked_element]

Result: {
  "picked": true,
  "element": {
    "tagName": "button",
    "className": "btn-primary submit-form",
    "text": "Sign In",
    "recommendedSelectors": [
      { "type": "xpath", "selector": "//button[contains(text(),'Sign In')]", "confidence": 80, "reason": "Contains text" },
      { "type": "xpath", "selector": "//button[@class='btn-primary submit-form']", "confidence": 70, "reason": "Class match" }
    ]
  }
}

Claude: Got it! The button has text "Sign In". I'll use this selector:
[browser_click selector="//button[contains(text(),'Sign In')]"]
用于 API 发现的网络分析

使用网络捕获来了解页面使用了哪些 API:

1. browser_start_network_capture capture_body=true
2. Perform the action (login, form submit, etc.)
3. browser_get_requests method=POST
4. Analyze the API endpoints found
5. Suggest: "Instead of browser automation, you could use
   Core.Net.HttpRequest directly with this endpoint"

示例工作流:

Claude: Let me capture network traffic to see what API this uses...
[browser_start_network_capture capture_body=true]

Claude: Now I'll fill in the login form...
[browser_type selector="//input[@name='email']" text="[email protected]"]
[browser_type selector="//input[@name='password']" text="password"]
[browser_click selector="//button[@type='submit']"]

Claude: Let me check what API calls were made...
[browser_get_requests method=POST]

Result: Found POST to /api/auth/login with JSON body:
{
  "email": "[email protected]",
  "password": "password"
}

Claude: I found the login API endpoint. Instead of browser automation,
you could create a simpler flow using Core.Net.HttpRequest:
- POST to /api/auth/login
- Store the auth token from response
- Use token for subsequent API calls

Would you prefer the API-based approach?
使用控制台日志调试

操作未按预期生效时:

1. browser_start_console_capture types=["error","warn"]
2. Retry the failing action
3. browser_get_console_logs type=error
4. Report findings and adjust approach

示例工作流:

Claude: The click didn't seem to work. Let me check for JavaScript errors...
[browser_start_console_capture types=["error","warn"]]
[browser_click selector="//button[@id='submit']"]
[browser_get_console_logs type=error]

Result: Error: "Cannot read property 'validate' of undefined" at form.js:42

Claude: Found a JavaScript error - the page has a bug in its validation code.
Let me try waiting for the form to fully load first...
[browser_wait selector="//form[@data-ready='true']"]
用于身份验证的会话持久化

处理需要身份验证的网站时:

1. Complete login manually or via automation
2. browser_export_session - save for later
3. Close browser, do other work
4. browser_open, browser_import_session - restore auth

示例工作流:

Claude: Let me save your authenticated session for later use...
[browser_export_session]

Session exported with 5 cookies and current URL.

Claude: I'll save this to a file so you can reuse it:
[browser_save_session path="/tmp/myapp-session.json"]

--- Later ---

Claude: Let me restore your previous session...
[browser_open]
[browser_load_session path="/tmp/myapp-session.json"]

Session restored - you're logged in as [email protected]
何时使用浏览器,何时使用 HTTP 请求
场景建议
已知端点的简单 API使用 Core.Net.HttpRequest
登录流程 → 需要身份验证 Cookie使用浏览器,然后导出会话
由复杂 JavaScript 渲染的内容使用浏览器自动化
带有 CSRF 令牌的表单使用浏览器(会自动处理令牌)
抓取分页数据从浏览器开始,如果找到 API 则切换到 API
文件下载使用浏览器进行身份验证,使用 API 下载

决策流程:

  1. 开始网络捕获
  2. 如果找到简洁的 REST API → 建议使用 HTTPRequest
  3. 如果身份验证/CSRF 复杂 → 继续使用浏览器
  4. 如果两者都需要 → 用浏览器进行身份验证,用 API 获取数据

评论

支持 Markdown