结构化
将杂乱的网页数据转换为符合 schema 的干净对象。
文档索引
可在此获取完整文档索引:https://docs.stagehand.dev/llms.txt
在进一步浏览前,可使用该文件发现所有可用页面。
从网页中提取结构化数据
extract()?await stagehand.extract("提取这个仓库的名称");extract() 用于从网页中抓取结构化数据。你可以使用 Zod(TypeScript)或 JSON 来定义 schema。如果你不想定义 schema,也可以只用自然语言提示词来调用 extract,或者在不传参数的情况下调用 extract。
extract()?结构化
将杂乱的网页数据转换为符合 schema 的干净对象。
更稳健
构建在网站变化时也不容易失效的提取流程。
当你使用 extract() 时,Stagehand 会返回一个 Promise<ExtractResult>,其结构如下:
当使用 schema 进行提取时,返回类型会从你的 Zod schema 中自动推断:
const result = await stagehand.extract( "提取商品详情", z.object({ name: z.string(), price: z.number(), inStock: z.boolean() }));示例结果:
{ name: "Wireless Mouse", price: 29.99, inStock: true}当提取数组时,你会得到一个对象数组:
const apartments = await stagehand.extract( "提取所有公寓房源", z.array( z.object({ address: z.string(), price: z.string(), sqft: z.number() }) ));示例结果:
[ { address: "123 Main St", price: "$1,200/mo", sqft: 750 }, { address: "456 Oak Ave", price: "$1,500/mo", sqft: 900 }]当提取单个原始值时:
const price = await stagehand.extract( "提取价格", z.number());示例结果:
19.99你也可以提取字符串、布尔值等:
const url = await stagehand.extract( "提取联系页面链接", z.string().url());当只传入一条指令时(不带 schema):
const result = await stagehand.extract("提取仓库名称");示例结果:
{ extraction: "stagehand"}当不传任何参数时:
const result = await stagehand.extract();示例结果:
{ pageText: "Accessibility Tree:\n[0-2] RootWebArea: Page Title\n [0-37] scrollable\n [0-118] body\n ..."}这会直接返回页面的无障碍树表示,而不会经过 LLM 处理。
你可以传入额外选项来配置模型、超时时间以及选择器范围:
const result = await stagehand.extract("提取仓库名称", { model: "anthropic/claude-sonnet-4-5", timeout: 30000, selector: "//header" // 聚焦到特定区域});当运行在 Browserbase 上时,Stagehand 会自动在服务端缓存 extract() 的结果。对于输入完全相同的重复调用,会立即返回结果,而不会消耗 LLM token。缓存默认开启,你可以在构造函数中全局控制它,也可以在单次调用时覆盖:
// 为整个实例禁用服务端缓存const stagehand = new Stagehand({ env: "BROWSERBASE", serverCache: false,});
// 或者仅为单次调用禁用const data = await stagehand.extract("提取仓库名称", { serverCache: false });
// 检查结果是否来自缓存const result = await stagehand.extract("提取页面标题");console.log(result.cacheStatus); // "HIT" 或 "MISS"给 extract 传入一个 selector,可以将提取目标限定到页面中的某个特定元素。
const tableData = await stagehand.extract( "提取第三行的值", z.object({ values: z.array(z.string()) }), { // xPath 或 CSS 选择器 selector: "xpath=/html/body/div/table/" });你也可以使用 ignoreSelectors 排除特定节点(以及它们的所有后代节点)。
const article = await stagehand.extract( "提取文章标题和正文", z.object({ title: z.string(), body: z.string() }), { ignoreSelectors: [".ad", ".newsletter-modal", "nav.related-posts"] });你可以为 schema 提供额外上下文,以帮助模型更准确地提取数据。
const apartments = await stagehand.extract( "提取所有公寓房源及其详细信息,包括地址、价格和面积。", z.array( z.object({ address: z.string().describe("公寓的地址"), price: z.string().describe("公寓的价格"), square_feet: z.string().describe("公寓的平方英尺面积"), }) ));下面是一个用于提取链接或 URL 的 extract 调用示例。它同样适用于图片链接。
const contactLink = await stagehand.extract( "提取“联系我们”页面的链接", z.string().url() // 注意:这里使用 z.string().url() 来校验 URL);
console.log("联系我们页面的链接是:", contactLink);问题:extract() 返回空数据或不完整的数据。
解决方案:
stagehand.observe() 确认页面上存在目标数据。stagehand.act("wait for the content to load")。示例:提取前先等待内容加载
// 提取前先等待内容加载await stagehand.act("wait for the product listings to load");const products = await stagehand.extract( "提取所有商品名称和价格", z.array(z.object({ name: z.string(), price: z.string() })));问题:出现 schema 校验错误或类型不匹配。
解决方案:
z.optional() 将字段设为可选。z.string() 而不是 z.number()。.describe() 帮助模型理解字段要求。示例:使用更灵活的 schema
const schema = z.object({ price: z.string().describe("包含货币符号的价格,例如 '$19.99'"), availability: z.string().optional().describe("如有库存状态则提取"), rating: z.number().optional()});问题:不同运行之间的提取结果不一致。
解决方案:
stagehand.observe() 了解页面结构。示例:先用 observe 验证
// 先 observe,理解页面结构const elements = await stagehand.observe("查找所有商品列表");console.log("找到的元素:", elements.map(e => e.description));
// 然后进行有针对性的提取const products = await stagehand.extract( "从页面显示的每个商品列表中提取名称和价格", z.array(z.object({ name: z.string().describe("商品标题或名称"), price: z.string().describe("页面上显示的价格,包含货币信息") })));问题:提取速度很慢或发生超时。
解决方案:
timeoutMs 参数。示例:拆分大型提取任务
// 不要一次提取所有内容const allData = [];const pageNumbers = [1, 2, 3, 4, 5];
for (const pageNum of pageNumbers) { await stagehand.act(`navigate to page ${pageNum}`);
const pageData = await stagehand.extract( "仅提取当前页面中的商品数据", z.array(z.object({ name: z.string(), price: z.number() })), { timeout: 60000 } // 60 秒超时 );
allData.push(...pageData);}