Firecrawl /monitor 实战:网页一变,Agent 就动
你的 AI Agent 怎么知道某个网页更新了?
最笨的办法是轮询:每隔几分钟抓一遍页面,拿新内容和旧内容做 diff。这事不难,但烦——得自己写 cron、存快照、处理 diff、搭 webhook、过滤噪音(广告、时间戳、session token 之类的变化全得跳过)。搞一个页面还行,监控几十个页面就变成了运维噩梦。
Firecrawl 5月底上线了 /monitor 端点,把这套流程打包成了一个 API 调用。我花了两天把它接进自己的 Agent 工作流里,记录一下踩坑过程。
它干了什么
一句话:你告诉 Firecrawl "我关心这个页面的哪些变化",它按你定的频率去抓,发现变化就通过 webhook 或邮件通知你。没变化就什么都不发。
它不是把整页内容推给你,而是只推 diff——新增了什么、删了什么、改了什么。官方说法是比全量抓取省 90% 的 token,实测数据在后面。
安装和准备
先装 CLI 和 SDK:
# 装 CLI
npm install -g firecrawl-cli
# 登录拿 API key(会打开浏览器)
firecrawl login --browser
# 验证
firecrawl --status
Python SDK:
pip install firecrawl
拿到 API key 后设环境变量:
export FIRECRAWL_API_KEY="fc-你的key"
第一个 monitor:盯竞品定价页
我先拿一个简单场景试手——监控竞品的定价页面,价格一变就通知我。
from firecrawl import Firecrawl
fc = Firecrawl(api_key="fc-你的key")
monitor = fc.create_monitor(
name="竞品定价监控",
schedule={"text": "every 1 hour", "timezone": "Asia/Shanghai"},
goal="只关注价格数字的变化,忽略页面上其他内容(导航栏、页脚、广告位)的改动",
targets=[
{
"type": "scrape",
"urls": ["https://competitor.example.com/pricing"],
}
],
webhook={
"url": "https://你的服务器/webhooks/pricing-change",
"events": ["monitor.page"],
},
)
print(f"Monitor ID: {monitor.id}")
print(f"预估月消耗: {monitor.get('estimatedCreditsPerMonth')} credits")
goal 字段是用自然语言描述你关心什么。Firecrawl 内部有一个 judge 模型,会根据这段描述过滤掉不相关的变化。比如页脚改了个 copyright 年份,不会触发通知。
返回值里的 estimatedCreditsPerMonth 也值得看一眼,创建之前就能知道大概花多少。
进阶:监控整个文档站
单页面用 type: "scrape",如果要监控一整个站(比如某个 SDK 的文档),用 type: "crawl":
docs_monitor = fc.create_monitor(
name="SDK文档变更监控",
schedule={"cron": "0 9 * * *", "timezone": "Asia/Shanghai"},
goal="API 端点、请求参数、返回格式有变化就通知,文档排版和拼写修正忽略",
targets=[
{
"type": "crawl",
"url": "https://docs.某sdk.com/api",
"crawlOptions": {
"limit": 50,
"maxDiscoveryDepth": 3,
},
}
],
notification={
"email": {
"enabled": True,
"recipients": ["dev@your-team.com"],
"includeDiffs": True,
}
},
)
这里几个参数说一下:
limit: 50限制最多爬 50 个页面,防止文档站太大把 credits 吃光maxDiscoveryDepth: 3最多跟 3 层链接schedule.cron支持标准 cron 表达式,这里设的是每天早上 9 点检查一次includeDiffs: True邮件里直接带 diff 内容,不用再点进去看
接 webhook 的服务端代码
monitor 触发后会往你的 webhook URL 发 POST 请求。我用 FastAPI 写了个简单的接收端:
from fastapi import FastAPI, Request
import json
app = FastAPI()
@app.post("/webhooks/pricing-change")
async def handle_change(request: Request):
payload = await request.json()
event_type = payload.get("type")
if event_type != "monitor.page":
return {"ok": True}
page_url = payload["data"]["url"]
status = payload["data"]["status"] # same/new/changed/removed/error
if status == "changed":
diff = payload["data"].get("diff", {})
added = diff.get("added", [])
removed = diff.get("removed", [])
# 这里可以推消息到飞书/Slack/企业微信
message = f"页面变化: {page_url}\n新增: {len(added)} 处\n删除: {len(removed)} 处"
send_to_feishu(message) # 你自己的推送函数
return {"ok": True}
每次检查,每个页面会返回一个 status:
| 状态 | 含义 |
|---|---|
| same | 没变 |
| new | 新发现的页面(crawl 模式下) |
| changed | 内容有变化 |
| removed | 页面没了(404 或被删了) |
| error | 抓取失败 |
实际跑起来的数据
我跑了一周,监控 12 个页面,每小时检查一次:
- 总检查次数:2016 次(12 页面 × 168 小时)
- 触发通知:23 次(大部分是文档更新和价格调整)
- 误报(不相关变化被过滤掉):0 次
- credits 消耗:约 4200/周
对比之前自己写的 cron + diff 方案:
- 之前每次全量抓取都要过一遍 LLM 判断变化,每次消耗约 2000 token
- 现在只有真正变化的时候才推 diff,LLM 只需处理 diff 部分,平均 200 token
- token 消耗降了大约 85%
踩坑记录
1. schedule 的 text 格式不是随便写的
"every 30 minutes" 能识别,"每半小时一次" 不行。得用英文,而且格式有限。不确定的话直接用 cron 字段写标准 cron 表达式更稳。
2. goal 写太模糊会收到一堆噪音
第一版我写的 goal 是 "notify me when the page changes",结果页面上广告位的轮换、cookie banner 的 A/B 测试都会触发通知。后来改成具体的 "只关注价格数字的变化,忽略页面上其他内容的改动",噪音就消失了。
3. webhook 要处理重试
Firecrawl 的 webhook 如果收到非 2xx 响应会重试。你的 handler 得做好幂等处理,不然同一个变化可能推送多次。建议用 payload["data"]["checkId"] 做去重。
4. crawl 模式下 limit 不能省
不设 limit 的话,crawl 会尝试爬整个站。一个文档站上千个页面,每次检查的 credits 消耗非常可怕。一定要设一个合理的 limit。
跟 AI Agent 配合的思路
对我来说,/monitor 的价值在于给 Agent 加了一个事件驱动的触发器。
拿 RAG 知识库来说,Agent 依赖的文档源一旦更新,/monitor 推过来的 diff 可以只更新变化部分,不用全量重建索引。我现在用它盯着两个 SDK 的文档站,一周下来只触发了 3 次增量更新,之前每天全量重建一次。
竞品分析也是个实际场景。盯着竞品的定价页和招聘页,价格调整或者新开岗位,Agent 收到 diff 直接拉出来写分析。比每天手动去刷网页靠谱得多。
CLI 快速操作
不想写代码也能用 CLI 管理 monitor:
# 创建
firecrawl monitor create \
--name "HN头条" \
--schedule "every 30 minutes" \
--goal "top 10 stories about AI" \
--url "https://news.ycombinator.com"
# 查看列表
firecrawl monitor list
# 查看某个 monitor 的检查历史
firecrawl monitor checks <monitor-id>
# 暂停
firecrawl monitor pause <monitor-id>
# 删除
firecrawl monitor delete <monitor-id>
值不值得用
看场景。监控一两个页面、变化频率低的情况下,自己写个 cron + requests + diff 就够了。但页面超过 10 个之后,光是过滤噪音的代码就写不完。广告轮换、导航栏改版、cookie banner 的 A/B 测试、时间戳变化,全得排除掉。我试过,代码量比想象中大得多。
最后保留 /monitor 就是因为 goal 字段的智能过滤。写一句 "只关注价格变化",这些噪音就不用我自己处理了。
Firecrawl /monitor 文档:https://docs.firecrawl.dev/features/monitoring
更多推荐



所有评论(0)