跳转到主要内容
UUIProxy

大规模采集电商价格而不被封禁的实践方案

如何搭建一条能产出「可比数据」的价格监控管道:站点建模、观测点固定、采集节奏、成本分级,以及大多数团队会漏记的上下文字段。

Daniel Okafor阅读约 6 分钟
跨地区、跨时间跟踪竞品价格点的抽象插画

价格监控项目很少因为爬虫坏了而失败。它们失败,是因为半年后有人问「竞品三月份是不是真的涨价了」,却没人答得上来——因为三月份的数据是从另一个国家、在另一个时点、在一场没人记录的促销期间采集的。

把数据拿到手是容易的那一半。让数据在一个季度之后依然有意义,才是值得设计的部分。

价格是一次测量,不是一个事实

同一个商品页面,会因为请求来自哪里、设备声称是什么、会话看起来是否像回访用户、当前有哪些促销,甚至仅仅因为现在几点,而显示不同的数字。

这意味着抓到的价格是「在某组条件下完成的一次测量」。如果你不记录条件,就无法比较两次测量。大多数管道只存 (sku, price, timestamp),然后在一年半之后发现整条序列无法解读。

最低限度的记录应该更接近这样:

{
  "sku": "B08N5WRWNW",
  "retailer": "example-marketplace",
  "storefront": "DE",
  "observed_at": "2026-04-09T06:00:00Z",
  "exit_country": "DE",
  "exit_city": "Munich",
  "device_class": "desktop",
  "session_state": "logged_out",
  "currency": "EUR",
  "price": 249.99,
  "price_includes_tax": true,
  "shipping_estimate": 0.0,
  "promotion_label": "Spring deal",
  "seller": "Example Retail GmbH",
  "in_stock": true,
  "raw_html_key": "s3://price-raw/2026/04/09/de/B08N5WRWNW.html.gz"
}

这里的每一个字段,都曾经让某个人的分析付出过代价。

建模的单位是站点,不是商品

采集的基本单位不是 SKU,而是「零售商 × 国家」这一对——也就是一个国家站点。同一个平台的德国站和奥地利站是两份不同的数据集:卖家不同、配送承诺不同,有时商品结构也不同。

这直接决定了代理配置:德国站点必须用德国出口采集。用美国机房 IP 去采,要么被重定向到美国站,要么拿到一个默认版本,而两种情况下解析器都会心安理得地记下错误的数字。

用带国家定位的住宅代理按站点固定出口国家;对于国内价格存在地区差异的品类,连城市也一起固定。

固定观测点

写代码之前,先为每个站点写下观测点,并把它当作常量:

  • 请求发起的国家与城市
  • 设备类型——桌面还是移动,两者经常不同
  • 会话状态——未登录是唯一可复现的选项;登录态会累积个性化
  • 币种与区域设置请求头

然后保持全部不变。如果要改观测点,就把它当作一条新序列,而不是旧序列的延续。年中悄悄把出口从法兰克福换成柏林,正是那种会制造出「从未发生过的价格变动」的操作。

节奏比频率更重要

团队常问应该多久采集一次。更有用的问题是:多规律地采集。

带缺口的小时级序列,对趋势分析而言比干净的日级序列更糟。选一个你的基础设施能长期维持的间隔,然后一直维持:

  • 每小时:波动大的品类,如促销期的电子产品、旅游,以及对方有主动调价算法的任何品类。
  • 每六小时:一般零售。
  • 每天:稳定品类,如家具、工业耗材、图书。

每天在相同的挂钟时间采集,使用固定时区,并以 UTC 存储时间戳。零售商会按计划批量更新价格;在一个漂移的时间点采样,会与这些批次产生混叠,制造出看起来像波动的伪影。

用分级出口控制成本

上了规模之后,价格监控会搬运大量字节。一个商品页通常在 150–400 KB,5 万个 SKU 每天采 6 次,大约是每天 45 到 120 GB。

把这些全部走住宅代理,是默认会犯的错误。有效的模式是:

  1. 发现阶段走数据中心。 分类页、sitemap 和搜索结果页的防护通常弱于商品详情页,用数据中心代理低成本枚举。
  2. 详情页走住宅代理,出口固定为站点所在国家。
  3. 只在分类判定为失败时才升级。 验证页返回的是 HTTP 200,必须检查响应体。可用的分类器见 Python 轮换代理完整设置指南
  4. 每网关每天超过约 120 GB 时切换到无限流量。 超过这个量级,按天固定计费的无限流量住宅网关比按量计费更便宜,账单也不再随负载波动。

前两层之间的取舍,在住宅代理与数据中心代理该怎么选里有更详细的讨论。

保留原始载荷

把压缩后的 HTML 或 JSON 响应与解析结果一起存储。它大约会让存储成本变成三倍,而每一次它都值这个钱。

零售商会在不打招呼的情况下改版页面结构。当某个选择器失效时——它一定会失效——你有两个选择:有原始载荷,你用一个下午重新解析归档、把历史找回来;没有原始载荷,唯一的选择是重新采集已经不存在的数据,因为昨天的价格今天花多少钱都买不到。

压缩后的 HTML 大约每页 30–50 KB。每天 30 万个页面约 12 GB,对象存储每月成本不过几美元。拿它和「丢掉一个季度的价格历史」比一比。

防御式解析

几个能避免数据静默损坏的习惯:

不要相信裸数字。 从页面里解析币种,而不是从配置文件里读。平台确实会返回意料之外的币种。

与上一次观测做校验。 一夜之间变动超过 60% 的价格,更可能是解析错误而不是真实变化。标记待审,而不是直接写入。

区分「缺失」与「零」。 缺货商品是没有价格,不是价格为零。混为一谈会毁掉之后所有的均值计算。

记录卖家。 平台上的黄金购物车得主会轮换,价格变化往往意味着换了一个卖家,而不是同一个卖家在调价。

检查截断。 一个平时返回 48 条结果的列表页只返回 12 条,那是部分响应,不是品类在缩水。

尊重目标站

除了道德层面,克制也是成本最低的防封手段:

  • 阅读并遵守你所采集路径的 robots.txt
  • 按主机名限制并发。从每秒 4 个请求起步,观察目标站自身的延迟;如果你加压时延迟上升,说明已经超过了它的舒适区间。
  • 只采集可公开访问的页面。任何登录之后的内容都属于别人的账号。
  • 遇到 429 和 503 立即退避,而不是继续往墙上撞。
  • 如果站点提供了联系渠道,就如实表明你的爬虫身份。有些零售商会直接给你一份数据源,比抓取更快也更便宜。

我们的价格监控电商情报页面介绍了这类业务的产品配置方式。

对变化量告警,而不是对绝对值

最后一环是你拿这条序列做什么。对绝对价格水平告警只会制造噪音——竞品单纯比你便宜,这不算新闻。

要对变化告警:窗口内超过阈值的变动、购物车卖家更替、库存状态切换、促销出现或消失。这些才是会触发决策的事件,其余的应该留在没人需要盯着看的看板里。

而且无论什么告警,都要把观测点带上。「价格下降 14%」是一句不完整的话;「德国站、桌面端、未登录、UTC 06:00 观测,价格下降 14%,并出现新的促销标签」才是定价经理能据此行动的信息。

多久重采一次

不是每个 SKU 都值得同一频率。消费电子、时装发售、快消促销需要一天内多次观测;大家电、配件每天或每周两次就够。全局一个间隔,要么把流量浪费在从不变动的页面上,要么错过竞品真正调价的那一小时。

可落地的拆分:近七天产生过告警、以及你直接对打的 5–10% SKU 作为热集,一到四小时采一次;其余关心的店面作为温集,每天错峰采;长尾冷集每周两到三次。有告警就升级到热集,安静一周再降回去。这一条通常能少 30–40% 流量,同时不丢掉定价团队真正会行动的事件。

重采时必须沿用上次的观测点:同一国家、同一设备类型、同一登录状态。把移动端已登录的德国价混进桌面未登录序列,会看起来像一次从未发生过的 12% 波动。

第一次请求往往会按出口 IP 种一条区域 Cookie。如果随后跟上为另一个国家生成的 URL,Cookie 和路径会对不上,结果是跳转循环或错误语言页。要么每次观测都清空 Cookie、让出口国家决定区域;要么把 Cookie 罐和粘性会话绑在同一次店面访问里,访问结束一起丢掉。记录你实际落到的区域,而不是你打算落到的区域。

分享这篇文章

Daniel Okafor 的头像

关于作者

Daniel Okafor

UUIProxy 数据工程负责人

加入 UUIProxy 之前,Daniel 为一家零售集团在九个市场负责价格情报业务。现在他大部分时间在帮助团队重构那些「成本增速快过数据量增速」的爬虫——办法通常是给出口分级、对响应做分类,而不是简单地买更多住宅流量。

高性价比、长期稳定的全球代理 IP

为你的数据业务打好基础设施底座,随业务一起扩张。

  • 多协议支持
  • 自动 IP 轮换
  • 无带宽限制

无需信用卡,即时开通。