Step-by-Step: 接入淘宝商品详情 API 并解析返回数据
在电商数据采集场景中,商品列表数据仅能满足基础分析需求,若需深入获取商品规格、详情描述、售后政策等精细化信息,必须接入淘宝商品详情 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“https://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 hashlibdef 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_secretsign = 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 datetimedef 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, Optionalasync 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_itemexcept 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 Listasync 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>