一、概述
淘宝商品类目是电商平台最基础的数据结构之一,它决定了商品在平台上的展示方式、属性规则以及搜索推荐逻辑。淘宝开放平台提供了多个类目相关API接口,开发者可以通过这些接口获取完整的类目体系、类目属性及属性值等信息。本文将详细介绍如何注册开发者账号、申请权限、生成签名并调用类目相关API。
二、准备工作
2.1 注册淘宝开放平台账号
- 访问 淘宝开放平台
- 点击注册,使用淘宝账号登录并完成实名认证
- 进入控制台,创建新应用
2.2 创建应用并获取密钥
在开放平台控制台中:
- 进入「应用管理」→「创建应用」
- 填写应用名称、描述、图标等信息
- 选择应用类型(自用型或他用型)
- 填写使用场景和目的
- 提交审核,审核通过后将获得:App Key:应用标识App Secret:应用密钥(用于签名)
2.3 申请API权限
在应用详情页中找到「接口权限」模块,申请以下类目相关接口权限:
- taobao.itemcats.get — 获取可供发布的类目列表
- taobao.item.cat.get — 获取单个类目详情
- taobao.itemprops.get — 获取标准商品类目属性
- taobao.itempropvalues.get — 获取标准类目属性值
- taobao.itemcats.authorize.get — 查询商家被授权的品牌和类目
⚠️ 注意:淘宝开放平台会根据应用情况、资质及安全策略进行审核,部分接口可能需要商家授权才能调用。
三、核心API接口详解
3.1 接口概览
| 接口名称 | 功能描述 | 是否需要授权 |
|---|---|---|
taobao.itemcats.get | 获取可供发布的标准类目列表 | 否 |
taobao.item.cat.get | 获取单个类目详细信息 | 否 |
taobao.itemprops.get | 获取类目的属性列表 | 否 |
taobao.itempropvalues.get | 获取类目的属性值列表 | 否 |
taobao.itemcats.authorize.get | 查询商家被授权的品牌和类目 | 是 |
四、签名生成机制
淘宝API采用 HMAC-MD5 签名算法,所有请求参数必须经过签名验证。签名步骤如下:
4.1 签名规则
- 排序:将所有参数(除 sign 外)按参数名 ASCII 码升序排列
- 拼接:将排序后的参数按 key+value 格式拼接成字符串,首尾各加一次 App Secret
- 加密:使用 HMAC-MD5 算法加密,结果转大写
4.2 Python签名示例
import hmac
import hashlib
import urllib.parse
def generate_sign(params: dict, app_secret: str) -> str:
"""
生成淘宝API请求签名(HMAC-MD5)
:param params: 请求参数(不含sign)
:param app_secret: 应用密钥
:return: 签名字符串(大写)
"""
# 1. 过滤空值参数,按key排序
sorted_params = sorted(
[(k, v) for k, v in params.items() if v is not None and k != 'sign'],
key=lambda x: x[0]
)
# 2. 拼接字符串:secret + key1value1 + key2value2 + ... + secret
sign_content = app_secret
for key, value in sorted_params:
sign_content += f"{key}{value}"
sign_content += app_secret
# 3. HMAC-MD5加密
sign = hmac.new(
app_secret.encode('utf-8'),
sign_content.encode('utf-8'),
hashlib.md5
).hexdigest().upper()
return sign
五、完整调用示例
5.1 获取一级类目列表(taobao.itemcats.get)
该接口用于获取可供发布的标准类目,通过递归调用可获取完整的类目树。
import requests
import time
import json
# ========== 配置信息 ==========
APP_KEY = 'your_app_key' # 替换为你的App Key
APP_SECRET = 'your_app_secret' # 替换为你的App Secret
API_URL = 'https://eco.taobao.com/router/rest'
# ========== 签名生成函数 ==========
def generate_sign(params, app_secret):
sorted_params = sorted(
[(k, v) for k, v in params.items() if v is not None and k != 'sign'],
key=lambda x: x[0]
)
sign_content = app_secret
for key, value in sorted_params:
sign_content += f"{key}{value}"
sign_content += app_secret
import hmac, hashlib
sign = hmac.new(
app_secret.encode('utf-8'),
sign_content.encode('utf-8'),
hashlib.md5
).hexdigest().upper()
return sign
# ========== 获取类目列表 ==========
def get_itemcats(parent_cid=0, fields=None):
"""
调用 taobao.itemcats.get 获取类目列表
:param parent_cid: 父类目ID,0表示获取一级类目
:param fields: 返回字段,默认获取常用字段
:return: 类目列表
"""
if fields is None:
fields = "cid,parent_cid,name,is_parent,status,sort_order"
params = {
'app_key': APP_KEY,
'method': 'taobao.itemcats.get',
'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
'format': 'json',
'v': '2.0',
'sign_method': 'hmac-md5',
'fields': fields,
'parent_cid': parent_cid
}
# 生成签名
params['sign'] = generate_sign(params, APP_SECRET)
# 发送请求
response = requests.post(API_URL, data=params, timeout=30)
result = response.json()
# 解析结果
if 'itemcats_get_response' in result:
itemcats = result['itemcats_get_response'].get('item_cats', {}).get('item_cat', [])
return itemcats
else:
error = result.get('error_response', {})
print(f"调用失败: {error.get('msg', '未知错误')}")
return None
# ========== 递归获取完整类目树 ==========
def build_category_tree(parent_cid=0, max_depth=3, current_depth=0):
"""
递归构建类目树
:param parent_cid: 父类目ID
:param max_depth: 最大递归深度
:param current_depth: 当前深度
:return: 类目树结构
"""
if current_depth >= max_depth:
return []
categories = get_itemcats(parent_cid)
if not categories:
return []
tree = []
for cat in categories:
node = {
'cid': cat.get('cid'),
'name': cat.get('name'),
'parent_cid': cat.get('parent_cid'),
'is_parent': cat.get('is_parent'),
'status': cat.get('status'),
'sort_order': cat.get('sort_order'),
'children': []
}
# 如果是父类目,递归获取子类目
if cat.get('is_parent') and current_depth < max_depth - 1:
# 添加延时避免触发限流(个人开发者通常1QPS)
time.sleep(1.2)
node['children'] = build_category_tree(
cat.get('cid'), max_depth, current_depth + 1
)
tree.append(node)
return tree
# ========== 主程序 ==========
if __name__ == '__main__':
print("=" * 50)
print("淘宝商品类目获取工具")
print("=" * 50)
# 获取一级类目
print("\n【一级类目列表】")
top_categories = get_itemcats(parent_cid=0)
for cat in top_categories[:5]: # 只展示前5个
print(f" 📁 [{cat['cid']}] {cat['name']} "
f"{'(有子类目)' if cat.get('is_parent') else '(叶子类目)'}")
# 获取某个一级类目下的二级类目(以女装为例:cid=50008163)
print("\n【女装类目下的二级类目】")
sub_categories = get_itemcats(parent_cid=50008163)
if sub_categories:
for cat in sub_categories[:5]:
print(f" 📂 [{cat['cid']}] {cat['name']}")
# 构建完整类目树(示例:只递归2层)
print("\n【构建类目树(深度2)】")
# tree = build_category_tree(parent_cid=0, max_depth=2)
# print(json.dumps(tree, ensure_ascii=False, indent=2))
5.2 获取单个类目详情(taobao.item.cat.get)
def get_item_cat_detail(cid):
"""
获取单个类目的详细信息
:param cid: 类目ID
:return: 类目详情
"""
params = {
'app_key': APP_KEY,
'method': 'taobao.item.cat.get',
'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
'format': 'json',
'v': '2.0',
'sign_method': 'hmac-md5',
'cid': cid
}
params['sign'] = generate_sign(params, APP_SECRET)
response = requests.post(API_URL, data=params, timeout=30)
result = response.json()
if 'item_cat_get_response' in result:
return result['item_cat_get_response'].get('item_cat', {})
else:
error = result.get('error_response', {})
print(f"获取失败: {error.get('msg', '未知错误')}")
return None
# 示例:获取女装类目详情
cat_detail = get_item_cat_detail(50008163)
if cat_detail:
print(f"类目名称: {cat_detail.get('name')}")
print(f"父类目ID: {cat_detail.get('parent_cid')}")
print(f"是否为父类目: {cat_detail.get('is_parent')}")
5.3 获取类目属性(taobao.itemprops.get)
def get_item_props(cid, fields=None):
"""
获取类目的属性列表
:param cid: 类目ID
:param fields: 返回字段
:return: 属性列表
"""
if fields is None:
fields = "pid,name,must,multi,prop_values,is_key_prop,is_sale_prop"
params = {
'app_key': APP_KEY,
'method': 'taobao.itemprops.get',
'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
'format': 'json',
'v': '2.0',
'sign_method': 'hmac-md5',
'fields': fields,
'cid': cid
}
params['sign'] = generate_sign(params, APP_SECRET)
response = requests.post(API_URL, data=params, timeout=30)
result = response.json()
if 'itemprops_get_response' in result:
return result['itemprops_get_response'].get('item_props', {}).get('item_prop', [])
else:
error = result.get('error_response', {})
print(f"获取失败: {error.get('msg', '未知错误')}")
return None
# 示例:获取手机类目(cid=1512)的属性
print("\n【手机类目属性列表】")
props = get_item_props(1512)
if props:
for prop in props[:5]:
print(f" 🔧 [{prop['pid']}] {prop['name']} "
f"{'(必填)' if prop.get('must') else '(选填)'} "
f"{'(多选)' if prop.get('multi') else '(单选)'}")
5.4 获取类目属性值(taobao.itempropvalues.get)
def get_item_prop_values(cid, pvs, fields=None):
"""
获取类目的属性值列表
:param cid: 类目ID
:param pvs: 属性ID,多个用逗号分隔,如 "139248429"
:param fields: 返回字段
:return: 属性值列表
"""
if fields is None:
fields = "cid,pid,prop_name,vid,name,name_alias,status,sort_order"
params = {
'app_key': APP_KEY,
'method': 'taobao.itempropvalues.get',
'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
'format': 'json',
'v': '2.0',
'sign_method': 'hmac-md5',
'fields': fields,
'cid': cid,
'pvs': pvs
}
params['sign'] = generate_sign(params, APP_SECRET)
response = requests.post(API_URL, data=params, timeout=30)
result = response.json()
if 'itempropvalues_get_response' in result:
return result['itempropvalues_get_response'].get('prop_values', {}).get('prop_value', [])
else:
error = result.get('error_response', {})
print(f"获取失败: {error.get('msg', '未知错误')}")
return None
六、返回字段说明
6.1 taobao.itemcats.get 返回字段
| 字段名 | 类型 | 说明 |
|---|---|---|
cid | Number | 类目ID |
parent_cid | Number | 父类目ID |
name | String | 类目名称 |
is_parent | Boolean | 是否为父类目(true表示有子类目) |
status | String | 类目状态(normal/normal) |
sort_order | Number | 排序值 |
6.2 类目属性字段
| 字段名 | 类型 | 说明 |
|---|---|---|
pid | Number | 属性ID |
name | String | 属性名称 |
must | Boolean | 是否必填 |
multi | Boolean | 是否多选 |
is_key_prop | Boolean | 是否关键属性(如品牌、型号) |
is_sale_prop | Boolean | 是否销售属性(影响SKU) |
七、关键注意事项
7.1 调用频率限制
淘宝开放平台对接口调用有 QPS(每秒查询率)限制,个人开发者通常限制为 1 QPS。建议在代码中加入延时控制:
import time
# 每次调用间隔至少1.2秒
time.sleep(1.2)
7.2 叶子类目
商品必须发布在叶子类目(is_parent = false)下。获取叶子类目的方法是通过递归调用 taobao.itemcats.get,直到 is_parent 为 false。
7.3 管控类目
部分类目(如食品、酒类、书籍、保健品、农药、医疗等)需要卖家提供相关资质才能发布,调用 taobao.itemcats.authorize.get 可查询商家是否有权限发布。
7.4 错误处理
常见错误码及处理方式:
| 错误码 | 说明 | 解决方案 |
|---|---|---|
isv.invalid-parameter | 参数错误 | 检查参数格式和必填项 |
isv.permission-ip-limit | IP受限 | 在开放平台配置服务器IP白名单 |
isv.permission-api-forbidden | API权限不足 | 申请对应接口权限 |
isv.trade-not-exist | 交易不存在 | 检查传入的参数值 |
八、Java调用示例
import java.util.*;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
import java.net.URLEncoder;
public class TaobaoCategoryApi {
private static final String APP_KEY = "your_app_key";
private static final String APP_SECRET = "your_app_secret";
private static final String API_URL = "https://eco.taobao.com/router/rest";
/**
* 生成HMAC-MD5签名
*/
public static String generateSign(Map<String, String> params, String appSecret) throws Exception {
List<String> keys = new ArrayList<>(params.keySet());
Collections.sort(keys);
StringBuilder sb = new StringBuilder();
sb.append(appSecret);
for (String key : keys) {
String value = params.get(key);
if (value != null && !value.isEmpty()) {
sb.append(key).append(value);
}
}
sb.append(appSecret);
Mac mac = Mac.getInstance("HmacMD5");
SecretKeySpec secretKey = new SecretKeySpec(appSecret.getBytes("UTF-8"), "HmacMD5");
mac.init(secretKey);
byte[] bytes = mac.doFinal(sb.toString().getBytes("UTF-8"));
return Hex.encodeHexString(bytes).toUpperCase();
}
/**
* 获取类目列表
*/
public static String getItemCats(long parentCid) throws Exception {
Map<String, String> params = new HashMap<>();
params.put("app_key", APP_KEY);
params.put("method", "taobao.itemcats.get");
params.put("timestamp", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
params.put("format", "json");
params.put("v", "2.0");
params.put("sign_method", "hmac-md5");
params.put("fields", "cid,parent_cid,name,is_parent,status,sort_order");
params.put("parent_cid", String.valueOf(parentCid));
String sign = generateSign(params, APP_SECRET);
params.put("sign", sign);
// 构造请求URL
StringBuilder urlBuilder = new StringBuilder(API_URL + "?");
for (Map.Entry<String, String> entry : params.entrySet()) {
urlBuilder.append(entry.getKey())
.append("=")
.append(URLEncoder.encode(entry.getValue(), "UTF-8"))
.append("&");
}
// 发送HTTP请求(此处使用HttpClient或URLConnection)
// ...
return urlBuilder.toString();
}
public static void main(String[] args) throws Exception {
System.out.println(getItemCats(0));
}
}
九、总结
| 步骤 | 内容 |
|---|---|
| 1. 注册 | 在淘宝开放平台注册开发者账号并完成实名认证 |
| 2. 创建应用 | 创建应用并获取 App Key 和 App Secret |
| 3. 申请权限 | 申请类目相关API接口权限 |
| 4. 生成签名 | 使用 HMAC-MD5 算法生成请求签名 |
| 5. 调用接口 | 通过 HTTP POST/GET 发送请求到 https://eco.taobao.com/router/rest |
| 6. 解析数据 | 解析JSON响应,构建类目树结构 通过以上步骤,您可以完整地获取淘宝的商品类目体系,为商品发布、数据分析、类目导航等功能提供数据支持。建议在实际开发中做好异常处理和限流控制,确保系统稳定运行。 |
如遇任何疑问或有进一步的需求,请随时与我私信或者评论联系。

