在电商数据采集场景中,商品列表数据仅能满足基础分析需求,若需深入获取商品规格、详情描述、售后政策等精细化信息,必须接入淘宝商品详情 API。相较于商品搜索 API,详情 API 返回数据结构更复杂(包含多层嵌套字段),且对请求格式、权限校验要求更严格。本文将以 “taobao.item_get”API(淘宝推荐的商品详情接口)为例,通过step-by-step的方式,带你完成从 API 准备、请求构造、数据解析到结果存储的全流程,同时提供可直接运行的代码示例,帮助你快速落地实践。
Step 1:接入前的核心准备工作
在调用淘宝商品详情 API 前,需完成 3 项关键准备,这是避免接口调用失败的前提,也是后续开发的基础。
1.1 确认 API 权限与适用场景
淘宝平台提供多个商品详情相关 API,不同 API 适用场景差异显著,需先选择匹配自身需求的接口:
- taobao.item_get:最常用的详情接口,支持获取单个商品的基础信息(标题、价格、规格、库存)、详情描述、售后规则等,适合 “单商品详情采集” 场景(本文以该接口为例)。
- taobao.item_get_batch:支持批量获取多个商品详情(最多 50 个商品 ID / 次),适合 “批量采集” 场景,但需额外申请批量权限。
- taobao.item_desc_get:仅返回商品详情页的描述内容(如图文介绍),适合 “仅需详情描述” 的轻量场景。
权限申请步骤:
- 登录,
- 在 “接口管理” 中搜索 “taobao.item_get”;
- 点击 “申请权限”。
1.2 获取必要的身份凭证
调用商品详情 API 需 3 类核心凭证,缺少任一凭证都会导致请求被拒绝:
- Api Key & Api Secret:api调用的唯一标识。
- Access Token:用户授权凭证,商品详情 API 属于 “需授权接口”,必须携带有效 Access Token。获取方式有两种:
- 个人测试:通过 “平台 - 测试工具 - Access Token 获取” 生成临时 Token(有效期 24 小时);
- 正式环境:集成淘宝 OAuth2.0 授权流程,引导用户授权后获取长期 Token(有效期 30 天,可刷新)。
1.3 理解 API 请求约束
淘宝对商品详情 API 的调用有严格约束,需提前规避违规风险:
- 调用频率限制:测试权限通常限制 “100 次 / 天”,正式权限根据应用等级调整(如企业应用可能支持 1000 次 / 天),超频率调用会触发 IP 封禁(临时 1-24 小时)。
- 商品 ID 有效性:仅支持淘宝 / 天猫平台的有效商品 ID(即num_iid,可从商品列表 API 或商品详情页 URL 中提取,如 URL“item.taobao.com/item.htm?id=123456789” 中的 “123456789” 即为num_iid)。
- 响应格式:支持 JSON 和 XML,推荐使用 JSON(解析更便捷,且字段类型更明确)。
Step 2:环境搭建与依赖安装
2.1 安装核心依赖库
调用商品详情 API 需用到以下库,其中aiohttp用于发起异步请求(兼容大规模采集),pycryptodome用于请求签名,beautifulsoup4用于解析商品详情中的 HTML 内容(如详情描述中的图片链接):
pip install aiohttp pycryptodome beautifulsoup4 pandas
2.2 复用签名工具函数
淘宝所有 API 均要求请求参数进行 HMAC-SHA256 签名(与商品搜索 API 签名规则一致),可直接复用之前实现的generate_taobao_sign函数,无需重复开发:
import hmac
import hashlib
def generate_taobao_sign(params: dict, app_secret: str) -> str:
"""
生成淘宝API请求签名(HMAC-SHA256)
:param params: 所有请求参数(公共参数+业务参数)
:param app_secret: 应用的App Secret
:return: 小写签名字符串
"""
# 1. 按参数名ASCII升序排序
sorted_params = sorted(params.items(), key=lambda x: x[0])
# 2. 拼接为"key=value"格式字符串(无分隔符)
canonical_str = ''.join([f"{k}{v}" for k, v in sorted_params])
# 3. 前后拼接App Secret后签名
sign_str = app_secret + canonical_str + app_secret
sign = hmac.new(
app_secret.encode('utf-8'),
sign_str.encode('utf-8'),
hashlib.sha256
).hexdigest().lower()
return sign
Step 3:构造商品详情 API 请求(核心步骤)
商品详情 API(taobao.item_get)的请求包含 “公共参数” 和 “业务参数” 两部分,需严格按格式构造,否则会返回 “参数错误” 或 “签名无效”。
3.1 明确请求参数格式
(1)公共参数(所有淘宝 API 必填)
| 参数名 | 类型 | 说明 |
| app_key | 字符串 | 应用的 App Key(从平台获取) |
| method | 字符串 | 接口名称,固定为 “taobao.item_get” |
| format | 字符串 | 响应格式,固定为 “json” |
| v | 字符串 | API 版本,固定为 “2.0” |
| sign_method | 字符串 | 签名方式,固定为 “hmac-sha256” |
| timestamp | 字符串 | 时间戳,格式为 “YYYY-MM-DD HH:MM:SS”(如 2025-08-28 15:30:00) |
| access_token | 字符串 | 有效授权凭证(从 OAuth2.0 流程或测试工具获取) |
(2)业务参数(商品详情 API 特有)
| 参数名 | 类型 | 说明 |
| num_iid | 字符串 | 商品 ID(即num_iid,如 123456789),必填 |
| is_promotion | 布尔值 | 是否获取促销价(true/false),可选,默认 false |
3.2 编写请求构造函数
为避免重复代码,编写build_item_detail_params函数,自动生成符合要求的请求参数(含签名):
from datetime import datetime
def build_item_detail_params(
app_key: str,
app_secret: str,
access_token: str,
num_iid: str,
is_promotion: bool = False
) -> dict:
"""
构造商品详情API的请求参数(含签名)
:param app_key: App Key
:param app_secret: App Secret
:param access_token: Access Token
:param num_iid: 商品ID(num_iid)
:param is_promotion: 是否获取促销价
:return: 完整请求参数(含sign)
"""
# 1. 构造公共参数
public_params = {
"app_key": app_key,
"method": "taobao.item_get",
"format": "json",
"v": "2.0",
"sign_method": "hmac-sha256",
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"access_token": access_token
}
# 2. 构造业务参数
business_params = {
"num_iid": num_iid,
"is_promotion": str(is_promotion).lower() # 转为小写字符串(API要求)
}
# 3. 合并参数并生成签名
all_params = {**public_params, **business_params}
all_params["sign"] = generate_taobao_sign(all_params, app_secret)
return all_params
Step 4:发起异步请求并解析返回数据
商品详情 API 返回数据包含200 + 字段,且存在多层嵌套(如规格信息嵌套在 “sku” 字段中,详情图片嵌套在 “desc” 字段的 HTML 中),需针对性解析核心字段。
4.1 发起异步请求(基于 Aiohttp)
使用 Aiohttp 发起异步请求,既能提升批量采集效率,又能通过 “超时控制”“异常捕获” 避免请求阻塞。编写fetch_item_detail协程函数,负责单商品详情的请求与初步解析:
import asyncio
import aiohttp
from bs4 import BeautifulSoup
from typing import Dict, Optional
async def fetch_item_detail(
session: aiohttp.ClientSession,
app_key: str,
app_secret: str,
access_token: str,
num_iid: str
) -> Optional[Dict]:
"""
异步请求商品详情API并解析核心数据
:param session: Aiohttp会话(复用连接)
:param app_key: App Key
:param app_secret: App Secret
:param access_token: Access Token
:param num_iid: 商品ID
:return: 解析后的商品详情字典(失败返回None)
"""
# 1. 构造请求参数
params = build_item_detail_params(
app_key=app_key,
app_secret=app_secret,
access_token=access_token,
num_iid=num_iid,
is_promotion=True # 获取促销价
)
# 2. 发起异步请求(添加随机延迟,避免限流)
api_url = "https://eco.taobao.com/router/rest" # 淘宝API网关
try:
await asyncio.sleep(asyncio.sleep(random.uniform(0.3, 0.8))) # 0.3-0.8秒延迟
async with session.get(api_url, params=params, timeout=10) as response:
# 3. 检查HTTP响应状态
if response.status != 200:
print(f"商品{num_iid}请求失败,HTTP状态码:{response.status}")
return None
# 4. 解析JSON响应
result = await response.json()
# 5. 检查API错误(如权限不足、商品不存在)
if "error_response" in result:
error_code = result["error_response"]["code"]
error_msg = result["error_response"]["msg"]
print(f"商品{num_iid}API调用失败:[{error_code}] {error_msg}")
return None
# 6. 提取核心详情数据(从"item_get_response.item"字段获取)
raw_item = result["item_get_response"]["item"]
parsed_item = parse_raw_item_data(raw_item) # 后续实现解析函数
print(f"商品{num_iid}详情解析成功,获取{len(parsed_item)}个核心字段")
return parsed_item
except Exception as e:
print(f"商品{num_iid}请求异常:{str(e)}")
return None
4.2 解析核心字段(应对嵌套结构)
淘宝详情 API 返回的raw_item是多层嵌套字典,需按业务需求提取核心字段。以下是常见场景的解析逻辑(含 HTML 解析、规格提取、价格处理):
def parse_raw_item_data(raw_item: Dict) -> Dict:
"""
解析商品详情原始数据,提取核心字段
:param raw_item: API返回的原始商品详情字典
:return: 结构化的商品详情字典
"""
# 1. 基础信息(标题、价格、库存等)
base_info = {
"商品ID": raw_item.get("num_iid", ""),
"商品标题": raw_item.get("title", "").replace("<span class='H'>", "").replace("</span>", ""),
"原价": raw_item.get("price", ""),
"促销价": raw_item.get("promotion_price", raw_item.get("price", "")), # 无促销价则用原价
"库存数量": raw_item.get("total_sold", ""), # 已售数量
"库存状态": "有货" if int(raw_item.get("stock", 0)) > 0 else "无货",
"商品链接": raw_item.get("detail_url", ""),
"主图链接": raw_item.get("pic_url", "")
}
# 2. 店铺信息
shop_info = {
"店铺名称": raw_item.get("seller", {}).get("shop_name", ""),
"店铺类型": raw_item.get("seller", {}).get("shop_type", ""), # 天猫/淘宝
"卖家昵称": raw_item.get("seller", {}).get("nick", ""),
"卖家ID": raw_item.get("seller", {}).get("user_id", "")
}
# 3. 规格信息(如颜色、尺寸,嵌套在"sku"字段中)
sku_info = []
skus = raw_item.get("sku", {}).get("sku_list", []) # 规格列表(可能为空)
for sku in skus:
sku_info.append({
"规格ID": sku.get("sku_id", ""),
"规格名称": sku.get("sku_name", ""), # 如"颜色:黑色;尺寸:XL"
"规格价格": sku.get("price", ""),
"规格库存": sku.get("stock", 0)
})
# 4. 详情描述图片(从HTML中提取,raw_item["desc"]是HTML字符串)
desc_html = raw_item.get("desc", "")
soup = BeautifulSoup(desc_html, "html.parser")
desc_images = [img["src"] for img in soup.find_all("img") if "src" in img.attrs]
# 5. 售后信息
after_sale_info = {
"支持7天无理由": raw_item.get("freight", {}).get("support_7d_return", "未知"),
"发货地": raw_item.get("freight", {}).get("from", "未知"),
"运费": raw_item.get("freight", {}).get("express_fee", "未知")
}
# 合并所有字段,返回结构化数据
return {
**base_info,
**shop_info,
"规格列表": sku_info,
"详情图片列表": desc_images,
**after_sale_info
}
Step 5:批量采集与数据存储
若需采集多个商品详情,可通过 “异步任务调度 + 信号量控制并发” 实现批量处理,并将结果存储为 Excel 或数据库(避免数据丢失)。
5.1 批量采集主函数
import time
import random
import pandas as pd
from typing import List
async def batch_fetch_item_details(
app_key: str,
app_secret: str,
access_token: str,
num_iid_list: List[str],
max_concurrency: int = 30
) -> List[Dict]:
"""
批量采集商品详情
:param app_key: App Key
:param app_secret: App Secret
:param access_token: Access Token
:param num_iid_list: 商品ID列表(如["123456789", "987654321"])
:param max_concurrency: 最大并发数(建议30-50,避免限流)
:return: 解析后的商品详情列表
"""
start_time = time.time()
all_details = []
# 1. 创建Aiohttp会话(复用TCP连接)
timeout = aiohttp.ClientTimeout(total=30)
async with aiohttp.ClientSession(timeout=timeout) as session:
# 2. 创建信号量(控制并发)
semaphore = asyncio.Semaphore(max_concurrency)
# 3. 生成所有异步任务(绑定信号量)
tasks = []
for num_iid in num_iid_list:
# 绑定信号量到任务(避免直接在函数内创建,便于复用)
task = asyncio.create_task(
fetch_item_detail(
session=session,
app_key=app</doubaocanvas>