微店商品详情 API 数据解析与批量获取优化指南
一、API 核心机制与限制
- 接口特性
- 商品详情接口(如
weidian.item.get)需通过 OAuth2.0 授权获取access_token,有效期 2 小时,需定期刷新。 - 商品列表接口(如
shop.item.list)支持分页,单页最大 20 条数据,全量获取需遍历所有分页。 - QPS 限制:单店铺授权下 API 调用 QPS 上限为 50-200(依店铺等级调整),跨店铺调用共享全局 QPS(如
appkey总 QPS=1000)。 - IP 限制:单 IP 1 分钟内请求超 500 次可能被临时封禁,返回
403 Forbidden或超时。
- 数据结构
- 商品详情包含多层嵌套字段:
- 基础信息:
item_id、title、price、stock、desc。 - 多媒体资源:
images(主图/详情图 URL 数组)、video_url(可选)。 - SKU 体系:
skus数组,每个 SKU 包含sku_id、properties(规格属性字符串)、price、stock。 - 商家信息:
seller(昵称、店铺 ID、名称)、logistics(运费模板、发货地、物流公司)。 - 社交指标:
share_count(分享量)、like_count(点赞数)。
二、分页策略与全量获取实践
- 分页任务生成
- 步骤:
- 调用
shop.item.list获取店铺商品总数total_count,计算总页数total_page = ceil(total_count / 20)。 - 按页码生成分页任务(如
shop_id=123&page=1、shop_id=123&page=2),推入商品队列。
- 优化点:
- 断点续传:记录每个店铺的已完成页码(Redis
key=shop:{shop_id}:last_page),宕机后从last_page+1继续。 - 增量标记:对比商品
update_time,标记“新增/修改/下架”状态,减少重复请求。
- 全量覆盖保障
- 双层队列设计:
- 店铺队列:按“店铺授权有效期”排序,优先处理即将过期的
token对应店铺。 - 商品队列:按店铺 ID 哈希分区,避免不同店铺商品任务混流。
- 任务调度:
- 店铺调度:刷新
access_token(提前 30 分钟触发),生成分页任务。 - 商品调度:按店铺分配 QPS 配额,本地漏桶算法限流(如店铺 A 节点 QPS≤50)。
三、并发控制与性能优化
- 批量请求优化
- 商品详情批量查询:
weidian.item.get支持一次查询最多 10 个商品 ID,减少请求次数(单条调用节省 90% 请求量)。 - 代码示例(Python):
python import requests def batch_get_items(access_token, item_ids): url = "https://api.weidian.com/micro/item_get" params = { "accessToken": access_token, "num_iids": ",".join(map(str, item_ids)), "fields": "item_id,title,price,stock,images" # 精简字段 } response = requests.get(url, params=params) return response.json()
- 异步与连接池
- 异步请求:使用
asyncio+aiohttp实现并发,示例:
python import asyncio import aiohttp async def fetch_items(session, item_id, access_token): url = f"https://api.weidian.com/micro/item_get?accessToken={access_token}&num_iid={item_id}" async with session.get(url) as response: return await response.json() async def main(): access_token = "YOUR_TOKEN" item_ids = [123, 456, 789] async with aiohttp.ClientSession() as session: tasks = [fetch_items(session, id, access_token) for id in item_ids] results = await asyncio.gather(*tasks) for item in results: print(item) asyncio.run(main())
- 连接池:
requests.Session()复用连接,减少建立/关闭开销。
- 缓存策略
- 热点商品缓存:Redis 存储近 24 小时有更新的商品,
key=item:{item_id},过期时间 2 小时。 - 全量数据持久化:MySQL 分库分表(按
item_id哈希分片),Elasticsearch 建立索引(支持按店铺、分类、价格区间检索)。
四、错误处理与重试机制
- 常见错误码
401 Unauthorized:token失效,触发店铺调度模块刷新token,任务回退到队列头部。429 Too Many Requests:店铺 QPS 超限,延迟重试(延迟时间 =(当前重试次数+1)*10s,最多 5 次),临时下调店铺配额(如降 10%)。5xx:微店服务错误,立即重试(最多 3 次),失败后标记为“待人工处理”。
- 日志与监控
- 店铺维度:任务完成率、失败页码分布、
token刷新成功率。 - 商品维度:单店铺商品总数(API 返回)与实际存储数的差值、重复商品 ID 数。
- 系统维度:节点并发数、代理 IP 可用率、队列堆积量(单店铺商品队列堆积超 100 页即告警)。
五、实践案例:全量商品请求架构
- 架构设计
- 任务源:业务数据库同步的店铺 ID 列表(含授权标记)。
- 店铺队列:RabbitMQ 延迟队列,按“店铺授权有效期”排序。
- 商品队列:按店铺 ID 哈希分区,每个店铺商品任务单独分片。
- 执行节点:本地限流 + 分页请求 + 批量详情查询。
- 数据存储:Redis 缓存热点商品,MySQL 持久化全量数据,Elasticsearch 索引。
- 问题与解决
- 问题 1:店铺数量超 1 万,单店铺平均 100 页,总任务量达 100 万,压垮队列。
- 解决:按“店铺等级”分批次执行(核心店铺优先,普通店铺分时段执行),限制单批次并发店铺数(如同时处理 500 个店铺)。
- 问题 2:大量店铺
token同时过期,集中刷新触发token.refresh接口 QPS 限制。
- 解决:
token过期时间分散化(初始授权时按店铺 ID 哈希错开 30 分钟),为token.refresh单独配置 QPS(如 200QPS),超过则进入延迟队列。
- 问题 3:全量过程中店铺商品更新,导致分页数据偏移。
- 解决:分页任务生成时记录“快照时间”,若执行时发现
total_count变化超 10%,则重新生成分页任务;非核心店铺降低全量频率(如从每日 1 次改为每 3 日 1 次),通过增量接口(如weidian.items.update.list)获取更新商品。