×

唯品会商品详情接口开发实践:SKU 扁平化与促销字段过滤方案

Ace Ace 发表于2026-10-14 16:23:00 浏览19 评论0

抢沙发发表评论

前言

在商品数据同步业务中,唯品会详情接口最大难点不是基础请求,而是嵌套多层的 SKU 规格、动态促销标签与限时价格。常规直接读取原始返回 JSON 的写法,经常出现规格数组入库困难、活动价和原价混淆、下架商品残留脏数据等问题。本文不只是简单演示接口调用,重点封装一套 SKU 扁平化、促销字段分离、异常重试的工具类,适用于商品数据同步、比价业务。

前置准备

Python3 环境,依赖 requests 库。接口存在会话校验,需要维持请求会话;平台会校验请求头,缺少 Referer 或者 UA 会直接返回数据为空。批量查询时必须增加请求间隔,高频调用会触发 IP 限流。

点击获取key和secret

完整代码示例

python

import requests
import time

class VipDetailClient:
    def __init__(self):
        self.session = requests.Session()
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
            "Referer": "https://www.vip.com/"
        }
        self.retry_times = 2
        self.delay = 1.3

    def get_goods_detail(self, goods_id):
        """根据商品ID获取详情,扁平化SKU数据"""
        api_url = "https://api.vip.com/item/detail"
        params = {
            "itemId": goods_id
        }
        for i in range(self.retry_times):
            try:
                resp = self.session.get(api_url, params=params, headers=self.headers, timeout=12)
                time.sleep(self.delay)
                if resp.status_code != 200:
                    return {"code": resp.status_code, "data": None, "msg": "http请求失败"}
                res_json = resp.json()
                raw_data = res_json.get("data", {})
                sku_list = []
                # 扁平化SKU规格
                for sku in raw_data.get("skuList", []):
                    sku_info = {
                        "sku_id": sku.get("skuId"),
                        "spec_name": sku.get("spec", ""),
                        "sale_price": sku.get("salePrice"),
                        "market_price": sku.get("marketPrice"),
                        "stock_num": sku.get("stock", 0)
                    }
                    sku_list.append(sku_info)
                detail_result = {
                    "goods_id": raw_data.get("itemId"),
                    "title": raw_data.get("title", "").strip(),
                    "brand_name": raw_data.get("brandName", ""),
                    "main_images": raw_data.get("picList", []),
                    "desc_html": raw_data.get("description", ""),
                    "promotion_tags": raw_data.get("promotionTagList", []),
                    "sku_list": sku_list,
                    "is_on_sale": raw_data.get("status") == 1
                }
                return {"code":0, "data":detail_result, "msg":"success"}
            except Exception as e:
                if i < self.retry_times -1:
                    time.sleep(2)
                    continue
                return {"code":-1, "data":None, "msg":str(e)}

if __name__ == "__main__":
    client = VipDetailClient()
    item_id = "123456789"
    ret = client.get_goods_detail(item_id)
    if ret["code"] ==0:
        item = ret["data"]
        print("商品标题:", item["title"])
        print("SKU数量:", len(item["sku_list"]))
    else:
        print("获取详情失败:", ret["msg"])

核心逻辑解析


  1. 会话复用:使用 Session 保持 Cookie,减少每次请求握手开销,降低风控识别概率。

  2. SKU 扁平化处理:将多层嵌套的 SKU 规格提取为一维数组,方便直接写入数据库,避免嵌套 JSON 入库解析麻烦。

  3. 促销标签独立存放:把活动标签单独拆分,和基础价格隔离,防止业务误把临时促销价作为日常售价。

  4. 重试机制:网络抖动时自动重试,减少单次请求失败造成的数据丢失。


线上踩坑要点


  1. 商品状态校验:下架商品接口依然会返回基础标题,必须通过 status 字段判断在售状态,避免同步无效商品。

  2. 图片地址:详情描述内图片为相对路径,业务使用时需要拼接域名,否则图片无法正常加载。

  3. 价格类型:价格字段为字符串类型,入库前建议转为浮点,空价格需要做兜底处理,防止程序抛出类型异常。

  4. 限流策略:单次查询间隔建议大于 1 秒,大规模同步建议使用代理 IP 轮换。

群贤毕至

访客