名称: browse
描述: 使用 stagehand CLI 创建和部署浏览器自动化功能的完整指南
主页: https://browserbase.com
元数据: {"moltbot":{"emoji":"🌐","requires":{"bins":["stagehand"],"env":["BROWSERBASE_API_KEY","BROWSERBASE_PROJECT_ID"]},"primaryEnv":"BROWSERBASE_API_KEY"}}
使用 stagehand CLI 创建和部署浏览器自动化功能的完整指南。
stagehand fn auth status # 检查是否已配置
stagehand fn auth login # 如果需要 - 从 https://browserbase.com/settings 获取凭据
启动本地浏览器会话以了解网站结构:
stagehand session create --local
stagehand goto https://example.com
stagehand snapshot # 获取带引用的 DOM 结构
stagehand screenshot -o page.png # 可视化检查
手动测试交互:
stagehand click @0-5
stagehand fill @0-6 "value"
stagehand eval "document.querySelector('.price').textContent"
stagehand session end # 探索完成后结束会话
stagehand fn init my-automation
cd my-automation
创建以下文件:
- package.json - 依赖项
- .env - 凭据(来自 ~/.stagehand/config.json)
- index.ts - 函数模板
- tsconfig.json - TypeScript 配置
严重错误:stagehand fn init 生成的 package.json 不完整,会导致部署失败并显示“未构建任何函数”。
必需修复 - 在进行任何其他操作之前更新 package.json:
{
"name": "my-automation",
"version": "1.0.0",
"description": "我的自动化描述",
"main": "index.js",
"type": "module",
"packageManager": "pnpm@10.14.0",
"scripts": {
"dev": "pnpm bb dev index.ts",
"publish": "pnpm bb publish index.ts"
},
"dependencies": {
"@browserbasehq/sdk-functions": "^0.0.5",
"playwright-core": "^1.58.0"
},
"devDependencies": {
"@types/node": "^25.0.10",
"typescript": "^5.9.3"
}
}
与生成文件的关键更改:
- ✅ 添加 description 和 main 字段
- ✅ 添加 packageManager 字段
- ✅ 将 "latest" 更改为固定版本,如 "^0.0.5"
- ✅ 添加包含 TypeScript 和类型定义的 devDependencies
然后安装:
pnpm install
编辑 index.ts:
import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";
defineFn("my-automation", async (context) => {
const { session, params } = context;
console.log("连接到浏览器会话:", session.id);
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
// 在此处编写自动化逻辑
await page.goto("https://example.com");
await page.waitForLoadState("domcontentloaded");
// 提取数据
const data = await page.evaluate(() => {
// 复杂的数据提取逻辑
return Array.from(document.querySelectorAll('.item')).map(el => ({
title: el.querySelector('.title')?.textContent,
value: el.querySelector('.value')?.textContent,
}));
});
// 返回结果(必须是 JSON 可序列化的)
return {
success: true,
count: data.length,
data,
timestamp: new Date().toISOString(),
};
});
关键概念:
- context.session - 浏览器会话信息(id, connectUrl)
- context.params - 调用时传入的输入参数
- 返回 JSON 可序列化的数据
- 最长执行时间为 15 分钟
启动开发服务器:
pnpm bb dev index.ts
服务器运行在 http://127.0.0.1:14113
使用 curl 调用:
curl -X POST http://127.0.0.1:14113/v1/functions/my-automation/invoke \
-H "Content-Type: application/json" \
-d '{"params": {"url": "https://example.com"}}'
开发服务器会在文件更改时自动重新加载。检查终端以查看日志。
pnpm bb publish index.ts
# 或:stagehand fn publish index.ts
预期输出:
✓ 构建成功完成
构建 ID:xxx-xxx-xxx
函数 ID:yyy-yyy-yyy ← 保存此 ID!
如果看到“未构建任何函数” → 你的 package.json 不完整(参见步骤 3)。
stagehand fn invoke <function-id> -p '{"param": "value"}'
或通过 API:
curl -X POST https://api.browserbase.com/v1/functions/<function-id>/invoke \
-H "Content-Type: application/json" \
-H "x-bb-api-key: $BROWSERBASE_API_KEY" \
-d '{"params": {}}'
import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";
defineFn("hn-scraper", async (context) => {
const { session } = context;
console.log("连接到浏览器会话:", session.id);
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
await page.goto("https://news.ycombinator.com");
await page.waitForLoadState("domcontentloaded");
// 提取前 10 条故事
const stories = await page.evaluate(() => {
const storyRows = Array.from(document.querySelectorAll('.athing')).slice(0, 10);
return storyRows.map((row) => {
const titleLine = row.querySelector('.titleline a');
const subtext = row.nextElementSibling?.querySelector('.subtext');
const commentsLink = Array.from(subtext?.querySelectorAll('a') || []).pop();
return {
rank: row.querySelector('.rank')?.textContent?.replace('.', '') || '',
title: titleLine?.textContent || '',
url: titleLine?.getAttribute('href') || '',
points: subtext?.querySelector('.score')?.textContent?.replace(' points', '') || '0',
author: subtext?.querySelector('.hnuser')?.textContent || '',
time: subtext?.querySelector('.age')?.textContent || '',
comments: commentsLink?.textContent?.replace(/\u00a0comments?/, '').trim() || '0',
id: row.id,
};
});
});
return {
success: true,
count: stories.length,
stories,
timestamp: new Date().toISOString(),
};
});
defineFn("scrape", async (context) => {
const { session, params } = context;
const { url, selector } = params; // 从调用中接收参数
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
await page.goto(url);
const data = await page.$$eval(selector, els =>
els.map(el => el.textContent)
);
return { url, data };
});
defineFn("auth-action", async (context) => {
const { session, params } = context;
const { username, password } = params;
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
await page.goto("https://example.com/login");
await page.fill('input[name="email"]', username);
await page.fill('input[name="password"]', password);
await page.click('button[type="submit"]');
await page.waitForURL("**/dashboard");
const data = await page.textContent('.user-data');
return { success: true, data };
});
defineFn("multi-page", async (context) => {
const { session, params } = context;
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
const results = [];
for (const url of params.urls) {
await page.goto(url);
await page.waitForLoadState("domcontentloaded");
const title = await page.title();
results.push({ url, title });
}
return { results };
});
这是最常见的错误!
原因: stagehand fn init 生成的 package.json 不完整。
修复方法:
1. 更新 package.json(参见上面的步骤 3)
2. 添加所有必需字段:description、main、packageManager
3. 将 "latest" 更改为固定版本,如 "^0.0.5"
4. 添加包含 TypeScript 和类型定义的 devDependencies 部分
5. 运行 pnpm install
6. 再次尝试部署
快速检查: 将你的 package.json 与代码库中的 bitcoin-functions/package.json 进行比较。
# 检查凭据
stagehand fn auth status
# 如果需要,重新登录
stagehand fn auth login
# 全局安装 SDK
pnpm add -g @browserbasehq/sdk-functions
常见原因:
1. 缺少 devDependencies(TypeScript 无法编译)
2. 使用 "latest" 而不是固定版本
3. package.json 中缺少必需字段
解决方案: 按照步骤 3 的描述修复 package.json。
stagehand screenshot -o debug.pngstagehand snapshotpage.evaluate() 记录 DOM 中的内容stagehand fn init 之后console.log() 有助于调试已部署的函数paramsstagehand session create --local 探索网站stagehand fn init <name>pnpm installindex.ts 中编写自动化代码pnpm bb dev index.tspnpm bb publish index.tsstagehand fn invoke <function-id>文件: /src/commands/functions.ts
行号: 146-158
函数: initFunction()
将当前的 packageJson 对象替换为:
const packageJson = {
name,
version: '1.0.0',
description: `${name} function`,
main: 'index.js',
type: 'module',
packageManager: 'pnpm@10.14.0',
scripts: {
dev: 'pnpm bb dev index.ts',
publish: 'pnpm bb publish index.ts',
},
dependencies: {
'@browserbasehq/sdk-functions': '^0.0.5',
'playwright-core': '^1.58.0',
},
devDependencies: {
'@types/node': '^25.0.10',
'typescript': '^5.9.3',
},
};
这将为所有新项目消除“未构建任何函数”的错误。