前言 17 货源(gz.17zwd.com)作为广州沙河、十三行服装批发 B2B 平台,商品详情接口除基础图文之外,还包含档口摊位、拿货规则、多尺码 SKU、面料材质等服装供应链特有的元数据。网上大多示例只做简单 http 请求,忽略该平台痛点:SKU 规格嵌套层级不固定、档口信息字段分散、起批规则多样、下架商品依旧返回部分基础字段。本文不再演示基础调用,聚焦规格扁平化解析、档口货源元数据提取、无效商品状态识别,适配服装 ERP 货源同步业务。 对接前需要在开放后台申请 完整代码示例 核心差异化设计思路 SKU 规格扁平化:针对服装多颜色多尺码嵌套结构,把多层 sku_list 拆解为一维数组,方便直接入库,避免业务层反复嵌套循环解析。 B2B 货源元数据提取:专门解析批发市场、档口摊位、起批模式、面料材质,这是服装批发业务核心信息,区别普通电商只解析图文价格。 在售状态强校验:下架商品接口不会直接报错,通过 安全取值容错:所有字段均使用 get 安全取值,不同品类(女装、男装、家居服)返回字段存在差异,防止个别字段缺失直接抛出异常。app_key、app_secret,接口需要 MD5 签名鉴权,入参为商品 goods_id,返回包含图文、多 SKU、批发市场档口信息。
import requests
import time
import hashlib
class SeventeenZwdDetail:
def __init__(self, app_key, app_secret):
self.app_key = app_key
self.app_secret = app_secret
self.api_url = "https://open.17zwd.com/api/goods/detail"
self.session = requests.Session()
def build_sign(self, params):
"""参数字典排序生成md5签名"""
sorted_items = sorted(params.items())
raw_str = "".join([f"{k}{v}" for k, v in sorted_items]) + self.app_secret
return hashlib.md5(raw_str.encode("utf‑8")).hexdigest().upper()
def get_goods_detail(self, goods_id, site="gz"):
params = {
"app_key": self.app_key,
"site": site,
"goods_id": goods_id,
"timestamp": str(int(time.time()))
}
params["sign"] = self.build_sign(params)
try:
resp = self.session.get(self.api_url, params=params, timeout=16)
resp.raise_for_status()
resp_json = resp.json()
except Exception as e:
return {"ok":False, "msg":f"网络异常:{str(e)}", "data":None}
if resp_json.get("code") != 200:
return {"ok":False, "msg":resp_json.get("msg","接口业务异常"), "data":None}
raw = resp_json.get("data",{})
#规格扁平化处理,把嵌套SKU展开成一维数组
sku_list = []
for sku in raw.get("sku_list",[]):
sku_list.append({
"spec_name":sku.get("spec_name",""),
"wholesale_price":float(sku.get("wholesale_price",0)),
"stock_num":sku.get("stock_num",0),
"spec_code":sku.get("spec_code","")
})
result_data = {
"goods_id":raw.get("goods_id"),
"title":raw.get("title","").strip(),
"goods_sn":raw.get("goods_sn",""),
"market_name":raw.get("market_name",""),
"stall_name":raw.get("stall_name",""),
"stall_no":raw.get("stall_no",""),
"min_batch":raw.get("min_batch",1),
"batch_type":raw.get("batch_type",""),
"material":raw.get("material",""),
"images":[img.get("url","") for img in raw.get("images",[])],
"desc":raw.get("desc",""),
"sku_list":sku_list,
"is_on_sale":bool(raw.get("is_on_sale",0))
}
#过滤已经下架商品
if not result_data["is_on_sale"]:
return {"ok":False,"msg":"商品已下架","data":result_data}
return {"ok":True,"data":result_data}
if __name__ == "__main__":
client = SeventeenZwdDetail("your_app_key","your_app_secret")
ret = client.get_goods_detail(goods_id="12345678",site="gz")
print(ret["data"])is_on_sale字段主动识别,做业务标记,避免把已经停售的货源同步到业务系统。