1. 项目概述:为AI智能体赋予“真实浏览器”的双手
如果你尝试过让AI助手帮你完成一些网页操作,比如“帮我退订所有营销邮件”或者“去LinkedIn上申请这个职位”,大概率会以失败告终。不是AI不够聪明,而是现实世界的网页太“狡猾”了。X(原Twitter)的动态内容加载、LinkedIn按钮的隐藏式设计、Gmail对键盘快捷键的依赖……这些人类习以为常的交互细节,对于只“看”DOM(文档对象模型)的AI来说,就像是在布满陷阱的迷宫里摸索。
这就是Hanzi Browse要解决的核心问题。它不是一个传统的、编写死板脚本的RPA(机器人流程自动化)工具,而是一个“浏览器上下文层”。简单说,它给AI智能体(比如Claude Code、Cursor、Codex等)配备了一双能在真实浏览器中“看”和“操作”的手,并附赠了一本针对24个主流网站的“通关秘籍”(Site Playbooks)。这本秘籍不是指令集,而是给AI的“提示”,告诉它:“嘿,这个网站喜欢异步加载,按钮可能藏在这里,你可以试试按这个快捷键。” AI依然主导思考和决策,但有了这些关键提示,成功率便从碰运气变成了可预期。
我花了几天时间深度测试了它的CLI模式和API模式。最让我印象深刻的是其设计哲学:将领域知识(Domain Knowledge)与执行引擎(Execution Engine)解耦。这意味着,当网站改版时,你无需重写整个自动化脚本,只需更新那条对应的“提示”,AI就能自己适应变化。这种思路,对于构建稳定、可维护的AI智能体应用来说,至关重要。
2. 核心架构解析:为什么是“提示”而非“脚本”?
在深入实操之前,有必要先理解Hanzi Browse的架构精髓。这决定了它为何比传统方案更灵活、更健壮。
2.1 传统自动化方案的瓶颈
传统的浏览器自动化,无论是通过Puppeteer、Playwright还是Selenium,其核心是编写精确的脚本:找到特定CSS选择器的元素,然后执行点击、输入等操作。这种方式在可控的测试环境下很有效,但面对动态内容、反爬虫机制、频繁的UI迭代时,脚本极其脆弱。一个选择器的微小变动就可能导致整个流程崩溃,维护成本高昂。
2.2 Hanzi Browse的“智能体循环”模式
Hanzi Browse引入了一个“智能体循环”(Agent Loop)的概念。这个循环由三个核心角色协同完成:
- 主智能体(Your AI Agent):比如你正在使用的Claude Code。它理解你的自然语言指令(如“申请工作”),并将其分解为高层次目标。
- 浏览子智能体(Browser Sub-agent):这是Hanzi Browse的核心。它接收主智能体的目标,在真实的Chrome浏览器环境中,执行一个“观察-思考-行动”的循环:
- 观察:获取当前页面的DOM、可交互元素列表、截图(视觉上下文)。
- 思考:结合网站玩法手册(Site Playbook)中的提示,决定下一步最佳操作(点击哪里、输入什么、是否滚动)。
- 行动:通过浏览器扩展执行操作。
- 重复:直到任务完成或无法继续。
- 网站玩法手册(Site Playbooks):这是“上下文层”的实体。它是一个JSON文件,为特定域名(如
linkedin.com)提供结构化的提示。例如,它可能包含:“connect按钮的文本可能显示为‘Connect’或‘Follow’,其父级容器可能有artdeco-button__text类。” 这不是命令,而是知识。
这种架构的优势在于“关注点分离”和“韧性”。AI负责理解和规划,Playbook提供领域知识,浏览器引擎负责可靠执行。当LinkedIn把按钮颜色从蓝色改成绿色时,你不需要修改任何代码,因为AI是根据语义(“连接按钮”)和Playbook提供的线索来寻找元素,而不是死板的CSS路径。
2.3 两种使用模式背后的统一引擎
项目提供了两种入口,但底层是同一套引擎:
- CLI / MCP 模式:面向开发者或终端用户。通过一条
npx hanzi-browse setup命令,它将浏览子智能体以“工具”的形式集成到你本地的AI编码助手(通过MCP协议)中。此后,你只需对AI说“用浏览器做X”,它就会自动调用Hanzi Browse来完成。 - API / SDK 模式:面向产品开发者。你可以将Hanzi Browse的浏览器自动化能力作为服务嵌入到自己的SaaS产品、内部工具或工作流中。用户通过配对链接授权自己的浏览器,然后你的后端就可以代表用户安全地执行任务。
这两种模式都调用相同的server/src/agent/domain-skills.json中的Playbooks,确保了行为的一致性。
3. 从零开始:CLI模式完整实操指南
让我们先从个人使用角度,体验如何将Hanzi Browse变成你AI助手的超能力。这里以macOS系统为例,Windows和Linux用户只需在命令终端上稍作调整。
3.1 环境准备与一键安装
首先,确保你的系统满足两个基本条件:安装了Node.js (18+)和一个基于Chromium的浏览器(如Chrome, Edge, Brave)。然后,打开你的终端。
安装过程被设计为极简的一键式。你不需要克隆仓库或手动配置任何东西。
npx hanzi-browse setup执行这个命令后,一个交互式向导会自动启动。它会依次完成以下六步,你可以在终端里清晰地看到进度:
- 检测浏览器:自动查找你系统里已安装的Chrome、Edge、Brave等。
- 安装浏览器扩展:它会打开Chrome网上应用店页面,并等待你手动点击‘添加至Chrome’。这是出于安全考虑,扩展需要你的明确授权。安装后,扩展图标会出现在浏览器工具栏。
- 检测AI智能体:扫描你的电脑,寻找支持的AI开发环境,如Claude Code、Cursor、Windsurf、VS Code(需安装相应AI插件)等。
- 配置MCP(模型上下文协议):这是关键一步。它会修改检测到的AI智能体的配置文件(通常是
mcp.json或claude_desktop_config.json),将hanzi-browse服务器添加为一个可用的工具源。这样,AI助手就知道可以调用这个“浏览器工具”了。 - 安装技能(Skills):将一系列预定义的“技能”描述文件复制到AI智能体的技能目录。这些技能是Markdown文件,教会AI“何时以及如何”使用浏览器工具来处理特定任务(如数据提取、社交发布等)。
- 选择AI模式:最后,向导会让你选择运行模式:
- 托管模式(Managed):省心之选。Hanzi Browse的后端使用Gemini等模型来处理“思考”部分。每月有20次免费任务,之后按 $0.05/次 计费。你的数据会发送到Hanzi的服务器进行处理。
- 自带模型模式(BYOM):隐私和成本之选。完全免费。你需要提供自己的AI API密钥(如OpenAI GPT-4、Anthropic Claude等)。整个“观察-思考-行动”循环都在你的本地机器上完成,截图和页面数据不会离开你的电脑。
实操心得与避坑指南:
- 扩展安装:如果第2步卡住,可能是因为网络问题无法打开应用商店。你可以手动访问 Chrome Web Store链接 进行安装。安装后,确保扩展是启用状态。
- 智能体检测失败:如果你常用的AI工具(比如某个特定的VS Code插件)没被检测到,可能是因为它使用了非标准的配置路径。此时可以查看Hanzi Browse在
~/.config/或~/Library/Application Support/下生成的日志文件,手动对照配置。- 模式选择:对于初步体验和简单任务,托管模式足够方便。但如果你处理的是敏感信息(如银行、邮箱),或者需要高频使用,强烈建议选择BYOM模式。你需要在后续配置中设置环境变量,如
ANTHROPIC_API_KEY或OPENAI_API_KEY。
3.2 首次任务测试与工作流体验
安装配置完成后,重启你的AI开发环境(如Cursor或Claude Code)。现在,你可以尝试给它一个真正的浏览器任务了。
在AI助手的聊天框里,你可以用自然语言输入:
“请使用浏览器工具,访问GitHub官网,搜索‘hanzi-browse’这个仓库,进入其主页,然后把项目描述读给我听。”接下来,你会观察到以下神奇的过程:
- AI理解与规划:你的主智能体(如Cursor)会识别出这是一个浏览器任务,并生成一个调用
browser_start工具的内部指令,将你的自然语言指令作为task参数传递进去。 - 浏览器启动:你的Chrome浏览器会自动打开一个新窗口(或标签页)。
- 智能体循环开始:浏览子智能体接管控制。
- 它首先导航到
github.com。 - 观察页面,发现搜索框。Playbook可能提示:“GitHub的搜索框主选择器是
[data-test-selector="nav-search-input"]”。 - 它模拟输入“hanzi-browse”并回车。
- 在搜索结果页,它识别出仓库链接并点击。
- 最终,在仓库主页,它提取
README.md区域的主要描述文本。
- 它首先导航到
- 结果返回:循环结束,子智能体将提取到的文本结果返回给主智能体。主智能体再组织语言,将结果呈现给你。
整个过程中,你不需要编写任何选择器或等待逻辑。AI在Playbook的提示下,自主完成了导航、识别、交互和提取。
注意事项:
- 任务描述要具体:“把项目描述读给我听”比“看看这个项目”要好。更具体的指令能减少AI的歧义。
- 耐心等待:复杂的任务可能需要几十个“观察-思考-行动”步骤,浏览器会真实地加载页面、等待元素,这需要时间。不要中途关闭浏览器窗口。
- 查看扩展日志:如果任务卡住了,点击浏览器工具栏的Hanzi Browse扩展图标,可以查看当前任务的详细执行日志和截图,这对于调试非常有帮助。
3.3 核心技能(Skills)详解与自定义
Hanzi Browse预装了一套“技能”,这些技能本质上是教导AI如何将复杂工作流分解为浏览器任务的“元提示”。例如,># Trello Weekly Export Use this skill when the user wants to automatically export their Trello board as a PDF every Monday. ## How to use 1. The user must be logged into Trello in the paired browser session. 2. Use the `browser_start` tool with a task like: "Go to my Trello board named 'Project Alpha', open the menu, find the 'Export as PDF' option, and download it." 3. The tool will handle navigation and clicking. You may need to guide it if the board name is ambiguous. ## Example User: "Can you save a PDF of my 'Q4 Planning' Trello board?" Assistant: I'll use the browser tool to export your Trello board. I need to know the exact name of the board, is it 'Q4 Planning'?
通过创建自定义技能,你可以不断扩展你的AI助手的能力边界,将其与你的个人工作流深度绑定。
4. 开发者视角:集成Hanzi Browse API构建产品
对于开发者而言,CLI模式是“消费”能力,而API/SDK模式则是“生产”能力。它允许你将稳定的浏览器自动化作为服务提供给最终用户。
4.1 架构概览与核心概念
当你使用SDK时,数据流是这样的:
你的后端服务器 -> Hanzi Browse API -> (通过配对链接) -> 用户浏览器 -> 执行结果返回给你的服务器关键点在于:任务是在最终用户的浏览器环境中执行的。这意味着:
- 登录态持久:用户只需配对一次,后续任务可以自动使用其已登录的会话(如Gmail、LinkedIn)。
- 安全边界:你的服务器永远不会接触到用户的密码或Cookie。
- 环境真实:规避了无头浏览器可能遇到的检测问题。
核心概念包括:
- API Key:你在Hanzi Browse开发者平台创建的凭证,用于认证API请求。
- 配对令牌(Pairing Token):一个有时效性的唯一令牌,用于将你的应用与一个用户浏览器实例绑定。
- 浏览器会话(Browser Session):配对成功后建立的持久连接,代表一个已授权的、可控制的浏览器实例。
- 任务(Task):一个需要浏览器执行的自然语言描述。
4.2 一步步实现一个“竞品监控”小工具
假设我们要构建一个SaaS工具,帮助用户监控竞争对手在X(原Twitter)上的动态。我们将使用Hanzi Browse SDK。
步骤一:获取API密钥并初始化SDK
首先,访问 Hanzi Browse Dashboard 注册并创建一个API密钥。然后,在你的Node.js项目中安装SDK并初始化客户端。
npm install @hanzi-browse/sdk// server/competitor-monitor.ts import { HanziClient } from '@hanzi-browse/sdk'; import dotenv from 'dotenv'; dotenv.config(); const client = new HanziClient({ apiKey: process.env.HANZI_API_KEY!, // 从环境变量读取 // 如果是本地开发,可以指定 baseUrl: 'http://localhost:3456' }); // 检查服务状态 async function checkHealth() { try { const health = await client.health(); console.log('服务状态:', health.status); } catch (error) { console.error('服务连接失败:', error); } }步骤二:实现用户浏览器配对流程
用户首次使用时,需要将其浏览器与你的应用配对。最佳实践是提供一个简单的配对页面。
// 后端API端点:生成配对链接 app.get('/api/pair', async (req, res) => { try { // 1. 向Hanzi API申请一个配对令牌 const { pairingToken } = await client.createPairingToken({ expiresIn: 3600, // 令牌1小时后过期 metadata: { userId: req.user.id } // 可附加自定义元数据,便于关联 }); // 2. 构造配对URL。你需要在前端引导用户点击此链接。 const pairingUrl = `https://api.hanzilla.co/pair/${pairingToken}`; // 如果是本地开发:`http://localhost:3456/pair/${pairingToken}` res.json({ pairingUrl, pairingToken }); } catch (error) { console.error('生成配对令牌失败:', error); res.status(500).json({ error: '配对服务暂时不可用' }); } }); // 前端页面 (pair.html) // 提供一个按钮,点击后调用上述API,然后将 pairingUrl 以二维码或可点击链接的形式展示给用户。 // 用户点击链接后,会跳转到Hanzi的引导页面,完成浏览器扩展的授权。步骤三:查询已配对会话并执行任务
用户配对后,你的后端就可以代表该用户执行任务了。
async function monitorCompetitorX(browserSessionId: string, competitorHandle: string) { const taskDescription = ` 请执行以下任务: 1. 导航到 X (twitter.com)。 2. 在搜索框中输入“@${competitorHandle}”并搜索。 3. 进入该用户的主页。 4. 获取其最近5条推文的以下信息: - 推文发布时间(精确到小时) - 推文正文内容 - 获得的点赞数 - 获得的转发数 5. 将以上信息整理成JSON格式返回。 `; console.log(`开始监控竞品 @${competitorHandle}...`); try { // runTask 是阻塞调用,会等待任务完成或超时 const result = await client.runTask({ browserSessionId, task: taskDescription, // 可选参数:设置超时、是否返回截图等 timeoutMs: 120000, // 2分钟超时 }); if (result.status === 'completed') { console.log('任务成功完成!'); // result.answer 包含了AI整理后的结果 const tweetsData = JSON.parse(result.answer); console.log('抓取到的推文数据:', tweetsData); // 在这里,你可以将 tweetsData 存入数据库,或触发后续分析、报警流程 return tweetsData; } else { console.error('任务失败:', result.error); // 可能是网络问题、页面结构变化或任务描述不清 // 可以尝试更详细的任务描述,或使用 browser_screenshot 工具调试 const screenshot = await client.browserScreenshot({ browserSessionId }); // 保存截图用于分析失败原因 return null; } } catch (error) { console.error('调用API失败:', error); return null; } } // 调用示例:假设我们已经从数据库拿到了用户的 browserSessionId const sessionId = 'user_123_browser_session'; const data = await monitorCompetitorX(sessionId, 'OpenAI');步骤四:处理异步与长任务
对于可能运行时间很长的任务(如监控多个竞品),runTask的阻塞等待可能不适用。可以使用异步轮询的方式。
async function runLongTaskAndPoll(browserSessionId: string, task: string) { // 1. 创建任务(非阻塞) const { id: taskId } = await client.createTask({ browserSessionId, task }); console.log(`任务已创建,ID: ${taskId}`); // 2. 轮询任务状态 let attempts = 0; const maxAttempts = 60; // 最多轮询60次 const pollInterval = 5000; // 每5秒一次 while (attempts < maxAttempts) { await new Promise(resolve => setTimeout(resolve, pollInterval)); attempts++; const taskStatus = await client.getTask({ taskId }); console.log(`轮询 ${attempts}/${maxAttempts}: 状态 - ${taskStatus.status}`); if (taskStatus.status === 'completed') { console.log('任务完成!结果:', taskStatus.answer); return taskStatus; } else if (taskStatus.status === 'failed' || taskStatus.status === 'stopped') { console.error('任务失败或停止:', taskStatus.error); return taskStatus; } // 状态为 'running' 或 'pending' 则继续轮询 } console.error('任务超时'); // 可以选择停止任务 await client.stopTask({ taskId }); return null; }开发经验与陷阱:
- 任务描述的艺术:API调用的成败,很大程度上取决于
task描述的清晰度。要像给一个细心但不懂技术的人写步骤说明一样,明确、有序、无歧义。包含网站名称、关键按钮的预期文本、需要提取的数据格式。- 会话管理:一个用户可能从多个设备(工作电脑、家庭电脑)配对,产生多个
browserSessionId。你的应用需要设计逻辑来决定使用哪个会话,或者让用户选择。- 错误处理与重试:网络波动、目标网站临时不可用、浏览器崩溃都可能导致任务失败。必须实现健壮的错误处理和重试机制,对于重要任务,可以考虑失败后通知用户重新配对或手动干预。
- 成本控制:如果使用托管模式,每个任务无论成功失败都可能计费(失败任务通常免费,但需确认)。务必在代码中设置合理的超时,并监控API使用量。对于BYOM模式,成本是你的AI API调用费用。
5. 深入原理:Site Playbooks与领域知识工程
Hanzi Browse的“智能”很大程度上来源于其Site Playbooks。理解它的设计,对于有效使用和贡献都至关重要。
5.1 Playbooks文件结构解析
Playbooks定义在server/src/agent/domain-skills.json中,是一个JSON数组。每个条目针对一个域名或一组域名。
[ { "domain": "linkedin.com", "skill": { "description": "LinkedIn 是一个职业社交网络,其界面动态加载,按钮状态复杂。", "selectors": { "primaryActionButton": ["button:has(> span:contains('Connect'))", "button[aria-label*='Connect']", ".artdeco-button--primary"], "messageInput": ["div[role='textbox']", ".msg-form__contenteditable"], "profileName": ["h1.text-heading-xlarge"] }, "behaviors": [ "页面滚动会触发动态加载更多内容。", "'Connect' 按钮在发送邀请后会变为 'Pending'。", "搜索结果的‘消息’按钮可能被隐藏,需要先点击‘更多’菜单。" ], "keyboardShortcuts": { "openMessaging": "k", "search": "/" } } }, { "domain": "github.com", "skill": { "description": "GitHub 是一个代码托管平台,使用了许多自定义的 React 组件和动态渲染。", "selectors": { "searchBox": ["input[data-test-selector='nav-search-input']", "input[placeholder='Search GitHub']"], "repoLinkInSearch": ["a[data-hydro-click*='repository']"], "readmeContent": ["article.markdown-body"] }, "behaviors": [ "仓库主页的 README 可能在‘About’部分或独立的标签页中。", "需要等待 AJAX 请求完成才能获取完整的文件列表。" ] } } ]- domain:字符串或数组,用于URL匹配。
- skill:包含以下核心部分:
- description:网站的基本描述。
- selectors:这不是唯一的元素定位方式,而是给AI的“线索”。AI会结合这些选择器、元素文本、ARIA属性等多种信号来定位目标。提供多个备选选择器能提高鲁棒性。
- behaviors:描述网站特有的交互模式或“坑”。这是最有价值的部分,是传统脚本难以编码的隐性知识。
- keyboardShortcuts:列出可用的快捷键,AI可以优先使用更可靠的键盘操作而非鼠标点击。
5.2 如何为新的网站贡献Playbook
当你发现Hanzi Browse对某个网站支持不好时,可以为其贡献Playbook。
- 观察与分析:手动在目标网站上完成你想自动化的任务。用浏览器的开发者工具(F12)仔细观察:
- 关键元素的特征:它的CSS类、ID、
>问题现象可能原因 排查步骤与解决方案 CLI安装后AI助手不识别浏览器工具 1. MCP配置未生效。
2. AI智能体未重启。
3. 技能文件未正确安装。1. 检查AI智能体的配置文件(如 ~/.cursor/mcp.json),确认hanzi-browse的command路径正确且服务器在运行 (ps aux | grep hanzi-browse)。
2.完全退出并重启AI智能体应用。
3. 检查技能目录是否存在对应的.md技能文件。任务启动后浏览器无反应或立即关闭 1. 浏览器扩展未启用或未配对。
2. 本地服务器 (hanzi-browse) 未运行。
3. 防火墙/端口阻塞。1. 点击浏览器扩展图标,检查状态是否为“已连接”。如未连接,尝试重新配对或重装扩展。
2. 在终端运行curl http://localhost:3456/v1/health检查本地API服务是否健康。
3. 确保端口3456未被其他程序占用。任务卡在某个步骤,AI不断重复操作 1. 页面元素未按预期出现(网络慢、JS错误)。
2. Playbook提示不足或过时。
3. 任务描述存在歧义。1. 打开扩展的调试日志,查看AI“看到”的页面快照和计划的下一个动作。判断是页面没加载完,还是AI找不到元素。
2. 尝试更详细的任务描述,例如明确指定按钮的完整文本。
3. 考虑为该网站贡献或改进Playbook。BYOM模式下任务速度很慢 1. 本地AI API(如OpenAI)响应慢。
2. 页面内容过多,导致观察步骤的上下文太长。
3. 网络延迟。1. 考虑使用更快的模型(如 gpt-4o-mini比gpt-4快)。
2. 在任务描述中可要求AI“只关注主要内容区域”,或未来期待Hanzi Browse支持更智能的页面内容过滤。
3. 确保网络连接稳定。API调用返回“无效的会话ID” 1. 用户浏览器已关闭或扩展被禁用。
2. 配对令牌过期。
3. 服务器端会话清理。1. 引导用户重新打开浏览器并确保扩展启用。
2. 实现重配对流程:当检测到会话失效时,引导用户生成新的配对链接。
3. 设计你的应用逻辑,定期检查会话有效性,或在执行关键任务前先发一个简单的browser_status请求验证。托管模式任务费用意外增高 1. 任务逻辑循环导致步骤过多。
2. 网站结构复杂,AI需要更多“思考”步骤。1. 优化任务描述,使其更直接、明确,减少AI的探索步骤。
2. 对于复杂但重复的任务,考虑将其拆解,用多个简单的、可缓存结果的子任务组合完成。6.2 性能与成本优化建议
- 任务描述精细化:这是最重要的优化点。模糊的指令会导致AI进行大量探索。清晰的指令如“在页面顶部的搜索框,输入‘XXX’并按下回车”比“搜索XXX”效率高得多。
- 利用
browser_screenshot进行调试:在开发阶段,如果任务失败,可以编程式地调用browser_screenshot获取失败时的页面截图,这比看日志更直观,能帮你改进Playbook或任务描述。 - 会话复用与预热:对于需要用户登录的任务,尽量复用同一个
browserSessionId,避免每次任务都重新登录。可以在用户不活跃时,通过执行一个微小任务(如访问 about:blank)来保持会话活跃,防止超时断开。 - 设置合理的超时:根据任务复杂度,在API调用中设置
timeoutMs。避免因一个卡住的任务长时间占用资源并产生费用。 - BYOM模式下的模型选择:如果你使用自己的API密钥,可以权衡速度、成本和智能程度。对于结构化的、重复性的任务,
gpt-4o-mini或claude-3-haiku可能比gpt-4或claude-3-opus更具性价比。
经过一段时间的深度使用,我认为Hanzi Browse代表了AI智能体走向实用化的重要一步。它没有试图用僵硬的脚本取代AI,而是选择增强AI,将人类的领域知识(Playbooks)与AI的泛化能力、浏览器的真实渲染能力相结合。这种“人机协同”的设计思路,使得它既能处理今天复杂的Web交互,也具备了适应明天Web变化的潜力。对于开发者而言,它提供了一个前所未有的、能够安全操作用户真实浏览器环境的API,这为构建下一代“主动式”的SaaS工具和个性化助手打开了大门。当然,它目前仍处于早期阶段,对非常规网站的覆盖和极端复杂任务的稳定性还有提升空间,但其架构和理念已经奠定了坚实的基础。
- 关键元素的特征:它的CSS类、ID、