名称: functions
描述: 指导 Claude 使用官方 bb CLI 部署无服务器浏览器自动化
指导 Claude 使用官方 bb CLI 部署无服务器浏览器自动化。
在以下情况使用此技能:
- 用户希望部署按计划运行的自动化任务
- 用户需要浏览器自动化的 Webhook 端点
- 用户希望在云端(而非本地)运行自动化
- 用户询问关于 Browserbase Functions
从以下地址获取 API 密钥和项目 ID:https://browserbase.com/settings
直接设置:
export BROWSERBASE_API_KEY="your_api_key"
export BROWSERBASE_PROJECT_ID="your_project_id"
pnpm dlx @browserbasehq/sdk-functions init my-function
cd my-function
这将创建:
my-function/
├── package.json
├── index.ts # 你的函数代码
└── .env # 在此添加凭证
# 从存储的凭证复制
echo "BROWSERBASE_API_KEY=$BROWSERBASE_API_KEY" >> .env
echo "BROWSERBASE_PROJECT_ID=$BROWSERBASE_PROJECT_ID" >> .env
或手动编辑 .env:
BROWSERBASE_API_KEY=your_api_key
BROWSERBASE_PROJECT_ID=your_project_id
pnpm install
import { defineFn } from "@browserbasehq/sdk-functions";
import { chromium } from "playwright-core";
defineFn("my-function", async (context) => {
const { session, params } = context;
// 连接到浏览器
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
// 你的自动化逻辑
await page.goto(params.url || "https://example.com");
const title = await page.title();
// 返回可 JSON 序列化的结果
return { success: true, title };
});
关键对象:
- context.session.connectUrl - 用于连接 Playwright 的 CDP 端点
- context.params - 调用时传入的输入参数
pnpm bb dev index.ts
服务器运行在 http://127.0.0.1:14113
curl -X POST http://127.0.0.1:14113/v1/functions/my-function/invoke \
-H "Content-Type: application/json" \
-d '{"params": {"url": "https://news.ycombinator.com"}}'
开发服务器会在文件更改时自动重载。使用 console.log() 进行调试,输出会显示在终端中。
pnpm bb publish index.ts
输出:
Function published successfully
Build ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Function ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
保存 Function ID - 调用时需要用到它。
# 开始调用
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": {"url": "https://example.com"}}'
# 响应:{"id": "INVOCATION_ID"}
# 轮询结果
curl "https://api.browserbase.com/v1/functions/invocations/INVOCATION_ID" \
-H "x-bb-api-key: $BROWSERBASE_API_KEY"
async function invokeFunction(functionId: string, params: object) {
// 开始调用
const invokeRes = await fetch(
`https://api.browserbase.com/v1/functions/${functionId}/invoke`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-bb-api-key': process.env.BROWSERBASE_API_KEY!,
},
body: JSON.stringify({ params }),
}
);
const { id: invocationId } = await invokeRes.json();
// 轮询直到完成
while (true) {
await new Promise(r => setTimeout(r, 5000));
const statusRes = await fetch(
`https://api.browserbase.com/v1/functions/invocations/${invocationId}`,
{ headers: { 'x-bb-api-key': process.env.BROWSERBASE_API_KEY! } }
);
const result = await statusRes.json();
if (result.status === 'COMPLETED') return result.results;
if (result.status === 'FAILED') throw new Error(result.error);
}
}
defineFn("scrape", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
await page.goto(params.url);
await page.waitForSelector(params.selector);
const items = await page.$$eval(params.selector, els =>
els.map(el => el.textContent?.trim())
);
return { url: params.url, items };
});
defineFn("authenticated-action", async ({ session, 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('[name="email"]', params.email);
await page.fill('[name="password"]', params.password);
await page.click('button[type="submit"]');
await page.waitForURL('**/dashboard');
// 执行需要身份验证的操作
const data = await page.textContent('.user-data');
return { data };
});
defineFn("safe-scrape", async ({ session, params }) => {
const browser = await chromium.connectOverCDP(session.connectUrl);
const page = browser.contexts()[0]!.pages()[0]!;
try {
await page.goto(params.url, { timeout: 30000 });
await page.waitForSelector(params.selector, { timeout: 10000 });
const data = await page.textContent(params.selector);
return { success: true, data };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : '未知错误'
};
}
});
| 命令 | 描述 |
|---|---|
pnpm dlx @browserbasehq/sdk-functions init <name> |
创建新项目 |
pnpm bb dev <file> |
启动本地开发服务器 |
pnpm bb publish <file> |
部署到 Browserbase |
# 检查 .env 文件是否有凭证
cat .env
# 或为当前 shell 设置
export BROWSERBASE_API_KEY="your_key"
export BROWSERBASE_PROJECT_ID="your_project"
# 确保 SDK 已安装
pnpm add @browserbasehq/sdk-functions
# 或使用 npx
npx @browserbasehq/sdk-functions dev index.ts
waitForSelector 而不是 sleepsession.connectUrlchromium.connectOverCDP() 而不是 chromium.launch()