上周五下班前,运营同事扔过来一个需求:"帮我从20个网站上把竞品价格抓下来,每天一次。"
我看了一眼那些网站,有的要登录,有的价格藏在弹窗里,有的还有验证码。写 Selenium 脚本?光处理登录态就得搞半天。写 Playwright?动态渲染页面调试到头秃。
后来我试了 browser-use。一个 Python 库,8万多 GitHub stars,干的事情简单粗暴:你用自然语言告诉 AI 要做什么,它自己去操作浏览器。不用写 CSS 选择器,不用处理页面加载等待,AI 自己看页面、点按钮、填表单。
花了一个多小时搞定,记录一下过程。
安装和环境配置
browser-use 需要 Python 3.11 或更高版本。用 uv 管理环境最省事:
bash
# 创建虚拟环境
pip install uv
uv venv --python 3.12
source .venv/bin/activate
# 安装 browser-use 和浏览器内核
uv pip install browser-use
uvx browser-use install
uvx browser-use install 会自动下载 Chromium,不用自己折腾浏览器驱动。
接下来配置 API Key。browser-use 支持多家 LLM,我用的是 Gemini(免费额度够用):
bash
# 创建 .env 文件
touch .env
echo "GOOGLE_API_KEY=你的key" >> .env
也可以用 OpenAI 或 Anthropic,换个环境变量就行:
bash
# OpenAI
OPENAI_API_KEY=你的key
# Anthropic
ANTHROPIC_API_KEY=你的key
第一个例子:让 AI 去搜东西
先跑个最简单的,确认环境没问题:
python
from browser_use import Agent, ChatGoogle
from dotenv import load_dotenv
import asyncio
load_dotenv()
async def main():
llm = ChatGoogle(model="gemini-flash-latest")
agent = Agent(
task="打开百度,搜索'browser-use github',告诉我第一个结果的标题",
llm=llm
)
result = await agent.run()
print(result)
if __name__ == "__main__":
asyncio.run(main())
运行后会弹出一个 Chrome 窗口,你能看到 AI 在操作:打开百度、输入搜索词、点搜索、读取结果。整个过程大概15秒。
第一次跑的时候我盯着屏幕看了好几遍------它真的在自己打字、自己点按钮。跟之前写的那些脚本完全是两回事。
真实场景:自动填写表单
搜索太简单了。来个实际的:自动登录一个后台系统,填写表单提交数据。
python
from browser_use import Agent, Browser, BrowserConfig, ChatGoogle
from dotenv import load_dotenv
import asyncio
load_dotenv()
async def main():
# 配置浏览器:用自己本地的 Chrome,保留登录态
browser = Browser(config=BrowserConfig(
chrome_instance_path="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
disable_security=True
))
llm = ChatGoogle(model="gemini-flash-latest")
agent = Agent(
task="""
1. 打开 http://internal.example.com/admin
2. 如果需要登录,用户名填 admin,密码填 test123
3. 点击左侧菜单的"数据录入"
4. 在表单里填写:名称=测试产品,价格=99.9,分类选择"电子产品"
5. 点提交按钮
6. 确认提交成功
""",
llm=llm,
browser=browser
)
result = await agent.run()
print(result)
if __name__ == "__main__":
asyncio.run(main())
这里有几个值得说的配置:
chrome_instance_path 指定用本地 Chrome 而不是内置 Chromium。好处是能复用你已有的登录状态和 Cookie,不用每次重新登录。
disable_security 关掉一些安全限制。测试环境可以开,生产环境别开。
task 用自然语言写 不用写 XPath 或 CSS 选择器。AI 自己看页面结构,找到对应的元素。你说"点击左侧菜单的数据录入",它就能找到那个菜单项。
踩坑记录
跑了一周,遇到几个问题,记下来供参考。
坑1:页面加载慢,AI 太着急
有些内部系统加载要三四秒,AI 还没等页面渲染完就开始点了,结果点到空白处。解决办法是在 Agent 初始化时加个等待参数:
python
agent = Agent(
task="...",
llm=llm,
browser=browser,
max_actions_per_step=3, # 每步最多执行3个动作,防止操作太快
)
另外可以在 task 里直接写"等页面加载完再操作",AI 会自己判断。
坑2:下拉菜单选不中
有些前端框架的下拉菜单(比如 Ant Design 的 Select),实际的选项列表是动态插入到 body 下面的,不在原来的位置。AI 有时候找不到。
我的做法是把 task 写得更具体:"点击分类下拉框,等弹出选项列表后,在列表中找到并点击'电子产品'"。描述越细,成功率越高。
坑3:Token 消耗比预想大
每一步操作,browser-use 都会把当前页面的可交互元素列表发给 LLM。一个复杂页面可能有上百个按钮、链接、输入框,一次就消耗几千 token。
20个网站跑一轮,Gemini Flash 模型大概花 $0.3。用 GPT-4 的话要贵好几倍。建议:
- 简单任务用 Gemini Flash 或 GPT-4.1-mini
- 复杂页面(登录+验证码+多步操作)用 Claude Sonnet 或 GPT-4.1
- 别用太贵的模型跑日常重复任务
坑4:偶尔会死循环
AI 操作失败后会自动重试,但有时候它不知道自己在重复同一个错误动作。加个 max_steps 限制:
python
agent = Agent(
task="...",
llm=llm,
max_steps=20, # 最多20步,超了就停
)
批量任务:用循环跑多个网站
回到开头的需求,批量抓竞品价格。我写了个循环,每个网站一个 task:
python
import asyncio
import json
from browser_use import Agent, ChatGoogle
from dotenv import load_dotenv
load_dotenv()
SITES = [
{
"url": "https://shop-a.example.com/product/123",
"task": "打开这个页面,找到商品价格,只返回数字价格"
},
{
"url": "https://shop-b.example.com/item/456",
"task": "打开这个页面,找到标价,只返回数字"
},
# ... 更多网站
]
async def scrape_price(site):
llm = ChatGoogle(model="gemini-flash-latest")
agent = Agent(
task=f"访问 {site['url']},{site['task']}",
llm=llm,
max_steps=10
)
result = await agent.run()
return {"url": site["url"], "price": str(result)}
async def main():
results = []
for site in SITES:
try:
r = await scrape_price(site)
results.append(r)
print(f"完成: {r['url']} -> {r['price']}")
except Exception as e:
print(f"失败: {site['url']} -> {e}")
results.append({"url": site["url"], "price": "获取失败"})
await asyncio.sleep(5) # 每个网站之间等5秒
with open("prices.json", "w") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
if __name__ == "__main__":
asyncio.run(main())
这里没用 asyncio.gather 并发跑,是因为多个浏览器窗口同时操作会互相干扰。老老实实串行,稳定性好很多。
跟传统方案的对比
我之前用 Playwright 写过类似的抓取脚本。对比一下:
| Playwright 脚本 | browser-use | |
|---|---|---|
| 开发时间 | 每个网站1-2小时 | 每个网站5-10分钟 |
| 维护成本 | 页面改版就得改代码 | 改 task 描述就行 |
| 处理动态页面 | 要手动等待+判断 | AI 自动处理 |
| 成功率 | 稳定但僵硬 | 灵活但偶尔犯傻 |
| 运行成本 | 0(本地跑) | API 调用费用 |
| 适合场景 | 固定流程、高频任务 | 多变页面、低频任务 |
结论:高频固定任务还是 Playwright 好,写死的脚本又快又稳。browser-use 适合那种"20个不同网站各抓一次"的场景,省的是开发时间。
生产环境部署
如果要定时跑,browser-use 提供了 sandbox 模式,可以在云端运行:
python
from browser_use import Browser, sandbox, ChatBrowserUse
from browser_use.agent.service import Agent
import asyncio
@sandbox(cloud_profile_id='your-profile-id')
async def daily_task(browser: Browser):
agent = Agent(
task="你的任务描述",
browser=browser,
llm=ChatBrowserUse(),
)
await agent.run()
if __name__ == "__main__":
asyncio.run(daily_task())
不过 sandbox 模式需要付费。我自己是用 crontab + 本地 Chrome 跑的,每天早上9点执行一次,结果写到 JSON 文件里,再用另一个脚本推送到飞书群。
browser-use 的 GitHub 仓库:https://github.com/browser-use/browser-use
文档:https://docs.browser-use.com
需要 Python 3.11+,建议用 uv 管理环境。Gemini Flash 是性价比最高的模型选择,新手可以先用这个试。