×

抖音商品详情接口技术解析与实战指南

admin admin 发表于2026-04-21 17:30:00 浏览9 评论0

抢沙发发表评论

一、接口概述

抖音商品详情接口是抖音开放平台/电商生态中用于获取商品详细信息的核心 API,广泛应用于商品展示、比价系统、数据分析、选品工具等场景。通过该接口,开发者可以获取商品的标题、价格、图片、规格、销量、评价等完整信息。

二、接口基本信息

2.1 接口端点

plain
复制
GET /api/product/detail
# 或
GET /open/api/v1/product/info
注:具体端点需根据抖音开放平台最新文档确认,不同业务线(抖店、精选联盟、抖音电商等)接口路径可能不同。

2.2 请求方式

  • HTTP Method: GET / POST
  • Content-Type: application/jsonapplication/x-www-form-urlencoded
  • 协议: HTTPS(强制)

三、请求参数详解

表格
参数名类型必填说明
app_keystring应用唯一标识
timestampint当前时间戳(秒级)
signstring请求签名(防篡改)
product_idstring条件商品ID(与 sku_id 二选一)
sku_idstring条件SKU ID
fieldsstring指定返回字段,逗号分隔

3.1 签名生成算法

Python
复制
import hashlibimport timedef generate_sign(params: dict, app_secret: str) -> str:
    """
    抖音接口签名生成(通用 HMAC-SHA256 或 MD5 方式)
    """
    # 1. 过滤空值,按 key 升序排序
    sorted_params = sorted(
        [(k, v) for k, v in params.items() if v is not None and k != 'sign']
    )
    
    # 2. 拼接字符串:key1value1key2value2...
    param_str = ''.join([f"{k}{v}" for k, v in sorted_params])
    
    # 3. 首尾拼接 app_secret
    sign_str = f"{app_secret}{param_str}{app_secret}"
    
    # 4. MD5 加密并转大写
    sign = hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()
    return sign# 使用示例params = {
    "app_key": "your_app_key",
    "timestamp": int(time.time()),
    "product_id": "1234567890"}sign = generate_sign(params, "your_app_secret")params["sign"] = sign

四、响应数据结构

4.1 成功响应示例

JSON
复制
{
    "code": 0,
    "message": "success",
    "data": {
        "product_id": "1234567890",
        "product_name": "【官方正品】某某品牌无线蓝牙耳机 降噪长续航",
        "category": {
            "cat_id": 1234,
            "cat_name": "数码配件",
            "parent_id": 100
        },
        "price_info": {
            "original_price": 29900,
            "sale_price": 19900,
            "currency": "CNY",
            "price_unit": "分"
        },
        "inventory": {
            "total_stock": 5000,
            "available_stock": 3200
        },
        "images": [
            {
                "url": "https://p3.douyinpic.com/img/xxx~noop.webp",
                "width": 800,
                "height": 800
            }
        ],
        "sku_list": [
            {
                "sku_id": "sku_001",
                "sku_name": "白色-标准版",
                "price": 19900,
                "stock": 1500,
                "properties": [
                    {"prop_name": "颜色", "value": "白色"},
                    {"prop_name": "版本", "value": "标准版"}
                ]
            }
        ],
        "sales_info": {
            "total_sales": 150000,
            "month_sales": 25000,
            "unit": "件"
        },
        "shop_info": {
            "shop_id": "shop_123",
            "shop_name": "某某旗舰店",
            "shop_score": 4.8
        },
        "logistics": {
            "template_id": "tpl_001",
            "free_shipping": true,
            "dispatch_city": "深圳市"
        },
        "status": 1,
        "create_time": "2024-01-15T10:30:00Z",
        "update_time": "2026-04-21T08:00:00Z"
    }}

4.2 错误码对照表

表格
错误码说明处理建议
0成功-
10001参数错误检查必填参数及格式
10002签名错误核对签名算法及密钥
10003商品不存在或已下架确认商品 ID 有效性
10004接口调用频次超限降低请求频率,申请提额
10005权限不足检查应用权限范围
10006服务内部错误稍后重试或联系客服

五、实战代码示例

5.1 Python 完整调用示例

Python
复制
import requestsimport jsonimport timeimport hashlibfrom urllib.parse import urlencodeclass DouyinProductAPI:
    BASE_URL = "https://open.douyin.com"
    
    def __init__(self, app_key: str, app_secret: str):
        self.app_key = app_key
        self.app_secret = app_secret    
    def _generate_sign(self, params: dict) -> str:
        sorted_params = sorted(
            [(k, v) for k, v in params.items() if v is not None and k != 'sign']
        )
        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()).hexdigest().upper()
    
    def get_product_detail(self, product_id: str, fields: str = None) -> dict:
        """
        获取商品详情
        """
        params = {
            "app_key": self.app_key,
            "timestamp": int(time.time()),
            "product_id": product_id,
        }
        if fields:
            params["fields"] = fields
        
        params["sign"] = self._generate_sign(params)
        
        url = f"{self.BASE_URL}/api/product/detail"
        
        try:
            response = requests.get(
                url, 
                params=params, 
                timeout=10,
                headers={"Accept": "application/json"}
            )
            response.raise_for_status()
            result = response.json()
            
            if result.get("code") != 0:
                raise Exception(f"API Error: {result.get('message')}")
            
            return result["data"]
            
        except requests.exceptions.RequestException as e:
            raise Exception(f"Request failed: {str(e)}")# 使用示例if __name__ == "__main__":
    api = DouyinProductAPI(
        app_key="your_app_key",
        app_secret="your_app_secret"
    )
    
    try:
        product = api.get_product_detail(
            product_id="1234567890",
            fields="product_name,price_info,images,sales_info"
        )
        print(json.dumps(product, indent=2, ensure_ascii=False))
    except Exception as e:
        print(f"Error: {e}")

5.2 批量获取与并发控制

Python
复制
import asyncioimport aiohttpfrom typing import List, Dictclass DouyinProductBatchAPI(DouyinProductAPI):
    
    async def get_product_detail_async(
        self, 
        session: aiohttp.ClientSession, 
        product_id: str
    ) -> Dict:
        params = {
            "app_key": self.app_key,
            "timestamp": int(time.time()),
            "product_id": product_id,
        }
        params["sign"] = self._generate_sign(params)
        
        async with session.get(
            f"{self.BASE_URL}/api/product/detail",
            params=params,
            timeout=aiohttp.ClientTimeout(total=10)
        ) as response:
            result = await response.json()
            return result.get("data", {})
    
    async def batch_get_products(
        self, 
        product_ids: List[str], 
        max_concurrent: int = 10
    ) -> List[Dict]:
        """
        批量获取商品详情,带并发控制
        """
        semaphore = asyncio.Semaphore(max_concurrent)
        
        async def fetch_with_limit(session, pid):
            async with semaphore:
                return await self.get_product_detail_async(session, pid)
        
        async with aiohttp.ClientSession() as session:
            tasks = [fetch_with_limit(session, pid) for pid in product_ids]
            return await asyncio.gather(*tasks)# 批量调用示例async def main():
    api = DouyinProductBatchAPI("app_key", "app_secret")
    product_ids = ["111", "222", "333", "444", "555"]
    results = await api.batch_get_products(product_ids, max_concurrent=5)
    print(f"成功获取 {len(results)} 个商品信息")# asyncio.run(main())

六、关键注意事项

6.1 频率限制与限流策略

表格
限制类型默认值说明
QPS 限制10-100根据应用等级调整
日调用量1万-100万需申请提升额度
并发限制视接口而定建议设置熔断降级
最佳实践:
  • 使用令牌桶/漏桶算法进行客户端限流
  • 实现指数退避重试机制
  • 缓存热点商品数据(Redis,TTL 5-15分钟)

6.2 数据安全与合规

  1. 用户隐私:不得存储、传播用户敏感信息
  2. 数据用途:仅限授权范围内的业务使用
  3. 签名保护app_secret 严禁前端暴露或硬编码
  4. HTTPS 强制:所有请求必须使用 TLS 1.2+

6.3 价格单位处理

抖音接口中价格通常以为单位返回,使用时需转换:
Python
复制
def format_price(price_in_fen: int) -> str:
    """将分转换为元,保留两位小数"""
    return f"¥{price_in_fen / 100:.2f}"# 示例print(format_price(19900))  # 输出: ¥199.00

七、典型应用场景

表格
场景实现思路
商品比价系统定时同步多平台商品信息,建立价格监控
选品分析工具抓取销量、评价数据,生成选品报告
直播带货助手实时获取商品库存、价格,自动切换讲解
电商 ERP 对接同步订单、库存信息,实现统一管理
数据分析平台聚合商品数据,进行市场趋势分析

八、常见问题排查

Q1: 返回 "签名错误" 怎么办?
  • 检查参数是否按 ASCII 排序
  • 确认 app_secret 正确且无多余空格
  • 注意 timestamp 与服务器时间差不超过 5 分钟
Q2: 商品图片无法访问?
  • 抖音图片 URL 通常带防盗链,需通过合法渠道获取
  • 部分图片有有效期,建议下载后转存至自有 CDN
Q3: 如何获取历史价格?
  • 标准接口通常只返回当前价格,历史价格需自行记录
  • 可结合定时任务建立价格变动数据库


群贤毕至

访客