在电商开发这条布满荆棘的路上摸爬滚打了这么多年,和淘宝商品详情 API 接口 “过招” 的经历,至今想起来都印象深刻。从被各种报错整到抓狂,到能熟练用它搭建功能,其中的辛酸与收获,今天就掏心窝子和大伙唠一唠,再附上超实用的代码干货!
刚开始对接淘宝商品详情 API,那叫一个自信满满,心想照着文档走,申请权限、调用接口,不就能轻松拿到数据?现实却立马给了我一记暴击。申请权限时,淘宝开放平台审核严格得超乎想象,营业执照、应用场景说明、数据使用规范等资料,反复修改提交了三四次,等了整整四天,才终于通过审核。好不容易拿到App Key和App Secret,签名验证又成了拦路虎。淘宝的签名算法复杂又严谨,参数顺序、编码格式稍有差错,就返回40001签名错误。那段时间,我日夜对着文档和示例代码钻研,眼睛都快瞅花了,终于写出了正确的签名生成函数:
python
运行
import hashlib
import hmac
import time
import urllib.parse
def generate_sign(params, app_secret):
sorted_params = sorted(params.items(), key=lambda x: x[0])
sign_str = app_secret
for k, v in sorted_params:
sign_str += f"{k}{v}"
sign_str += app_secret
return hmac.new(
app_secret.encode(), sign_str.encode(), hashlib.sha256
).hexdigest().upper()
解决了签名问题,新的难关又出现了。接口调用频率限制让我头疼不已,当时为了快速采集一批商品数据,没把控好请求节奏,短时间内发送过多请求,直接被淘宝封了 IP,还收到警告邮件。没办法,只能静下心研究淘宝的限流规则,用漏桶算法写了个频率控制类,限制请求的发送:
python
运行
import time
class LeakyBucket:
def init(self, capacity, rate):
self.capacity = capacity
self.rate = rate
self.tokens = capacity
self.last_update = time.time()
def consume(self, tokens=1):
now = time.time()
# 补充令牌
self.tokens = min(
self.capacity, self.tokens + (now - self.last_update) * self.rate
)
self.last_update = now
if self.tokens >= tokens:
self.tokens -= tokens
return True
return False
使用示例
bucket = LeakyBucket(capacity=100, rate=20) # 容量100,每秒补充20个令牌
if bucket.consume():
# 调用API
response = requests.get(api_url)
else:
time.sleep(0.1) # 等待令牌补充
python实例
{
"item": {
"seller": {
"seller_id": "1991926764",
"seller_title": "萤石官方旗舰店",
"shop_id": "108801324",
"shop_title": "萤石官方旗舰店",
"shop_url": "//shop108801324.taobao.com",
"shop_icon": "//img.alicdn.com/imgextra//fa/a1/TB1jrf.bV67gK0jSZPfwu1hhFXa.png",
"user_type": "B",
"evaluates": [
{
"score": "4.5",
"title": "宝贝质量"
},
{
"score": "4.7",
"title": "服务保障"
},
{
"score": "4.9",
"title": "物流速度"
}
]
},
"item": {
"num_iid": "680078401583",
"title": "萤石AI人脸识别智能猫眼视频y3000无需指纹家用防盗门电子密码锁",
"sales": "1万+",
"detailurl": "//item.taobao.com/item.htm?id=680078401583",
"images": [
"https://picasso.alicdn.com/imgextra/O1CNA1gU5ZHx1zpy1sNNkWu!!1991926764-0-psf.jpg",
"https://gw.alicdn.com/imgextra/O1CN01dlBDxe1zpxvFHCMU3_!!1991926764.jpg",
"https://gw.alicdn.com/imgextra/O1CN01Bpr20y1zpxlC4kPiZ_!!1991926764.jpg",
"https://gw.alicdn.com/imgextra/O1CN01u0S5FZ1zpxl8DHhP7_!!1991926764.jpg",
"https://gw.alicdn.com/imgextra/O1CN01LtDVqN1zpxlYG6VNs_!!1991926764.jpg"
],
"videos": [
{
"itemId": "680078401583",
"spatialVideoDimension": "3:4",
"url": "http://cloud.video.taobao.com/play/u/1991926764/p/2/e/6/t/1/403135576199.mp4?appKey=38829",
"videoId": "403135576199",
"videoThumbnailURL": "https://picasso.alicdn.com/imgextra/O1CNA1gU5ZHx1zpy1sNNkWu_!!1991926764-0-psf.jpg"
}
],
"descimgs": [
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01qBjMHQ1zpy1PVQ4h3!!1991926764.png",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01kJMnaC1zpy1lp4azl_!!1991926764.png",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01NS1tDu1zpxlVi3F9E_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN01gSwxIt1zpxzGa4PQG_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01Meby0a1zpy1nzk0Bc_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01ycgAMZ1zpxyRZGiSY_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01NkoSvN1zpy1VyEjkN_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN014hrRmK1zpxurSKDpw_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01Fd9pkm1zpxunO1gRj_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN01qy15SD1zpxloGOKfl_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i2/1991926764/O1CN01owRGP81zpxlzfIBJP_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01wV8qSX1zpxlqVM1jW_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN013fo39c1zpxlslaww0_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN01zBsplA1zpxlwoZN6f_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN018NJ7Px1zpxlhG3iXS_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN018oI4951zpxppfuTw2_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN01D6Ztqo1zpxlnUi8Jg_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01Ru69gC1zpxlvh5ktF_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i2/1991926764/O1CN01hpQhIe1zpxlqcgfE6_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN01dwLQRX1zpxwdhvLhK_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01Cryg9b1zpxoRHOgLT_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01e9yQ9L1zpxlhG5vod_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i2/1991926764/O1CN01oXh9v21zpxlnUhriz_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01mZPChI1zpxvM3gX4i_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01EL44Dx1zpxlxaSzqt_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01sHke121zpxlzfGuL2_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN01wZj1TZ1zpxlxaUbdS_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i2/1991926764/O1CN01rqhraG1zpxlypji2Q_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01srU1zt1zpxlxaSvhD_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN01q1HwTG1zpxlslcDwT_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN010rLEHQ1zpxlnUkPhP_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01EaKDeO1zpxlzfH2ea_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01AMWt651zpxlnUjH2d_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i2/1991926764/O1CN01lOOmAH1zpxloGPTN0_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01gf29eF1zpxq0F8IFH_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN01YKtFPI1zpxlvh3LGa_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i2/1991926764/O1CN01i8Swdg1zpxvh1NV2v_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i1/1991926764/O1CN01Gc4iZ31zpxlwoZAfV_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01s9RtRc1zpxw4Dk5ml_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01KCbiov1zpxr9yudOL_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01412DQH1zpxxNFldSn_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i3/1991926764/O1CN01CnGwgW1zpxy8HjCdr_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i2/1991926764/O1CN01vAYzWB1zpxyCHXkiI_!!1991926764.jpg",
"https://img.alicdn.com/imgextra/i4/1991926764/O1CN01ONf91C1zpy1nzkTIR_!!1991926764.jpg"
]
},
"skuBase": {
"1627207": {
"pid": "1627207",
"name": "饰面颜色",
"values": [
{
"vid": "30598787885",
"name": "Y3000F极致灰【3D人脸 不带视频】",
"image": "http://img.alicdn.com/imgextra/i1/1991926764/O1CN01AUty1d1zpxufZY57f_!!1991926764.jpg"
},
{
"vid": "30598787886",
"name": "Y3000FV极致灰【3D人脸+远程视频对讲】",
"image": "http://img.alicdn.com/imgextra/i2/1991926764/O1CN01QWG9bn1zpxuiecyOZ_!!1991926764.jpg"
},
{
"vid": "30598787887",
"name": "Y3000FV晶石紫【3D人脸+远程视频对讲】",
"image": "http://img.alicdn.com/imgextra/i2/1991926764/O1CN01Ot95XQ1zpxug3kw5y_!!1991926764.jpg"
},
{
"vid": "30598841824",
"name": "Y3000FVS静谧黑【3D人脸+远程视频对讲+可视大屏+儿童出门检测】",
"image": "http://img.alicdn.com/imgextra/i3/1991926764/O1CN01aan3rC1zpxun4cooO_!!1991926764.jpg"
}
]
}
},
"skuCore": {
"sku2info": [
{
"skuId": "5442252479410",
"price": "2199.00",
"promotion_price": "1699.00",
"activity_price": "1199.00",
"propPath": "1627207:30598787885",
"propName": "1627207:30598787885:饰面颜色:Y3000F极致灰【3D人脸 不带视频】",
"quantity": 200
},
{
"skuId": "5442252479408",
"price": "2999.00",
"promotion_price": "1999.00",
"activity_price": "1499.00",
"propPath": "1627207:30598787886",
"propName": "1627207:30598787886:饰面颜色:Y3000FV极致灰【3D人脸+远程视频对讲】",
"quantity": 200
},
{
"skuId": "5686996374626",
"price": "2999.00",
"promotion_price": "1999.00",
"activity_price": "1499.00",
"propPath": "1627207:30598787887",
"propName": "1627207:30598787887:饰面颜色:Y3000FV晶石紫【3D人脸+远程视频对讲】",
"quantity": 94
},
{
"skuId": "5442252479411",
"price": "3999.00",
"promotion_price": "2199.00",
"activity_price": "1699.00",
"propPath": "1627207:30598841824",
"propName": "1627207:30598841824:饰面颜色:Y3000FVS静谧黑【3D人脸+远程视频对讲+可视大屏+儿童出门检测】",
"quantity": 200
}
]
},
"price": {
"price": {
"hiddenPrice": "false",
"priceColor": "#FF4F00",
"priceColorNew": "#FFFFFF",
"priceDesc": "起",
"priceMoney": "169900",
"priceText": "1699",
"priceTitle": "百亿补贴",
"priceTitleColor": "#FF4F00",
"priceUnit": "¥"
},
"extraPrice": {
"hiddenPrice": "false",
"priceBgColor": "#FF5000",
"priceColor": "#FFFFFF",
"priceColorNew": "#FFFFFF",
"priceDesc": "起",
"priceMoney": "119900",
"priceText": "1199",
"priceTitle": "折后",
"priceTitleColor": "#FFFFFF",
"priceUnit": "¥"
}
},
"props": [
{
"name": "品牌",
"value": "EZVIZ/萤石"
},
{
"name": "型号",
"value": "Y3000FV人脸视频锁"
},
{
"name": "产地",
"value": "中国大陆"
},
{
"name": "省份",
"value": "浙江省"
},
{
"name": "地市",
"value": "杭州市"
},
{
"name": "面板及执手材质",
"value": "铝合金"
},
{
"name": "智能类型",
"value": "其他智能"
},
{
"name": "电源类型",
"value": "直流电"
},
{
"name": "数据存储类型",
"value": "在线"
},
{
"name": "电子类型",
"value": "密码锁 人脸锁"
},
{
"name": "屏幕数量",
"value": "单屏"
},
{
"name": "饰面颜色",
"value": "Y3000F极致灰【3D人脸 不带视频】 Y3000FV极致灰【3D人脸+远程视频对讲】 Y3000FV晶石紫【3D人脸+远程视频对讲】 Y3000FVS静谧黑【3D人脸+远程视频对讲+可视大屏+儿童出门检测】"
}
],
"extensionInfo": [
{
"items": [
{
"text": [
"购买得积分"
]
}
],
"title": "优惠",
"type": "DAILY_COUPON"
}
],
"delivery": {
"addressId": "11996539000",
"agingDesc": "预计5小时内发货|承诺48小时内发货",
"agingDescColor": "#00A67C",
"areaId": "130435102",
"deliverToCity": "邯郸市",
"deliveryFromAddr": "浙江杭州",
"deliveryToAddr": "邯郸市 曲周县 侯村镇",
"deliveryToDistrict": "曲周县",
"freight": "快递: 免运费"
数据到手后,才发现更大的挑战在等着我。淘宝商品详情数据格式极为复杂,商品基础信息、规格参数、价格体系、库存状态、商家资质等内容层层嵌套,不同类目商品的数据结构还存在差异。比如服装类目会有尺码、面料等信息,电子产品则有型号、配置参数等。为了准确提取关键数据,我写了个通用的数据解析函数,还加了容错处理:
python
运行
def parse_product_data(raw_data):
try:
return {
"product_title": raw_data.get("item", {}).get("title", ""),
"current_price": float(raw_data.get("item", {}).get("price", 0)),
"original_price": float(raw_data.get("item", {}).get("originalPrice", 0)),
"stock": int(raw_data.get("item", {}).get("quantity", 0)),
"category": raw_data.get("item", {}).get("categoryName", "")
}
except KeyError as e:
print(f"字段缺失: {e}")
return {}
示例调用
raw_response = {...} # API返回数据
parsed_data = parse_product_data(raw_response)
有一回,给客户开发一个商品监控系统,需要实时获取商品价格和库存变动。起初我采用定时轮询的方式调用 API,不仅效率低,还浪费资源。后来发现可以利用淘宝的消息订阅功能,当商品信息更新时,淘宝主动推送消息,大大提高了实时性和效率。不过接入消息订阅也没那么容易,要处理消息签名验证、消息解密、重复消息过滤等问题,经过一番折腾,终于实现了稳定接入:
python
运行
import base64
import hashlib
import hmac
from flask import Flask, request, abort
app = Flask(name)
SUBSCRIPTION_SECRET = "your_subscription_secret"
@app.route('/message/subscribe', methods=['POST'])
def handle_subscribe_message():
sign = request.headers.get('X-Taobao-Signature')
if not sign:
abort(401)
data = request.data
local_sign = hmac.new(
SUBSCRIPTION_SECRET.encode('utf-8'),
data,
hashlib.sha256
).hexdigest()
if sign != local_sign:
abort(401)
# 解密消息体(如果有加密)
encrypted_data = request.json.get('encrypted_data', '')
decrypted_data = decrypt_message(encrypted_data) # 自行实现解密函数
# 处理商品更新数据
handle_product_update(decrypted_data)
return "OK", 200
if name == 'main':
app.run(debug=True)
这些年在淘宝商品详情 API 接口开发上,每踩一个坑,就积累一份经验;每解决一个难题,技术能力就得到一次提升。