如果你让一个编程智能体构建竞品价格追踪器,大约一分钟就能得到可运行的代码。对于这类任务,这部分已经接近解决。接下来才是很少有人会为之编列预算的部分。追踪器正常运行,表格不断填充,但有些数字却悄悄出错。究竟是哪些数字、错了多少,取决于你为智能体接入了什么底层能力,而我们用两种方式都运行了这项任务。
不是缺失,而是错误。价格其实属于保障计划,评分来自另一家零售商,某一行看起来完整,只因为单元格里必须填点什么。如果你是开发者,这可能是几周后才会发现的 bug,也可能永远发现不了。如果你负责定价、商品运营或市场情报数据源,那你已经基于错误数据做出了决策。如果你正在它之上构建 AI 产品,这就是你的模型会无比自信地说出的数字。
差距不在于智能体的编程能力。对于会保护自己页面的零售商,读取页面意味着要应对该零售商的机器人管理机制,而多写一些 Python 通常解决不了问题。
所以我们对它进行了测量。一项价格追踪器任务、41 个冻结的零售商商品页面、2 个编程智能体、相同提示词和相同模型,分别在接入和不接入托管网页数据层的情况下运行。每个页面、每轮交互和每个错误值都已公开,CLI 报告的所有成本数据也一并发布;仓库中的一条命令可以重新推导下方的核心数字,如果文章内容与这些数字发生偏差,命令就会失败。
接入 Bright Data MCP 的 Cursor CLI 读取了 41 个页面中的 40 个,并在我们人工核验的真实答案中取得了 89% 的数值准确率。同类智能体在没有数据层时读取了 34 个页面,准确率为 72%。在 Best Buy 上,未获辅助的 Claude Code 组丢失了大部分页面,而前者读取了 9 个页面中的全部 9 个,后者只有 4 个。
简而言之
我们让 2 个编程智能体分别在接入和不接入托管网页数据层的情况下执行同一项价格追踪器任务,并人工评判了每一个值。
- 在相同页面和相同模型上,接入数据层时字段准确率为 89%,未接入时为 72%。
- 3 次接入数据层的运行中只有一个页面被拒绝;两次未接入数据层的运行各丢失了 5 个页面。
- 价格字段几乎打平。评分和供货状态拉开了差距:93% 和 94%,对比 83% 和 52%。
- 未获辅助的 Cursor 组编写了 729 行 Python,其 User-Agent 比当前 Chrome 落后了 20 个版本。
我们的运行方式,以及保持不变的条件
我们在所有运行开始前就确定了任务:针对 5 家零售商的一份冻结 SKU 列表,采集商品名称、价格、供货状态和评分,添加一个通过搜索发现新商品的动态数据源,并将结果放入一个小型控制面板。我们只使用公开页面,不涉及任何登录后内容。
SKU 列表在首次请求前就已冻结:涵盖 5 家零售商的 10 款消费电子产品,共 41 个商品页面,并写入 skus.json。每次运行都会读取这个文件,因此所有运行请求的目标完全相同。
全部 4 次运行均为非交互式运行,并保存了每一份交互记录:
| 运行 | 智能体 | 数据层 | 角色 |
|---|---|---|---|
| A | Cursor CLI(cursor-agent) |
Bright Data 托管 MCP | 待测试的配置 |
| B | Claude Code | 无 | 对比基准 |
| Control | 相同版本的 Cursor CLI | 无 | 辅助对照,用于隔离数据层变量 |
| B+ | Claude Code | Bright Data 托管 MCP | 辅助对照,用于隔离智能体变量 |
A 和 B 实际比较的内容
A 与 B 是核心比较:一支采用 Cursor 并接入数据层的团队,对比一支采用编程智能体并自行编写抓取逻辑的团队。保持不变的条件包括:41 个 URL、4 个字段、提示词文本、模型、评分代码、机器和运行时段。提示词从未提到 Bright Data、代理或抓取服务商。
这项比较同时改变了两个变量:智能体和数据层,这正是设置另外两个辅助对照的原因。Control 固定智能体,只移除数据层;B+ 固定智能体,只添加数据层。结合这两个辅助对照,可以看出究竟哪个变量带来了结果,而这个变量并不是智能体。
唯一不同的文件
A 和 Control 之间唯一的变量是一个文件。运行 A 的项目包含一个 .cursor/mcp.json其中指定了一台服务器,并将其指向 Bright Data 的托管 MCP 端点。这个文件不到 10 行 JSON,我们没有安装任何 SDK 或客户端库。Control 的项目包含相同文件,但其中的 mcpServers 对象为空。完整内容如下:
{ "mcpServers": { "brightdata": {
"type": "http",
"url": "https://mcp.brightdata.com/mcp?token=YOUR_BRIGHT_DATA_API_KEY" } } }
Claude Code 通过路径获得了同一文件,并使用 --strict-mcp-config因此机器上的其他任何内容都无法接入。两个智能体使用的配置在字节层面完全一致,唯一差别是各自查找的文件名不同。
模型,以及怎样才算采集成功
模型保持不变。全部 4 次运行都固定使用 Sonnet 5:Cursor CLI 中为 claude-sonnet-5-highClaude Code 中为 claude-sonnet-5这是两家供应商对同一个基础模型的不同命名。Cursor 的别名将推理强度固定为 high,而 Claude Code 的默认值更低;这是唯一不同的模型设置,后文的同等推理强度检查进一步控制了这一变量。
只有当返回内容中同时可以读出商品名称和价格时,页面才算采集成功。返回 HTTP 200 但内容是机器人验证挑战,不算成功;返回 HTTP 200 和商品页面但价格始终未渲染,也不算成功。
配置好该文件后,即使未明确告知,智能体也能使用这些工具。收到任务且提示词中未提及任何供应商时,智能体将零售商 URL 批量合并到一次 scrape_batch 调用中,并在发送该调用前请求批准。

在真实列表上的操作过程。智能体自行选择了 scrape_batch自行整理 URL 集合,而 Cursor 在任何数据离开机器前通过审批关卡将其拦住。
任务成功:二元判定版本
全部 4 次运行都生成了 results.json、new_listings.json、dashboard.html 和 README,因此如果采用“能否端到端运行”的二元判断,所有运行都通过。这是我们提出的所有问题中信息量最低的一个。
| 名称 + 价格 | 全部 4 个字段 | 字段准确率 | |
|---|---|---|---|
| A. Cursor + Bright Data | 40 / 41 | 38 | 89% |
| B. Claude Code,无数据层 | 34 / 41 | 29 | 72% |
| B+. Claude Code + Bright Data | 34 / 41 | 34 | 78% |
| Control. Cursor,无数据层 | 28 / 41 | 28 | 74% |
准确率依据覆盖全部 41 个页面、经人工裁定的真实答案进行评分,后文会进一步说明。
同等推理强度检查
上表有意省略了一组。在完成上述 4 次运行后,我们将 B+ 的推理强度提高到 high 并重新运行,以匹配 Cursor 组已经采用的档位。它读取了 41 个页面中的 35 个,准确率达到 88%高于此前的 34 个页面和 78%。这个单一变化非常重要:如果没有它,上述 4 行结果可能会被解读为推理强度带来的结果,而不是数据层带来的结果。
| 接入 Bright Data | 未接入 | |
|---|---|---|
| Cursor | 89% | 74% |
| Claude Code,同等推理强度 | 88% | 72% |
差距分别为 15 和 16 个百分点,方向一致,来自 2 个不同智能体,并使用相同模型和相同推理强度。这两行将数据层带来的结果与智能体带来的结果区分开来,也正因如此,后续数字才能按这一方式解读。
这张表支持两种解读。第一种是排序:无论按读取的页面数还是正确的数值数,两组接入数据层的运行都高于两组未接入数据层的运行。第二种是,读取页面数低估了差距。A 读取 40 个页面,B 读取 34 个,相差 6 个。但在这些页面内部的数值上,差距达到 17 个百分点,即 89% 对 72%,因为即使页面抓取得很差,它仍然会被计为一个页面。对于这样的页面集合,使用当前模型的编程智能体能够编写合格的抓取代码并采集大部分数据,但无法完成最后一段,而最后一段恰好包含最难处理的零售商和最难提取的字段。
控制面板展示了什么
两次运行都构建了任务要求的控制面板,这是看出差异的最快方式。

运行 A。屏幕上唯一的缺口被报告为 missing_price而不是被强行填充。
Control 使用相同的 41 个 URL 构建了相同视图,差异出现在单元格中,而不是布局中:

Control。相同的 41 个页面、相同模型、无数据层:采集到 28 个,对比 38 个;Amazon 行因配送地区问题而失败,而不是因机器人管理机制失败。
这两条 Amazon 记录并不是被拦截的结果。Amazon 返回了页面,但拒绝为请求所来自的网络提供价格。Control 共有 6 条 Amazon 记录因此失败,这解释了它在 Amazon 上仅成功 3/10,而运行 A 成功 9/10 的大部分差距。这些失败源于地理位置,而不是机器人管理机制,尽管它们看起来很像被拦截。
单独统计被拦截的请求
真正的拦截值得单独统计,因为这是人们最常预期的失败,而且它与字段缺失的表现不同。每次运行都为每个页面写入了状态,这些状态可以清楚地区分两类情况:页面成功返回但缺少某个字段,以及请求从未产生可用页面。只有第二种才算拦截:
| 运行 | 从未产生页面 | 运行记录的内容 |
|---|---|---|
| A. Cursor + Bright Data | 0 / 41 | |
| B+. Claude Code + Bright Data | 0 / 41 | |
| B+. Claude Code,同等推理强度 | 1 / 41 | 重试后仍有一个页面为空 |
| Control. Cursor,无数据层 | 5 / 41 | blocked_by_bot_protection (are you a human) |
| B. Claude Code,无数据层 | 5 / 41 | 2 次 HTTP/2 导航失败,3 次始终未完成 |
两次未接入数据层的运行都各丢失了 5 个页面,并且均未恢复。Control 丢失的 5 个页面都是 Newegg 明确返回的机器人验证挑战。B 在 Best Buy 丢失的 5 个页面表现为 HTTP/2 导航失败和请求始终未完成,这通常是客户端看到连接被拒绝时的样子,尽管 B 自己记录的状态没有明确指出验证挑战。它们发生在不同零售商上,因此并不是同一家格外难处理的零售商重复出现。3 次接入数据层的运行总共只有一个页面被拒绝。除此之外,所有缺口都是页面已返回但缺少字段。
完整性评分看不到的失败模式
全部 4 次受测运行都没有回填任何内容:我们将每次运行输出中的每个值与其自身源代码中的硬编码字面量进行匹配,4 次结果全部为零。
填满每一行的那次运行
但这并不一定会发生。该任务较早的一次运行产生了相反结果。一次未接入数据层、使用旧版模型的 Claude Code 运行报告了完美的41/41,且每个字段均已填充比这里任何 Bright Data 组都更好。但这并不是采集结果。那次运行无法填充部分记录,于是编写了一个补丁脚本。脚本自己的注释说明了规则:
# Product-level ratings (verified from live web searches + tracker captures).
# Applied to ALL retailers for the same SKU where rating is still None.
PRODUCT_RATINGS = {"S01": "4.4", "S02": "4.6", "S05": "4.8", ...}
41 行中只有 2 行没有携带硬编码值。全部 9 条 Best Buy 记录的名称和价格都来自一个搜索表,而它自己的追踪器从未成功抓取过这家零售商。它的完整性得分最高,但在价格追踪器真正重要的指标上得分最低。
应将其理解为某个模型上的某个智能体案例,而不是智能体会编造数据的证据。对同一组配置进行一次全新重跑后,它没有填充任何内容,而是如实报告 null。实际结论仍然成立:完整性评分无法区分这两者。两者都会产生 41/41。只有一项检查能区分真正读取页面的追踪器与从其他地方找到数字的追踪器:每个值来自哪里。这项检查对最难处理的零售商尤为重要,因为智能体最可能被迫填补的正是这些记录。
接入数据层后,来自 2 家不同供应商的智能体都拒绝猜测:

共 41 行,每个缺口都附带原因。“全部带有说明性状态字符串,从不猜测”是智能体未经提示自行给出的表述。
在同一任务和同一列表上,Claude Code 也以同样方式结束运行:

来自另一家供应商的智能体、相同指令、相同的 3 个缺口:明确指出,而不是强行填充。
应评估数据来源,而不是完整性。它只需要几行代码,而且如果只能保留一项检查,我们会保留这一项。
与人工核验真实答案对比的字段准确率
来源信息能说明一个值来自哪里,但不能说明这个值是否正确。为此,我们读取了页面。
我们打开了全部 41 个页面已提交的载荷,并逐一目视记录真实值。如果页面在明确的售价标记下展示价格,该数字就是真实值。保障计划、对比轮播、赞助商品行、分期付款金额和带删除线的“原价”都不算。4 个页面返回的载荷为空或不完整,且没有可解析的购买框,因此这些页面被记录为 null 并附上原因,而不是猜测。
由此得到 100 个经人工裁定的值。对价格、评分和供货状态进行评分后,每次运行产生 97 项比较。另外 3 个字段是所有运行都完全没有尝试的字段。
| 运行 | 正确 | 准确率 | 价格 | 评分 | 供货状态 |
|---|---|---|---|---|---|
| A. Cursor + Bright Data | 86 / 97 | 89% | 80% | 93% | 94% |
| B+. Claude Code + Bright Data,同等推理强度 | 85 / 97 | 88% | 86% | 93% | 85% |
| B+. Claude Code + Bright Data | 76 / 97 | 78% | 74% | 90% | 73% |
| Control. Cursor,无数据层 | 72 / 97 | 74% | 66% | 93% | 67% |
| B. Claude Code,无数据层 | 70 / 97 | 72% | 83% | 83% | 52% |
如何解读价格列
两组接入数据层的运行都高于两组未接入数据层的运行。各字段列显示了领先来自哪里,而价格列在得出任何结论前需要谨慎解读:A 在全部 35 个可评分页面上都尝试提取价格,没有留下空白。B 尝试了 31 个,并放弃了 4 个。在实际尝试的页面上,B 得分为 94%,但如果一次运行跳过了无法读取的页面,它接受评分的集合就更容易。对于展示价格的页面,价格追踪器中的空白也应算作错误。按这个口径,B 在该列仍以 29 个值对 28 个值领先,但它为了这一个值的领先放弃了 4 个页面。价格字段几乎打平,任何一组都不应宣称胜出。
另外两个字段拉开了差距。A 的评分准确率为 93%,供货状态准确率为 94%;B 分别只有 83% 和 52%。在这些零售商页面上,评分和供货状态位于页面更靠下的位置,并依赖客户端渲染,因此部分抓取会最先丢失这些字段。数据层并不是读得更好,而是拿到了更多可供读取的页面内容。
对答案键的修正
价格列暴露了所有使用固定答案键评测实时页面的基准测试都会遇到的失败模式。我们的真实答案根据运行前一天捕获的载荷裁定,而零售价格会变化。有 5 行中,所有返回价格的运行都返回了新价格,但这些价格全部被标记为错误,因此排行榜衡量的是日期差异,而不是智能体表现。所有拿到价格的组彼此一致,只与我们的答案不同,这促使我们重新检查运行时间窗口内的页面快照:
| 记录 | 答案键 | 页面显示内容 |
|---|---|---|
| S02 Walmart | $199.99,0 次命中 | $225.00,9 次命中 |
| S09 Amazon | $138.68,0 次命中 | $129.99,14 次命中 |
| S02 Best Buy | $242.00,不存在 | $238.99,存在 |
| S06 Target | $18.99,不存在 | $19.49,存在 |
| S09 Target | $136.22,不存在 | $143.30,存在 |
全部 5 项都已在 ground_truth_hand.json 中修正,并附有证据。修正提高了所有组的得分,而不是只提高其中一组,这是真实修复而非偏袒自家结果的一个迹象。如果你使用已存储的答案键评分,请为两者都添加时间戳,并重新检查所有方法都与你的答案不一致的记录。
投入:每个编程智能体实际花费了什么
两个 CLI 报告的指标不同,因此表中保留空缺,而不是进行估算。Cursor 报告工具调用次数,Claude Code 报告交互轮数和成本。这里没有任何数字是推断出来的。
| A. Cursor + BD | Control. Cursor | B. Claude Code | B+. Claude Code + BD | |
|---|---|---|---|---|
| 实际耗时 | 3,281 秒 | 3,183 秒 | 1,054 秒 | 1,650 秒 |
| 不同工具调用数 | 196 | 178 | 不适用 | 不适用 |
| 智能体交互轮数 | 不适用 | 不适用 | 151 | 133 |
| 输出 token | 未报告 | 未报告 | 68,106 | 72,422 |
| 缓存读取 token | 未报告 | 未报告 | 12.3M | 13.3M |
| 模型成本 | 未报告 | 未报告 | $6.09 | $6.21 |
| 人工干预 | 0 | 0 | 0 | 0 |
成本、交互轮数和实际耗时
这张表可以得出 3 点结论。
在这项工作负载中,数据层对模型账单的额外影响接近于零。B+ 的成本为 $6.21,B 为 $6.09;在约 $6 的运行中仅相差 12 美分,却换来了 6 个百分点的字段准确率提升。将抓取工作交给服务会消耗更多 token 的直觉在这里并不成立,因为 token 消耗主要由读取的内容决定,而不是由获取内容的方式决定。
B+ 还用了更少的交互轮数完成任务133 轮对 151 轮。在这些运行中,抓取正常的智能体把交互轮数用于采集,而没有数据层的智能体则把轮数花在诊断、重试和编写变通方案上。在按量计费的套餐中,交互轮数通常是最先耗尽的资源,而数据层节省了 12%。
Cursor 两组的实际耗时几乎相同。运行 A 用时 3,281 秒,Control 用时 3,183 秒,仅多 3%,却多读取了 12 个页面,准确率高出 15 个百分点。Claude Code 两组则相反:B+ 用时 1,650 秒,B 用时 1,054 秒,因此数据层并未让该智能体节省时间。B 更快的部分原因是少读取了 6 个页面;它节省的时间,正是它没有花在那些始终无法读取的零售商上的时间。
Cursor 的 CLI 不会在 stream-json 中报告金额,因此 Cursor 两行没有成本数据。我们不进行估算。
一次刷新需要多少成本
Bright Data 的网络解锁器按量付费价格为每 1,000 次请求 $1.5,每月免费额度为 5,000 次请求。按这个费率,刷新一次冻结列表需要 41 次请求,约 6 美分;每天刷新一次、持续一个月约为 1,230 次请求,仅占免费额度的四分之一。
我们不公布这次基准测试的账户总费用。运行期间,该账户还用于其他无关工作,因此对应日期的用量视图无法将它们分开,而无法准确归因的数字不值得引用。
没人会放进演示文稿的编程智能体成本
人们常引用工具定义的上下文成本:我们使用的配置包含 5 个工具,成本为 1,007 token通过 tiktoken 对服务器自身的 tools/list 响应进行统计;如果你希望减少成本,服务器也提供更小的配置。在这类工作负载中,这并不是最重要的成本。我们对实际返回的内容进行了 token 统计,对 41 个已提交载荷使用了同一个编码器。
| Token | |
|---|---|
| 工具定义,每个会话一次 | 1,007 |
| 41 个页面返回的 Markdown | 636,311 |
| 这些页面产生的答案 | 5,080 |
智能体读取了 636,311 个 token,最终生成 5,080 个。它付费读取的内容中有 99% 并不是答案页面载荷的 token 数是与之对比的工具定义的 632 倍。
负载分布也极不均匀。按零售商计算,每页 token 中位数如下:
| 零售商 | 每页 token 中位数 |
|---|---|
| Amazon | 63,920 |
| Newegg | 5,101 |
| Walmart | 2,060 |
| Best Buy | 1,789 |
| Target | 1,244 |
单个 Amazon 商品页面返回了 103,019 个 token。一个页面就占用了半个上下文窗口。Amazon 页面成本是 Target 页面的 51 倍,因此你的列表中包含哪些零售商,比零售商数量更能影响模型账单。
这也解释了上表中的一个数字。两次 Claude Code 运行都消耗了超过 12M 个缓存读取 token。这些成本来自页面,而不是模型。
达到实际业务规模时需要多少成本
41 个页面的运行只是演示。买家真正会问的是,每天处理 100,000 个页面需要多少成本。按照我们测得的 token 数和 Bright Data 公布的费率,以每月 3M 次请求计算:
| 每月 | |
|---|---|
| 抓取,按量付费,每 1,000 次 $1.5 | $4,500 |
| 抓取,Scale 套餐,$499 加每 1,000 次 $1.3 | $3,901 |
| 以 Markdown 读取,中位页面 | $22,833 |
| 以 Markdown 读取,Amazon 占比较高的商品目录 | $575,280 |
| 以结构化记录读取 | $1,115 |
我们采用的模型输入费率为每百万 token $3.00,结构化记录一行则根据智能体生成的相同 41 行结果实测得出。如果改变这些假设,数字也会变化,因此 scripts/cost_model.py 在顶部提供了可调整的输入项。
以中档输入价格将 Markdown 输入模型时,读取数据的成本是抓取成本的数倍:按我们的页面中位数计算约为 6 倍,在 Amazon 权重较高的列表上则高得多。改用类型化记录后,读取成本会降到抓取成本之下。在 Markdown 路径中,按每千次请求的价格比较不同爬虫服务商,衡量的其实是账单中更小的那一部分。
发现商品和读取商品是两项不同的工作
任务还有第二项交付物:由搜索驱动的新商品动态数据源,也就是销售同款商品的其他零售商。每次运行都生成了一份,而第二项交付物与第一项的结果存在明显差异。
| 运行 | 找到的新零售商 URL |
|---|---|
| A. Cursor + Bright Data | 46 |
| Control. Cursor,无数据层 | 30 |
| B. Claude Code,无数据层 | 24 |
| B+. Claude Code + Bright Data | 22 |
所有组都生成了可用的数据源,包括两组没有数据层的运行。在我们测试的零售商中,搜索结果页面不像商品页面那样设有严格限制,因此发现商品几乎不需要额外帮助;在决定投入预算前,你应该了解这一点。

智能体根据 3 款商品演示构建的发现面板。受测运行的数据源结果见上表。
在这些运行中,数据层在下一步体现了价值,也就是打开已找到的页面。找到候选商品和读取其价格是两个不同问题,成本也不同;在这些零售商中,只有第二个问题真正困难。
让输出格式匹配所需字段
成功获取页面和从页面中提取所有字段是两个不同问题,而后者取决于格式选择。
Markdown 是一种阅读格式:它为智能体提供整洁的文本,token 数仅为原始 HTML 的一小部分。在 41 个页面中,它成功交付全部 4 个字段的结果分别为:Amazon 10/10、Walmart 10/10、Best Buy 6/9。在 Target 和 Newegg 上,它交付了名称、价格和供货状态,但没有评分;原因并不是 Markdown 转换。
这些零售商很少以文本形式发布评分。Newegg 使用图片图标绘制星级,因此其 5 个页面中有 0 个以任何文本形式提供数字评分。Target 则是 7 个页面中有 2 个。对于从未以文本形式进入渲染页面的数字,Markdown 无法提取。本次基准测试中的一个智能体未经提示自行得出了这个结论,并在总结中写道:“Newegg 只会将星级评分渲染为图片图标,而不是文本,因此无法从页面中提取。”
何时使用类型化记录
这正是结构化记录适用的场景。它们能在 7/7 个 Target 页面和 5/5 个 Newegg 页面中提供星级评分,因为即使该值从未以文本形式进入渲染页面,它仍然存在于零售商的数据中。两条路径使用相同连接。
应根据所需字段选择输出格式,而不是依赖习惯。如果你希望智能体以较低成本读取页面,请使用 Markdown;如果某个特定字段必须尽可能可靠地返回,请使用类型化记录。
输出格式也是你在规模化运行时能够控制的最大成本差异。按前文每月 3M 次请求的规模,读取类型化记录每月成本为 $1,115,而 Markdown 为 $22,833因为记录只携带字段,不会附带字段周围的整张页面。因此,对这些零售商而言,类型化记录既填补了 Markdown 无法获取的字段,读取成本也只有后者的二十分之一。
明天还能正常运行吗?
耐久性仅在一个 24 小时时间窗口内进行测量。我们使用 ./rerun.sh在不修改任何内容的情况下,针对同一冻结列表重新运行了两个 Cursor 追踪器。一个时间窗口只能算一个检查点,我们也仅按一次检查点进行报告。
| 零售商 | A,Bright Data | Control,无数据层 |
|---|---|---|
| Amazon | 9 → 9 | 3 → 3 |
| Walmart | 10 → 10 | 10 → 10 |
| Target | 7 → 7 | 7 → 7 |
| Newegg | 5 → 5 | |
| Best Buy | 9 → 4 | 8 → 0 |
| 总计 | 40 → 35 | 28 → 20 |
除 Best Buy 外,其他结果都保持稳定。其余 4 家零售商返回的页面数量与前一天相同,而代码完全没有改动。唯一最难的目标发生了变化,而且两组都受到了影响。
在最难的零售商上保留了多少
两组的区别在于保留了多少结果。托管路径保留了 9 个 Best Buy 页面中的 4 个;手写爬虫一个也没有保留,并失去了从一开始就最难采集的零售商。总体保留率为 88% 对 71%。
部分变化甚至根本不是采集问题。我们手动打开了一个被丢弃的页面,即 Best Buy 上的 Sony WH-1000XM5。零售商给出了明确答案:“此商品已不再提供全新状态。”没有价格,因为它已经不存在可售价格。追踪器为该行返回 null 才是正确做法,而从其他地方填入价格,正是前文描述的失败模式。一天后重新运行价格追踪器时,部分变化来自市场,而不是代码;在任何人断定爬虫工具已经失效前,都值得先区分这两者。
应将它视为早期指标,而不是定论。24 小时窗口只能捕捉变化最快的防护机制,无法观察变化更慢的机制,因此保持稳定的 4 家零售商可能只是尚未做出任何调整。rerun.sh 和冻结列表都在仓库中,你可以按自己的时间安排,针对自己的目标执行同样的检查。
为什么接下来会变得更难
上述测量描述的是某个下午的情况,而背后的条件正从 4 个方面变化,且都指向同一方向。
Cloudflare 于 2026 年 7 月报告称目前超过一半的互联网流量来自非人类来源;截至 2026 年 6 月,52% 的爬虫请求用于 AI 训练,而 2025 年春季这一比例为 22%。从 2026 年 9 月 15 日起新接入 Cloudflare 的域名会获得一项默认设置:在展示广告的页面上拦截被归类为 Training 或智能体的机器人,但仍允许 Search。
检测正在深入页面以下的层面。Akamai 于 2026 年 8 月发布的研究发现,63.2% 的智能体浏览器请求不包含任何鼠标事件,只有 1.0% 携带了足够的移动数据,能被其传统行为模型评分。该研究中的智能体是商业浏览智能体,而不是爬虫工具。
另一些工作则朝相反方向发展:不是隐藏身份,而是证明身份。Web Bot Auth 由 Cloudflare 和 Google 的作者起草,截至 2026 年 8 月 18 日处于 draft-meunier-webbotauth-httpsig-protocol-02 阶段,它允许智能体使用公开密钥对请求签名。它仍是一份个人 Internet-Draft,并非已采纳的标准,而且 Cloudflare 目前只验证 Ed25519。
第四点来自法院记录中的一个细节,而不是可用于推导法律结论的裁决。在 2026 年 8 月 4 日裁决的 Amazon.com Services, LLC v. Perplexity AI, Inc. 一案中,争议核心是一个智能体没有发送用于标识其 AI 智能体身份的 user agent string。你的流量如何表明自身身份,正在成为一个会产生实际后果的问题。
这 4 点都影响同一个变量。它们都不会改变编程智能体能够编写什么代码,却都会影响其请求受到怎样的处理。
后续步骤
开发者几周后才发现的 bug、已经基于错误数据做出的定价决策、AI 产品无比自信地重复的数字:这三者都可能源于一个无法判断来源的值。以下步骤有助于将这种值与真实值区分开来。
在进行任何测量前冻结目标列表,这样数字变化代表现实世界发生了变化,而不是样本发生了变化。
评估数据来源,而不是完整性。为每个字段记录该值是否来自你正在追踪的页面。仅这一列,就能区分看似完美的运行与如实保留缺口的运行,而我们收集的其他指标都无法做到这一点。
抓取是否成功应根据字段能否提取来判断,绝不能只看状态码;无论空载荷由哪一层产生,都应在你自己的代码中将其视为失败。接入托管层时,要弄清楚你是在调用托管端点,还是自行运行服务器,因为两条路径可能经过不同网络,而且账户的 IP 设置可能只适用于其中一条。
然后测量你自己的目标。我们的目标是某个下午测试的 5 家美国零售商,请求来自印度连接并通过美国住宅网络出口;各零售商的数据表明,汇总数字对任何单一网站的解释力都非常有限。
仓库中包含什么
任务规范、完整提示词、冻结 SKU 列表、全部 4 份交互记录、逐页原始结果和评分代码均已发布在配套仓库中,因此你可以针对自己的列表运行相同测试。
其中有一个文件值得特别说明。verify.py 会从已提交数据中重新推导 40 个已发布数字,并检查草稿是否仍与之吻合;如果其中任何一个数字发生偏差,它会以非零状态退出。无需网络,也无需凭据。直接运行时,它会从数据中打印这些数字;如果提供文章文件,它会对两者进行检查:

一条命令,无需凭据。它会解析表格并比较特定单元格,因此即使同一个数字在其他位置正确出现,错误位置的数字仍会导致检查失败。
上述数字也以数据形式随项目发布。claims.json 列出了其中 39 个数字,以及各自的来源文件和用于计算它们的脚本:
{ "id": "cursor_bd.field_accuracy", "value": 89, "unit": "percent",
"derived_from": "runs_isolated/cursor_bd/results.json",
"computed_by": "scripts/score_accuracy_iso.py" }
所以不要只相信我们的话。让你自己的编程智能体读取仓库,并要求它根据数据核验本页面。对于一项基准测试,这是合理的检验方式,而且正是该基准测试本身所测量的任务。
Bright Data 的免费额度每月包含 5,000 次网络解锁器请求,而刷新一次 41 页列表只会消耗其中 41 次。将 Bright Data 托管 MCP 服务器指向你自己的目标,看看这些结论是否也适用于你。
常见问题
AI 编程智能体是否需要代理或解锁服务才能进行网页抓取?
对于高难度目标,需要,而且测得的差距很大:接入数据层后,同类智能体读取了 41 个页面中的 40 个字段准确率为 89%;未接入时读取 34 个页面,准确率为 72%。它在做到这一点的同时,没有编写任何抓取代码。不过,难度分布并不均匀。由当前模型驱动自有浏览器时,它无需辅助也能处理列表中较容易的零售商:Walmart 读取 10/10,Target 读取 7/7。在我们的运行中,它无法完成最后一段,而失败和大部分重试轮数也集中在这一段。因此,不要只问你是否需要解锁层,而应问你的哪些目标需要它,以及你的工程时间值多少钱。
如何判断抓取的数据是否准确?
检查每个值来自哪里,而不是检查该行是否填满,然后手动对照页面抽查样本。在这次基准测试中,4 次运行都没有回填任何内容。较早的一次 Claude Code 运行未接入数据层并使用旧模型,却报告了完美的 41/41,其中 29 个评分等于它自行编写的补丁脚本里硬编码的产品级数值。这两种情况都可能出现,而完整性评分无法区分它们,这项检查却只需要几行代码。
使用网页爬虫工具 API 时,可以期待多高的成功率?
应将任何被引用的成功率视为一次测量结果,而不是保证。本次基准测试中的 40/41 只是一次观测:共 41 个页面、某一天、模型固定为 claude-sonnet-5并来自一个网络位置。同一组在 24 小时后重新运行时,没有返回完全相同的数字;这对于实时页面很正常,也应该在预期之中。你的实际结果取决于自己的目标列表,因此应针对该列表进行测量。
使用 Bright Data 进行网页抓取需要多少成本?
网络解锁器按量付费价格为每 1,000 次请求 $1.5,免费额度每月包含 5,000 次请求。刷新一次 41 页列表需要 41 次请求,约 6 美分,因此每天刷新该列表也远低于免费额度。我们不提供整个基准测试的总费用:它与其他无关工作共用同一个账户,因此该数字无法准确归因。真实答案背后的抓取浏览器运行属于另一项产品,并采用不同的计费单位。