🛍️ 用淘宝官方API合规获取天猫商品数据——告别爬虫风控(附完整Demo)
淘宝/天猫商品数据官方提供
taobao.item.get接口,只需企业/个人实名应用 + AppKey,完全合法、稳定、不封IP,替代 Selenium/Requests 爬虫。一、前置准备
- 注册 淘宝开放平台→ 创建应用(自用型/网站应用)
- 获取
App Key+App Secret - 申请接口权限:
taobao.item.get(商品详情查询) - 天猫商品ID(num_iid)从商品URL提取:
https://detail.tmall.com/item.htm?id=654321098765 → num_iid = 654321098765
⚠️ 公开字段(标题/价格/主图/SKU规格)可不传 session;卖家自己店铺商品的 SKU库存/商家编码 需传 卖家 AccessToken(OAuth2授权)。
二、Python完整Demo(签名 + 调用 + 字段解析)
# top_item_get_demo.py
"""
淘宝/天猫商品详情 官方API调用 Demo
依赖: top_api_client.TaobaoTopClient (签名 + POST封装)
—— 如你还没存过 client,下面附带最小化内联版本 ——
"""
import hashlib
import hmac
import time
import requests
import urllib.parse
from typing import Dict, List, Optional
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
# ────────────────────────────────────────────────────────
# 内联最小化 TOP Client(复用你已有的也行)
# ────────────────────────────────────────────────────────
class TaobaoTopClient:
PROD_GW = "https://gw.api.taobao.com/router/rest"
SANDBOX = "https://gw.api.tbsandbox.com/router/rest"
def __init__(self, app_key: str, app_secret: str, sandbox=False):
self.ak = app_key
self.as_ = app_secret
self.gw = self.SANDBOX if sandbox else self.PROD_GW
def _sign(self, params: Dict) -> str:
filt = sorted((k, v) for k, v in params.items()
if v is not None and str(v).strip() != '' and k != 'sign')
qs = ''.join(f"{k}{v}" for k, v in filt)
return hashlib.md5(f"{self.as_}{qs}{self.as_}".encode()).hexdigest().upper()
def call(self, method: str, biz: Dict, session: str = None) -> Dict:
p = {
"method": method,
"app_key": self.ak,
"timestamp": str(int(time.time() * 1000)),
"format": "json",
"v": "2.0",
"sign_method": "md5"
}
if session:
p["session"] = session
p.update(biz)
p["sign"] = self._sign(p)
r = requests.post(self.gw, data=p, timeout=15)
r.raise_for_status()
d = r.json()
if "error_response" in d:
err = d["error_response"]
raise Exception(f"TOP [{err.get('code')}]: {err.get('msg')} {err.get('sub_msg','')}")
return d.get(list(d.keys() - {"error_response"})[0], {})
# ────────────────────────────────────────────────────────
# 核心:获取天猫/淘宝商品详情
# ────────────────────────────────────────────────────────
def get_tmall_item(client: TaobaoTopClient,
num_iid: str,
session: str = None,
fields: str = None) -> Dict:
"""
Args:
num_iid: 天猫/淘宝商品ID
session: 卖家AccessToken(查自己店铺SKU库存必传)
fields: 返回字段,逗号分隔
Returns:
item 字典
"""
fields = fields or (
"num_iid,title,price,org_price,pic_url,item_imgs,"
"skus,props_name,desc,approve_status,num,outer_id,"
"seller_nick,cid"
)
resp = client.call(
"taobao.item.get",
biz={"num_iid": num_iid, "fields": fields},
session=session
)
return resp.get("item", resp)
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
# ────────────────────────────────────────────────────────
# 解析并打印关键信息
# ────────────────────────────────────────────────────────
def print_item_summary(item: Dict):
print(f"\n📦 商品ID : {item.get('num_iid')}")
print(f" 标题 : {item.get('title')}")
print(f" 一口价 : ¥{item.get('price')}")
print(f" 原价 : ¥{item.get('org_price','—')}")
print(f" 主图 : {item.get('pic_url')}")
print(f" 库存 : {item.get('num')}")
print(f" 状态 : {item.get('approve_status')}")
skus = item.get("skus") or []
if skus:
print(f" SKU数 : {len(skus)}")
for sku in skus[:3]:
print(f" - {sku.get('properties_name','默认')} "
f"¥{sku.get('price')} 库:{sku.get('quantity')} "
f"商家码:{sku.get('outer_id','')}")
else:
print(" ℹ️ skus为空 → 查自己店铺商品需传 seller session")
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
# =========================================================
# 使用示例
# =========================================================
if __name__ == "__main__":
client = TaobaoTopClient(
app_key="YOUR_TOP_APP_KEY",
app_secret="YOUR_TOP_APP_SECRET",
sandbox=False # 生产直连
)
TMALL_ITEM_ID = "654321098765" # ← 替换真实天猫/淘宝商品ID
try:
item = get_tmall_item(
client,
num_iid=TMALL_ITEM_ID,
session=None, # ← 自己店铺查库存/outer_id 传 SELLER_ACCESS_TOKEN
fields="num_iid,title,price,org_price,pic_url,skus,num,approve_status,outer_id,props_name"
)
print_item_summary(item)
except Exception as e:
print("❌", e)
print("→ 检查: AppKey/Secret正确、接口权限已申请、num_iid是有效商品ID")三、关键返回字段(铺货/比价用)
TOP字段 | 含义 | 备注 |
|---|---|---|
num_iid | 商品唯一ID | 外部关联键 |
title | 标题(含营销词) | 裁剪适配目标平台 |
price | 一口价(字符串) | Decimal转换 |
org_price | 原价(划线价) | 促销展示 |
pic_url | 主图URL | 建议下载转存目标图床 |
item_imgs[].url | 所有商品图 | — |
skus[].price / quantity / outer_id | SKU价/库存/商家编码 | 库存需seller session |
skus[].properties_name | 规格文本(颜色:红;尺码:M) | SKU映射 |
approve_status | onsale/instock | 过滤下架 |
desc | 详情HTML(部分类目需 taobao.item.desc.get) | — |
四、避坑清单
坑 | 现象 | 解决 |
|---|---|---|
接口返回空 item | 未申请 taobao.item.get权限 | 控制台→应用→API权限→申请 |
skus为空 | 公开查询不返回库存SKU | 用店铺卖家AccessToken再查 |
天猫商品403 | 个人号无权限(极少)/ ID错 | 确认 num_iid 是天猫商品且未删除 |
desc为空 | 部分类目详情在独立接口 | 补调 taobao.item.desc.get |
QPS超限 | 429 / code=7 | 令牌桶限速 QPS≤4(免费上限5)退避重试 |
五、面试/方案一句话
天猫/淘宝商品数据用官方taobao.item.get(num_iid, fields)合规获取;公开字段不需 session,查自己店铺 SKU 库存/商家编码需传 卖家 OAuth AccessToken;签名按 TOP MD5 规则(参数ASCII升序拼 AppSecret+KV+AppSecret → 大写),完全替代爬虫杜绝风控封禁。
需要我补
taobao.item.desc.get详情HTML获取 + 图片本地化转存脚本 或 淘宝客选品API (taobao.tbk.dg.material.optional) 带佣金解析 吗?