代码示例:淘宝商品详情接口获取数据实战指南
一、淘宝商品详情接口体系概览
1.1 官方接口 vs 第三方接口
表格
| 方案 | 接口来源 | 数据完整性 | 认证要求 | 适用场景 |
|---|---|---|---|---|
| 淘宝开放平台 | 官方 TOP API | ★★★★★ | 企业认证 + 应用审核 | 自有店铺管理 |
| 淘宝联盟 API | 官方淘客接口 | ★★★★☆ | 淘客账号 | 推广选品 |
| 第三方聚合 API | 数据服务商 | ★★★★☆ | 注册即用的 API Key | 快速原型、竞品分析 |
| 网页解析 | 前端渲染数据 | ★★★☆☆ | 无 | 不推荐,反爬严格 |
1.2 核心接口对比
表格
| 接口 | 功能 | 返回字段 |
|---|---|---|
taobao.item.get | 获取单个商品详情 | 标题、价格、库存、SKU、图片、描述 |
taobao.item.sku.get | 获取 SKU 详情 | SKU ID、规格属性、价格、库存 |
taobao.tbk.item.info.get | 淘客商品信息 | 带佣金的商品信息 |
taobao.tbk.item.detail.get | 淘客商品详情 | 推广链接、优惠券、佣金比例 |
二、方案一:淘宝开放平台官方 API(TOP)
2.1 前置准备
- 注册 淘宝开放平台
- 创建应用,获取
AppKey和AppSecret - 申请
taobao.item.get接口权限 - 获取用户授权
SessionKey(OAuth2.0)
2.2 Python 实现
Python
# -*- coding: utf-8 -*-"""
淘宝开放平台 API 客户端
官方 TOP SDK 接入方案
"""import requestsimport hashlibimport timeimport jsonfrom urllib.parse import urlencodefrom typing import Dict, Optional, Listfrom dataclasses import dataclass@dataclassclass TaobaoProduct:
"""淘宝商品数据结构"""
num_iid: str
title: str
price: float
original_price: float
promotion_price: float
pic_url: str
item_imgs: List[str]
desc: str
sku_list: List[Dict]
props: List[Dict]
stock: int
sold_quantity: int
nick: str
seller_id: str
location: str
express_fee: float
ems_fee: float
post_fee: float
has_discount: bool
is_virtual: bool
is_tmall: bool
created: str
modified: strclass TaobaoOpenAPI:
"""
淘宝开放平台 API 客户端
"""
# 正式环境网关
GATEWAY_URL = "https://gw.api.taobao.com/router/rest"
# 沙箱环境
# GATEWAY_URL = "https://gw.api.tbsandbox.com/router/rest"
def __init__(self, app_key: str, app_secret: str, session_key: Optional[str] = None):
self.app_key = app_key
self.app_secret = app_secret
self.session_key = session_key
self.session = requests.Session()
def _generate_sign(self, params: Dict) -> str:
"""
生成 TOP API 签名
规则:参数按 key 排序后拼接,首尾加 app_secret,MD5 大写
"""
# 过滤 sign 和空值
filtered = {k: v for k, v in params.items()
if k != 'sign' and v is not None}
# 按 key 排序
sorted_params = sorted(filtered.items())
# 拼接字符串
param_str = ''.join([f"{k}{v}" for k, v in sorted_params])
# 首尾加 secret
sign_str = f"{self.app_secret}{param_str}{self.app_secret}"
return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
def call_api(self, method: str, params: Dict) -> Dict:
"""
调用 TOP API
Args:
method: API 方法名,如 taobao.item.get
params: 业务参数
Returns:
API 响应
"""
# 公共参数
common_params = {
"method": method,
"app_key": self.app_key,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"format": "json",
"v": "2.0",
"sign_method": "md5"
}
# 合并业务参数
common_params.update(params)
# 生成签名
common_params["sign"] = self._generate_sign(common_params)
try:
response = self.session.post(self.GATEWAY_URL, data=common_params, timeout=30)
response.raise_for_status()
result = response.json()
# 检查错误
if "error_response" in result:
error = result["error_response"]
raise Exception(f"API 错误: {error.get('msg')} (code: {error.get('code')})")
return result
except requests.exceptions.RequestException as e:
raise Exception(f"请求异常: {e}")
def get_item_detail(self, num_iid: str, fields: Optional[str] = None) -> Optional[TaobaoProduct]:
"""
获取商品详情
Args:
num_iid: 淘宝商品数字 ID
fields: 指定返回字段,None 返回全部
Returns:
TaobaoProduct 对象
"""
if fields is None:
fields = (
"num_iid,title,price,original_price,promotion_price,"
"pic_url,item_imgs,desc,sku,props_name,props,"
"num, sold_quantity,nick,seller_id,location,"
"express_fee,ems_fee,post_fee,has_discount,"
"is_virtual,is_tmall,created,modified"
)
params = {
"fields": fields,
"num_iid": num_iid }
# 需要用户授权
if self.session_key:
params["session"] = self.session_key
result = self.call_api("taobao.item.get", params)
# 解析响应
item = result.get("item_get_response", {}).get("item", {})
if not item:
return None
# 解析 SKU 列表
skus = []
for sku in item.get("skus", {}).get("sku", []):
skus.append({
"sku_id": sku.get("sku_id"),
"properties": sku.get("properties_name"),
"price": float(sku.get("price", 0)),
"quantity": int(sku.get("quantity", 0)),
"outer_id": sku.get("outer_id")
})
# 解析属性
props = []
for prop in item.get("props", {}).get("prop", []):
props.append({
"pid": prop.get("pid"),
"name": prop.get("name"),
"value": prop.get("value")
})
return TaobaoProduct(
num_iid=str(item.get("num_iid", "")),
title=item.get("title", ""),
price=float(item.get("price", 0)),
original_price=float(item.get("original_price", 0) or 0),
promotion_price=float(item.get("promotion_price", 0) or 0),
pic_url=item.get("pic_url", ""),
item_imgs=[img.get("url") for img in item.get("item_imgs", {}).get("item_img", [])],
desc=item.get("desc", ""),
sku_list=skus,
props=props,
stock=int(item.get("num", 0)),
sold_quantity=int(item.get("sold_quantity", 0)),
nick=item.get("nick", ""),
seller_id=str(item.get("seller_id", "")),
location=item.get("location", ""),
express_fee=float(item.get("express_fee", 0) or 0),
ems_fee=float(item.get("ems_fee", 0) or 0),
post_fee=float(item.get("post_fee", 0) or 0),
has_discount=item.get("has_discount", False),
is_virtual=item.get("is_virtual", False),
is_tmall=item.get("user_type", 0) == 1,
created=item.get("created", ""),
modified=item.get("modified", "")
)
def get_item_skus(self, num_iid: str) -> List[Dict]:
"""
获取商品 SKU 详情
"""
params = {
"fields": "sku_id,properties_name,price,quantity,outer_id,created,modified",
"num_iid": num_iid }
if self.session_key:
params["session"] = self.session_key
result = self.call_api("taobao.item.sku.get", params)
skus = result.get("item_sku_get_response", {}).get("skus", {}).get("sku", [])
return [{
"sku_id": s.get("sku_id"),
"properties": s.get("properties_name"),
"price": float(s.get("price", 0)),
"quantity": int(s.get("quantity", 0)),
"outer_id": s.get("outer_id")
} for s in skus]# ==================== 使用示例 ====================if __name__ == "__main__":
api = TaobaoOpenAPI(
app_key="your_app_key",
app_secret="your_app_secret",
session_key="your_session_key" # 需要用户授权
)
# 获取商品详情
num_iid = "652874751412"
product = api.get_item_detail(num_iid)
if product:
print("=" * 60)
print(f"商品详情: {product.title}")
print("=" * 60)
print(f"商品ID: {product.num_iid}")
print(f"售价: ¥{product.price}")
print(f"原价: ¥{product.original_price}")
print(f"促销价: ¥{product.promotion_price}")
print(f"库存: {product.stock}")
print(f"销量: {product.sold_quantity}")
print(f"店铺: {product.nick}")
print(f"天猫店: {'是' if product.is_tmall else '否'}")
print(f"发货地: {product.location}")
print(f"主图: {product.pic_url}")
print(f"图片数: {len(product.item_imgs)}")
print("\n【SKU 规格】")
for sku in product.sku_list:
print(f" {sku['properties']} → ¥{sku['price']} (库存:{sku['quantity']})")
print("\n【商品属性】")
for prop in product.props:
print(f" {prop['name']}: {prop['value']}")
else:
print("获取商品详情失败")三、方案二:淘宝联盟 API(淘客场景)
3.1 淘客商品详情获取
Python
class TaobaoTbkAPI:
"""
淘宝联盟 API 客户端
适合获取带佣金的商品信息
"""
def __init__(self, app_key: str, app_secret: str):
self.app_key = app_key
self.app_secret = app_secret
self.base_url = "https://gw.api.taobao.com/router/rest"
def get_tbk_item_info(self, num_iids: str) -> List[Dict]:
"""
获取淘客商品信息
Args:
num_iids: 商品 ID 列表,逗号分隔(最多 40 个)
Returns:
商品信息列表
"""
params = {
"method": "taobao.tbk.item.info.get",
"app_key": self.app_key,
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
"format": "json",
"v": "2.0",
"sign_method": "md5",
"fields": (
"num_iid,title,pict_url,small_images,reserve_price,"
"zk_final_price,user_type,provcity,item_url,"
"volume,nick,seller_id,cat_leaf_name,cat_name,"
"commission_rate,coupon_info"
),
"num_iids": num_iids }
# 生成签名
sign = self._generate_sign(params)
params["sign"] = sign
response = requests.post(self.base_url, data=params, timeout=30)
result = response.json()
items = result.get("tbk_item_info_get_response", {}).get("results", {}).get("n_tbk_item", [])
return [{
"num_iid": item.get("num_iid"),
"title": item.get("title"),
"pic_url": item.get("pict_url"),
"small_images": item.get("small_images", {}).get("string", []),
"reserve_price": float(item.get("reserve_price", 0)),
"zk_final_price": float(item.get("zk_final_price", 0)),
"user_type": item.get("user_type"), # 0=淘宝, 1=天猫
"location": item.get("provcity"),
"item_url": item.get("item_url"),
"volume": int(item.get("volume", 0)),
"nick": item.get("nick"),
"seller_id": item.get("seller_id"),
"commission_rate": float(item.get("commission_rate", 0)) / 100, # 佣金比例
"coupon_info": item.get("coupon_info")
} for item in items]
def _generate_sign(self, params: Dict) -> str:
"""生成签名"""
filtered = {k: v for k, v in params.items() if k != 'sign' and v is not None}
sorted_params = sorted(filtered.items())
param_str = ''.join([f"{k}{v}" for k, v in sorted_params])
sign_str = f"{self.app_secret}{param_str}{self.app_secret}"
return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()# 使用示例if __name__ == "__main__":
tbk = TaobaoTbkAPI(
app_key="your_app_key",
app_secret="your_app_secret"
)
# 批量获取淘客商品信息
items = tbk.get_tbk_item_info("652874751412,652874751413")
for item in items:
print(f"\n商品: {item['title'][:40]}...")
print(f" 券后价: ¥{item['zk_final_price']}")
print(f" 原价: ¥{item['reserve_price']}")
print(f" 30天销量: {item['volume']}")
print(f" 佣金比例: {item['commission_rate']}%")
print(f" 优惠券: {item['coupon_info'] or '无'}")
print(f" 链接: {item['item_url']}")四、方案三:第三方聚合 API(点击快速接入)
4.1 通用商品详情客户端
Python
class ThirdPartyTaobaoAPI:
"""
第三方淘宝商品详情 API 客户端
适合快速原型开发和公开商品数据采集
"""
def __init__(self, api_key: str, base_url: str = "https://api.example.com"):
self.api_key = api_key
self.base_url = base_url
self.session = requests.Session()
def get_item_detail(self, num_iid: str) -> Optional[Dict]:
"""
获取商品详情(全字段)
"""
url = f"{self.base_url}/taobao/item_detail"
params = {
"key": self.api_key,
"num_iid": num_iid,
"lang": "zh-CN"
}
try:
response = self.session.get(url, params=params, timeout=30)
response.raise_for_status()
result = response.json()
if result.get("code") == 200:
return result.get("data", {})
else:
print(f"API 错误: {result.get('msg')}")
return None
except requests.exceptions.RequestException as e:
print(f"请求异常: {e}")
return None
def search_items(self, keyword: str, page: int = 1, sort: str = "sales") -> List[Dict]:
"""
关键词搜索商品
"""
url = f"{self.base_url}/taobao/search"
params = {
"key": self.api_key,
"q": keyword,
"page": page,
"sort": sort # sales:销量, price_asc:价格升序, price_desc:价格降序
}
response = self.session.get(url, params=params, timeout=30)
result = response.json()
if result.get("code") == 200:
return result.get("data", {}).get("items", [])
return []# 使用示例if __name__ == "__main__":
api = ThirdPartyTaobaoAPI(api_key="your_api_key")
# 获取商品详情
detail = api.get_item_detail("652874751412")
if detail:
print("=" * 60)
print(f"商品: {detail.get('title')}")
print(f"价格: ¥{detail.get('price')}")
print(f"促销价: ¥{detail.get('promotion_price')}")
print(f"库存: {detail.get('num')}")
print(f"销量: {detail.get('sold_quantity')}")
print(f"店铺: {detail.get('nick')}")
print(f"评价数: {detail.get('rate_count')}")
print(f"好评率: {detail.get('good_rate')}%")
# SKU 信息
skus = detail.get("skus", [])
print(f"\nSKU 数量: {len(skus)}")
for sku in skus[:3]:
print(f" {sku.get('properties_name')} → ¥{sku.get('price')}")
# 图片列表
images = detail.get("item_imgs", [])
print(f"\n图片数: {len(images)}")
for img in images[:3]:
print(f" {img.get('url')}")
# 搜索商品
results = api.search_items("蓝牙耳机", page=1)
print(f"\n搜索到 {len(results)} 个商品")
for item in results[:5]:
print(f" {item.get('title')[:40]}... | ¥{item.get('price')} | 销量:{item.get('sales')}")五、数据解析与处理
5.1 商品属性解析
Python
def parse_item_props(props_list: List[Dict]) -> Dict[str, str]:
"""
解析商品属性列表为字典
"""
props_dict = {}
for prop in props_list:
name = prop.get("name", "")
value = prop.get("value", "")
if name and value:
props_dict[name] = value return props_dictdef parse_sku_properties(properties_name: str) -> Dict[str, str]:
"""
解析 SKU 属性字符串
如 "1627207:28320:颜色:黑色;20509:28324:版本:标准版"
"""
result = {}
if not properties_name:
return result
parts = properties_name.split(";")
for part in parts:
segments = part.split(":")
if len(segments) >= 4:
# 格式: pid:vid:属性名:属性值
prop_name = segments[2]
prop_value = segments[3]
result[prop_name] = prop_value
return resultdef calculate_discount(original: float, current: float) -> float:
"""计算折扣率"""
if original <= 0:
return 0
return round((original - current) / original * 100, 1)# 使用示例props = [
{"pid": "20000", "name": "品牌", "value": "Apple"},
{"pid": "122216608", "name": "型号", "value": "iPhone 16"},
{"pid": "100000177", "name": "存储容量", "value": "256GB"}]parsed = parse_item_props(props)print(parsed)# {'品牌': 'Apple', '型号': 'iPhone 16', '存储容量': '256GB'}sku_props = "1627207:28320:颜色:黑色;20509:28324:版本:标准版"print(parse_sku_properties(sku_props))# {'颜色': '黑色', '版本': '标准版'}六、异常处理与限流控制
Python
import timeimport randomfrom functools import wrapsdef retry_on_failure(max_retries=3, backoff_factor=1):
"""
重试装饰器
"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_retries - 1:
raise
wait = backoff_factor * (2 ** attempt) + random.uniform(0, 1)
print(f"请求失败,{wait:.1f}s 后重试 ({attempt + 1}/{max_retries})")
time.sleep(wait)
return None
return wrapper return decoratordef rate_limited(max_per_second=10):
"""
限流装饰器
"""
min_interval = 1.0 / max_per_second
last_called = [0.0]
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
elapsed = time.time() - last_called[0]
if elapsed < min_interval:
time.sleep(min_interval - elapsed)
result = func(*args, **kwargs)
last_called[0] = time.time()
return result return wrapper return decoratorclass RobustTaobaoAPI:
"""
带重试和限流的淘宝 API 客户端
"""
def __init__(self, api_key: str, api_secret: str):
self.api = TaobaoOpenAPI(api_key, api_secret)
@retry_on_failure(max_retries=3, backoff_factor=1)
@rate_limited(max_per_second=5)
def get_item_safe(self, num_iid: str) -> Optional[TaobaoProduct]:
"""安全获取商品详情"""
return self.api.get_item_detail(num_iid)
def batch_get_items(self, num_iids: List[str]) -> Dict[str, Optional[TaobaoProduct]]:
"""批量获取(带进度显示)"""
results = {}
total = len(num_iids)
for idx, num_iid in enumerate(num_iids, 1):
print(f"进度: {idx}/{total} | 获取 {num_iid}...")
results[num_iid] = self.get_item_safe(num_iid)
# 每 10 个暂停一下
if idx % 10 == 0:
time.sleep(2)
return results七、数据存储与监控
Python
import sqlite3from datetime import datetimeclass ProductDataStore:
"""商品数据存储"""
def __init__(self, db_path: str = "taobao_products.db"):
self.conn = sqlite3.connect(db_path)
self._init_tables()
def _init_tables(self):
self.conn.execute("""
CREATE TABLE IF NOT EXISTS products (
num_iid TEXT PRIMARY KEY,
title TEXT,
price REAL,
original_price REAL,
promotion_price REAL,
stock INTEGER,
sold_quantity INTEGER,
nick TEXT,
seller_id TEXT,
location TEXT,
is_tmall INTEGER,
pic_url TEXT,
created_at TIMESTAMP,
updated_at TIMESTAMP
)
""")
self.conn.execute("""
CREATE TABLE IF NOT EXISTS price_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
num_iid TEXT,
price REAL,
promotion_price REAL,
recorded_at TIMESTAMP,
FOREIGN KEY (num_iid) REFERENCES products(num_iid)
)
""")
self.conn.commit()
def save_product(self, product: TaobaoProduct):
"""保存或更新商品"""
self.conn.execute("""
INSERT OR REPLACE INTO products
(num_iid, title, price, original_price, promotion_price,
stock, sold_quantity, nick, seller_id, location,
is_tmall, pic_url, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (
product.num_iid, product.title, product.price,
product.original_price, product.promotion_price,
product.stock, product.sold_quantity,
product.nick, product.seller_id, product.location,
1 if product.is_tmall else 0, product.pic_url,
datetime.now(), datetime.now()
))
# 记录价格历史
self.conn.execute("""
INSERT INTO price_history (num_iid, price, promotion_price, recorded_at)
VALUES (?, ?, ?, ?)
""", (product.num_iid, product.price, product.promotion_price, datetime.now()))
self.conn.commit()
def get_price_trend(self, num_iid: str, days: int = 7) -> List[Dict]:
"""获取价格趋势"""
cursor = self.conn.execute("""
SELECT price, promotion_price, recorded_at
FROM price_history
WHERE num_iid = ? AND recorded_at > datetime('now', '-{} days')
ORDER BY recorded_at
""".format(days), (num_iid,))
return [{
"price": row[0],
"promotion_price": row[1],
"time": row[2]
} for row in cursor.fetchall()]八、关键注意事项
表格
| 注意事项 | 说明 |
|---|---|
| 企业认证 | 官方 API 需企业认证,个人权限受限 |
| SessionKey | 获取用户商品需 OAuth 授权,有效期有限 |
| 限流策略 | 官方默认 100 次/分钟,超出会封禁 |
| 字段变更 | 淘宝 API 字段可能调整,需关注更新公告 |
| 数据合规 | 仅用于自有业务,不得转售或恶意爬取 |
| 反爬机制 | 非官方接口需注意反爬,建议合规接入 |
九、总结
表格
| 方案 | 认证难度 | 数据完整性 | 适用场景 |
|---|---|---|---|
| 官方 TOP API | 高(需企业认证) | ★★★★★ | 自有店铺 ERP、数据同步 |
| 淘宝联盟 API | 中(需淘客账号) | ★★★★☆ | 推广选品、佣金计算 |
| 第三方聚合 API | 低(注册即用) | ★★★★☆ | 快速原型、竞品分析 |
淘宝商品详情接口是电商数据采集的核心能力,通过官方 API 可以获取最完整、最实时的数据。对于生产环境应用,建议优先申请淘宝开放平台正式接口,确保数据稳定性和合规性。