×

api开发 电商平台 数据挖掘

Step-by-Step: 接入淘宝商品详情 API 并解析返回数据

admin admin 发表于2025-08-28 15:56:23 浏览29 评论0

抢沙发发表评论

在电商数据采集场景中,商品列表数据仅能满足基础分析需求,若需深入获取商品规格、详情描述、售后政策等精细化信息,必须接入淘宝商品详情 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:仅返回商品详情页的描述内容(如图文介绍),适合 “仅需详情描述” 的轻量场景。

权限申请步骤:

  1. 登录,

  2. 在 “接口管理” 中搜索 “taobao.item_get”;

  3. 点击 “申请权限”。

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 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>



少长咸集

群贤毕至

访客