browser-use 完整教程:自动查询多个网站并整理结果
配置本地 browser-use 与模型,查询三个明确的软件文档来源,输出带证据的功能对照,并检查来源遗漏、失败与结构化结果。
跨网站查询软件功能时,任务不应只是“上网查一查然后总结”。如果没有指定来源、比较字段和失败表达,助手很容易把记忆里的信息写成刚刚读取的事实。
本文面向有 Python 基础的浏览器 Agent 初学者。我们读取 Crawlee、Playwright 和 Reader 的指定官方页面,整理 JavaScript 页面支持与模型依赖,输出带来源和证据的对照。示例使用本地浏览器与读者配置的模型;不是云浏览器套餐,也不测工具性能。
准备输入地址
先在浏览器找到下列页面并确认内容,再从地址栏复制完整地址。服务或仓库地址从相应账户设置、官方项目的接入说明或克隆菜单取得。不要从示例输出中反推真实地址。
CRAWLEE_DOC_URL:Crawlee JavaScript quick-start 官方页面地址。PLAYWRIGHT_DOC_URL:Playwright Python intro 官方页面地址。READER_REPO_URL:vakra-dev/reader 官方仓库页面地址。
在执行后续命令的同一个 Bash/WSL 终端中设置:
export CRAWLEE_DOC_URL='<paste-the-actual-crawlee-doc-url>'
export PLAYWRIGHT_DOC_URL='<paste-the-actual-playwright-doc-url>'
export READER_REPO_URL='<paste-the-actual-reader-repo-url>'下文 JSON 或任务参数中的 <变量名> 是待替换标记,提交前填写刚复制的实际值;JSON 不会自动展开环境变量。结果示例中的 example.16yun.cn 只表示来源字段的形状,不是本文部署的演示站。
先写清比较问题与来源
这三个项目承担的职责不同,因此不按“谁最强”排列。我们只询问明确的问题:提供什么浏览器或页面能力,完成基本用法是否必须依赖模型,依据来自哪里。
来源固定在三页,不让 Agent 自由搜索无限扩张。某页无法访问就标 unavailable,不能用其他网站的摘要代替而不说明。来源内容中的营销结论不自动成为对照表里的独立事实。
安装并准备本地浏览器
使用 uv 与 Python 3.12,命令采用 Bash:
uv init --python 3.12 browser-comparison
cd browser-comparison
uv add browser-use==0.13.14 python-dotenv
uv run browser-use install浏览器安装需要网络;Linux 还可能需要系统依赖。安装方法与本地运行说明见 browser-use 官方项目。
创建本地 .env:
OPENAI_API_KEY=replace-with-your-key
MODEL_NAME=replace-with-an-available-model这里选用库的 ChatOpenAI 适配器。模型名取你账户实际可用值;换用其他模型服务时,同时更换对应适配器与配置,不把所有协议都视为相同。
不要把本地模型接口或真实密钥写到文章里共享。执行示例会调用读者自己的模型服务,产生相应使用成本。
定义任务输出,允许明确失败
创建 compare_sites.py:
import asyncio
import json
import os
from pathlib import Path
from typing import Literal
from dotenv import load_dotenv
from pydantic import BaseModel
from browser_use import Agent, Browser, ChatOpenAI
load_dotenv()
sources = {
"crawlee": os.environ["CRAWLEE_DOC_URL"],
"playwright": os.environ["PLAYWRIGHT_DOC_URL"],
"reader": os.environ["READER_REPO_URL"],
}
class ToolRow(BaseModel):
id: Literal["crawlee", "playwright", "reader"]
status: Literal["read", "unavailable"]
javascript_support: str | None
model_required_for_basic_use: bool | None
evidence_quote: str | None
source_url: str
class Comparison(BaseModel):
rows: list[ToolRow]
async def main():
browser = Browser(
use_cloud=False,
allowed_domains=["crawlee.dev", "playwright.dev", "github.com"],
)
agent = Agent(
task=(
"逐一打开以下官方来源,只依据对应页面回答,不使用记忆补缺:"
+ json.dumps(sources)
+ "。每个来源返回一条记录。说明 JavaScript 页面支持,"
"以及基本用法是否必须依赖模型,附简短原文证据。"
"source_url 使用给定来源。无法访问时 status=unavailable,"
"其他未知字段为 null。不要注册、购买、登录或修改站点。"
),
llm=ChatOpenAI(model=os.environ["MODEL_NAME"]),
browser=browser,
output_model_schema=Comparison,
max_failures=3,
)
history = await agent.run(max_steps=24)
history.save_to_file("history.json")
raw = history.final_result()
if not raw:
raise RuntimeError("Agent 没有返回最终数据,请查看 history.json")
result = Comparison.model_validate_json(raw)
ids = [row.id for row in result.rows]
if len(ids) != len(sources) or set(ids) != set(sources):
raise ValueError("来源记录存在重复或遗漏")
for row in result.rows:
if row.source_url.rstrip("/") != sources[row.id].rstrip("/"):
raise ValueError("结果来源不是指定页面")
if row.status == "read" and not row.evidence_quote:
raise ValueError("已读取记录缺少证据")
Path("comparison.json").write_text(
result.model_dump_json(indent=2), encoding="utf-8"
)
incomplete = not history.is_successful() or any(
row.status != "read" for row in result.rows
)
print({"records": len(result.rows), "incomplete": incomplete})
if incomplete:
raise SystemExit(1)
asyncio.run(main())运行:
uv run python compare_sites.py本例按默认生命周期在 Agent.run 结束时清理浏览器。没有设置 keep_alive,也不额外创建长期会话。需要保留浏览器调试时,要另外明确会话所有者和结束方式,不能只加一个常驻开关就忘记回收。
为什么步骤上限与 Schema 都不够
max_steps 限制 Agent 动作轮次,不是严格总运行秒数,也不保证在上限内取得所有资料。步骤不足时查看 history,判断是页面打不开、反复导航还是任务描述不明确,不先无限提高上限。
Schema 检查 JSON 字段形状,不能证明 Agent 真正读过网页。脚本还核对来源集合、重复与原文证据,并保留历史。即便 Agent 自己标成功,仍要人工确认引用确实支持对应结论。
允许 unavailable 是为了表达部分失败。它与“这个工具不支持某功能”不同:无法访问页面不能成为产品能力的否定结论。
怎样检查并使用结果
comparison.json 每行对应一个指定来源,结构示例如下,具体值由页面证据决定:
{
"id": "reader",
"status": "unavailable",
"javascript_support": null,
"model_required_for_basic_use": null,
"evidence_quote": null,
"source_url": "https://example.16yun.cn/reader"
}这条示例明确失败,不是模型返回记录。成功记录应有简短原文证据;把它与原页面比较,检查是否把“支持浏览器”误写成“必须使用浏览器”,或把可选模型能力写成基本用法必需。
整理表格时保留 status 和 source_url。不要为了表格整齐把 null 改成“否”;未知、无法访问和确定不支持是三种不同含义。
保存的 history 可能包含页面内容和动作,按本地任务材料管理,不当成可无条件公开的日志。本文只读取公开文档,也不需要动作录像。
遇到失败怎样重做
模型鉴权失败。 检查 env 是否被加载、适配器和模型名是否匹配。浏览器页面正常不代表模型服务正常。
本地浏览器启动失败。 检查安装命令与运行账户、浏览器二进制和 Linux 依赖。use_cloud=False 不会替你补一个有效的云浏览器账户。
allowed_domains 拦住跳转。 查看目标实际重定向地址。只有确定仍属于预期官方来源时才增加必要域名,不直接放开所有网站。
只返回两条来源。 根据 history 找出未处理项,将任务缩小到该来源后补查。合并时保留原来源 ID 与新的观测,不覆盖其他已核对记录。
引用看起来合理但原文没有。 该记录不能作为已证实信息。重新打开指定页面,缩小提取问题并核对材料;结构化输出成功不能关闭事实错误。
步骤都在重复。 检查页面是否卡在相同状态,任务是否同时要求搜索、比较、登录和导出。把本次任务保持在三个明确来源与两个问题上,再决定是否扩展。
这种写法让跨站 Agent 有明确的任务边界和失败去向。最终对照表的价值来自可回查的来源,而不是一段流畅但无法追溯的总结。
需要企业代理方案?
我们可根据目标站点、并发规模与稳定性目标提供定制方案。