代码示例:淘宝商品详情接口获取数据实战指南

admin8小时前淘宝api9

一、淘宝商品详情接口体系概览

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 前置准备

  1. 创建应用,获取 AppKeyAppSecret
  2. 申请 taobao.item.get 接口权限
  3. 获取用户授权 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 可以获取最完整、最实时的数据。对于生产环境应用,建议优先申请淘宝开放平台正式接口,确保数据稳定性和合规性。


返回列表

上一篇:小红书笔记详情接口测试实战指南

没有最新的文章了...

相关文章

如何借助淘宝/天猫的 API 接口,实现订单系统的自动同步

在电商运营中,订单管理是商家的核心工作之一。随着业务的增长,手动处理订单的方式不仅效率低下,还容易出错。因此,实现订单信息的自动同步变得尤为重要。本文将详细介绍如何借助淘宝/天猫的 API 接口,实现...

淘宝商品详情高级版(item_get_pro)API 接口获取与应用指南

在电商领域,精准获取商品详情数据对于市场分析、价格策略制定、库存管理以及用户体验优化至关重要。淘宝作为国内领先的电商平台,其提供的 item_get_pro 接口能够帮助开发者高效获取商品的高级详情数...

调用淘宝API接口获取商品类目:完整开发指南

一、概述淘宝商品类目是电商平台最基础的数据结构之一,它决定了商品在平台上的展示方式、属性规则以及搜索推荐逻辑。淘宝开放平台提供了多个类目相关API接口,开发者可以通过这些接口获取完整的类目体系、类目属...

如何使用 Java 获取 1688 商品详情数据

在电商数据采集与分析场景中,1688 作为国内知名的 B2B 电商平台,其 API 提供了获取商品详情、价格、库存等实时数据的便捷途径。本文将详细介绍如何使用 Java 调用 1688 的 aliba...

淘宝 item_cat_get 接口详解:获取淘宝商品类目

一、接口概述item_cat_get 是淘宝开放平台提供的核心类目查询接口,用于获取淘宝/天猫平台的商品类目信息。该接口支持通过类目 ID 查询单个类目的详细信息,包括类目名称、层级、父类目、属性规则...

Java爬虫是什么,如何获取API接口

一、Java爬虫的定义Java爬虫是一种基于Java编程语言开发的网络爬虫程序。它通过模拟浏览器行为,向目标网站发送HTTP请求,获取网页内容并解析出所需数据。Java爬虫技术广泛应用于数据采集、市场...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。