反向海淘独立站的数据层架构:1688 / 淘宝 / 京东三平台接口怎么编排与降级
做反向海淘独立站,前端、支付、物流其实都有成熟方案,真正容易把项目拖死的是数据层——商品从哪来、怎么归一化、接口挂了怎么办。这篇把我现在跑的这套三平台数据层架构完整拆开,包括分层设计、降级链、缓存策略和成本控制,给正在搭系统的朋友一个可以直接抄的骨架。
一、为什么数据层是最先崩的地方
反向海淘的商品来源天然是分散的:1688 拿货、淘宝找同款、京东做价格对标。三个平台三套字段、三套反爬、三套失败率。很多团队一开始的做法是"哪里需要就在哪里写一次请求",结果三个月后代码里躺着几十处硬编码 URL,某个接口一抖动,全站跟着白屏。
问题的根子是把"取数"和"用数"耦合在了一起。正确的做法是先分层。
二、三层结构:采集层 / 归一化层 / 业务层
采集层只做一件事:给定平台和参数,返回原始 JSON。所有请求都走同一个网关形态 https://api-gw.onebound.cn/{平台}/{接口名},公共参数固定为 key、secret、api_name、cache、result_type、lang。用一个适配器字典管理平台差异:
GATEWAY = "https://api-gw.onebound.cn/{platform}/{api}"
PLATFORM_API = {
"1688": "item_get", # 详情主链路
"taobao": "item_get",
"jd": "item_get_pro",
}
def call(platform, api, **params):
url = GATEWAY.format(platform=platform, api=api)
base = {"key": KEY, "secret": SECRET, "result_type": "json"}
return requests.get(url, params={**base, **params}, timeout=12).json()归一化层负责把三个平台返回的商品对象,映射成同一种内部模型(SPU + SKU 列表 + 价格区间 + 主图数组)。这层写死了字段映射表,业务层就永远只面对一种数据结构。淘宝的 num_iid、1688 的 num_iid、京东的 sku_id 在归一化层统一成 platform_goods_id,后面换接口、加平台都不用动业务代码。
业务层才是定价(汇率 × 加价率 × 物流系数)、库存同步、上下架这些真正属于你产品的东西。
归一化层的映射表建议显式写死,不要靠猜测字段名:
| 内部字段 | 1688 | 淘宝 | 京东 |
|---|---|---|---|
| platform_goods_id | num_iid | num_iid | sku_id |
| title | title | title | title |
| price | price / price_range | price | price |
| images | pic_url + item_imgs | pic_url + item_imgs | pic_url |
| skus | skus.sku[] | skus.sku[] | skus.sku[] |
| seller | seller_info | seller_info | shop_info |
这张表是三个月里改动最频繁的文件,但它的价值在于:任何平台的接口变动,都只影响这一张表,业务层完全无感。顺带说一句,京东没有独立的"阶梯价"概念,price 单值即可,而 1688 必须处理区间价——这个差异放在归一化层消化,比散落在报价逻辑里安全得多。
三、降级链:按实测成功率排兵布阵
架构里最有价值的是降级链。我把后台统计的成功率数据(样本量十万次级)做成了一张"可靠性分层表",接口按可靠性分三档用:
| 平台 | 接口 | 成功率 | 定位 |
|---|---|---|---|
| 1688 | item_get / item_get_app / item_get_pro / custom | 99% | 主链路,几乎不需兜底 |
| 1688 | cat_get | 97% | 类目树,离线同步 |
| 1688 | item_fee | 96% | 运费预估 |
| 1688 | item_search | 53% | ⚠️ 不做实时主链路 |
| 淘宝 | item_link | 100% | 链接转换,最稳 |
| 淘宝 | item_search_shop_pro | 96% | 店铺采集 |
| 淘宝 | item_password | 95% | 淘口令解析 |
| 淘宝 | item_search_img | 92% | 图搜选品 |
| 淘宝 | item_search | 85% | 搜索,可用 |
| 淘宝 | item_get / item_get_pro | 40% | ⚠️ 必须做降级 |
| 京东 | cat_get | 100% | 静态数据 |
| 京东 | item_review | 99% | 评论 |
| 京东 | item_get_desc | 98% | 描述 |
| 京东 | item_get_pro / item_get | 78% | 可重试使用 |
| 京东 | item_history_price | 75% | 比价够用 |
| 京东 | item_search | 28% | ⚠️ 避开主链路 |
看这张表的结论很明确:1688 的详情链路可以放心当主链路用,淘宝和京东的详情接口必须配降级。淘宝 item_get 只有 40%,意味着每一次"用户粘贴链接"的请求都有六成概率失败,如果直接同步返回给用户,体验会直接崩掉。我的做法是给它挂一条降级链:
DEGRADE = {
("taobao", "item_get"): ["item_get_pro", "item_search_shop_pro", "custom"],
("jd", "item_get_pro"): ["item_get", "item_get_desc"],
("1688", "item_get"): [], # 99%,不配降级,省一次调用
}
def fetch_with_fallback(platform, api, **params):
for candidate in [api] + DEGRADE.get((platform, api), []):
for attempt in range(2): # 每个接口重试一次
r = call(platform, candidate, **params)
if r.get("code") == "0000":
return candidate, r["item"]
time.sleep(0.3)
return None, None # 交给上层入待补采队列注意最后那行 return None, None 不是失败,而是转入异步补采队列。前端立刻返回"数据同步中",后台任务稍后补齐。这一层设计让我的实时接口成功率从 40% 的体感,变成了用户侧 100% 的可响应率。
四、缓存与成本:两个容易漏的细节
第一,cache 参数默认走缓存,铺货、建库这类离线场景一定要用缓存,速度快、成本低;只有实时比价才显式传 cache=no。
第二,错误码直接决定钱。0000(成功)和 2000(搜索成功但无结果)计费,4000 / 4001 / 4002 / 4017 这类服务端与网络错误不计费。所以客户端超时不要设太短——超时主动断开时服务端可能已完成调用,白付一次还拿不到数据。我给到 12 秒,配合重试,长期看反而更省。
第三个容易被忽略的是监控。我在采集层出口统一打了三个指标:按"平台 + 接口"维度的成功率、P95 耗时、以及失败错误码的分布。当某个接口的成功率连续 30 分钟低于它历史基线(比如淘宝 item_get 从 40% 掉到 20%)时自动告警,此时应该立刻把它从降级链首位摘掉,而不是等用户投诉。这套指标另一个用途是对账:每月把各接口的计费调用量按错误码分组统计一次,和账户扣减额度对齐,能提前发现调用量异常增长的模块。
五、写在最后
数据层架构的核心就一句话:把接口的不确定性,关在适配器里。上层业务永远假设数据会来,只是可能晚一点来。测试 key 我是在控制台申请的,入口放这里,需要的自取:API 控制台

