×

🏪 淘宝店铺全量商品列表API批量拉取:参数配置・分页・限流处理(附Python源码)

万邦科技Lex 万邦科技Lex 发表于2026-06-22 09:11:06 浏览31 评论0

抢沙发发表评论

🏪 淘宝店铺全量商品列表API批量拉取:参数配置・分页・限流处理(附Python源码)

淘宝开放平台获取店铺商品用 taobao.items.onsale.get(在售)taobao.items.inventory.get(仓库中)。全量同步的核心难点是正确翻页 + QPS限速 + 字段过滤,下面给你生产可直接用的封装。

一、接口速览

项目
说明
API
taobao.items.onsale.get(在售)
taobao.items.inventory.get(库存/下架)
网关
生产 https://gw.api.taobao.com/router/rest
必传
page_no, page_size, fields
建议page_size
40~100(最大100),全量同步设100减少请求数
权限
需卖家授权(session/AccessToken),且应用申请对应接口权限
返回
items数组 + total_results
⚠️ 必须用卖家自身AccessToken调用,不能用买家账号查别人店铺全量商品(淘宝隐私限制)。第三方ISV需商户授权后查其店铺。

二、Python:全量分页拉取 + 令牌桶限速 + 限流重试

# top_items_batch.py
"""
淘宝店铺全量商品批量拉取
依赖: top_api_client.py 中的 TaobaoTopClient
"""
import time
from typing import List, Dict, Generator
from top_api_client import TaobaoTopClient
# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex

class _TokenBucket:
    def __init__(self, rate=5, cap=None):
        self.rate = rate
        self.cap = cap or int(rate)
        self.tok = float(self.cap)
        self.ts = time.monotonic()

    def wait(self):
        now = time.monotonic()
        self.tok = min(self.cap, self.tok + (now - self.ts) * self.rate)
        self.ts = now
        if self.tok >= 1:
            self.tok -= 1
            return
        time.sleep((1 - self.tok) / self.rate + 0.01)
        self.tok = 0


class TopShopItemsSyncer:
    """
    店铺商品全量同步器
    默认查【在售】,inventory=True 查仓库中
    """

    def __init__(self, app_key: str, app_secret: str,
                 session: str, sandbox=False, qps=5):
        self.client = TaobaoTopClient(app_key, app_secret,
                                      sandbox=sandbox)
        self.session = session
        self.bucket = _TokenBucket(rate=qps)

    def iter_all_items(self,
                       fields: str = None,
                       page_size: int = 100,
                       inventory: bool = False,
                       max_pages: int = 500) -> Generator[Dict, None, None]:
        """
        生成器逐条yield商品item,自动翻页至结束
        """
        method = "taobao.items.inventory.get" if inventory else "taobao.items.onsale.get"
        fields = fields or (
            "num_iid,title,price,num,pic_url,outer_id,cid,"
            "approve_status,list_time,modified"
        )
        page_no = 1
        total = None

        while page_no <= max_pages:
            self.bucket.wait()   # ← QPS控制

            try:
                result = self.client.call(
                    method,
                    biz_params={
                        "page_no": page_no,
                        "page_size": min(page_size, 100),
                        "fields": fields
                    },
                    session=self.session
                )
            except Exception as e:
                # TOP限流 code=7 / SubMsg=ISP_FLOW_CONTROL
                if "FLOW_CONTROL" in str(e) or "code=7" in str(e):
                    print(f"⚠️  限流!等待3s后退页重试 p{page_no}")
                    time.sleep(3)
                    continue
                raise

            items = result.get("items", []) or []
            if total is None:
                total = int(result.get("total_results", 0))
                print(f"📦 店铺共有商品 {total} 件,开始全量同步...")

            for it in items:
                yield it

            # 翻页判断
            if not items or (page_no * page_size >= total):
                break
            page_no += 1

    # ───────── 便捷:一次返回列表 ─────────
    def fetch_all(self, **kwargs) -> List[Dict]:
        return list(self.iter_all_items(**kwargs))


# =========================================================
# 使用示例
# =========================================================
if __name__ == "__main__":
    syncer = TopShopItemsSyncer(
        app_key="YOUR_TOP_APP_KEY",
        app_secret="YOUR_TOP_APP_SECRET",
        session="YOUR_SELLER_ACCESS_TOKEN",  # ← 卖家OAuth授权所得
        sandbox=True,   # 生产切 False
        qps=5           # 淘宝默认约 5~10/s 免费,留余量
    )

    try:
        count = 0
        for item in syncer.iter_all_items(
                fields="num_iid,title,price,num,outer_id,approve_status",
                page_size=100
        ):
            count += 1
            if count <= 3:
                print(f"  • {item.get('num_iid')} {item.get('title')} ¥{item.get('price')} 库:{item.get('num')}")
            if count == 4:
                print("  ...")

        print(f"\n✅ 全量同步完成,共 {count} 件商品")

    except Exception as e:
        print("❌", e)

三、关键参数说明与避坑

▶ 分页正确姿势

# 终止条件(必须!)
if len(items) == 0 or page_no * page_size >= total_results:
    break
只靠 len(items)<page_size判断可能在末页恰好满页时死循环,一定要用 total_results

▶ fields 务必指定

不传 fields或传 *会返回大量字段拖慢速度 → 触发隐性限流。
推荐最小集:num_iid,title,price,num,pic_url,outer_id,approve_status

▶ QPS 建议

应用类型
免费QPS
建议令牌桶值
自用型(企业)
≈5~10/s
rate=5
ISV(增值包)
更高
按购买值×0.8
超QPS返回 code=7, ISP_FLOW_CONTROL_LIMIT→ 捕获后 sleep(2~5)同页重试(上面代码已实现)。

▶ session 必传

此接口查当前授权店铺,必须用卖家AccessToken(OAuth2授权码换),买家token会返回无权限。

四、返回关键字段映射(同步ERP用)

TOP字段
ERP含义
备注
num_iid
外部商品ID
与1688 offerId同理做唯一键
outer_id
商家编码/SKU
内部货号,有则优先匹配
title
商品名
裁剪适配平台长度
price
一口价(字符串)
Decimal转换
num
库存
仅自己店铺可见
approve_status
onsale/instock
过滤下架
cid
后台类目ID
类目映射

五、全量 + 增量同步建议

每日凌晨:
  ① 全量翻页(this script)→ upsert ERP商品表
     WHERE approve_status='onsale'

  ② 增量(可选):调 taobao.items.onsale.get 按 modified 筛选近1天
     → 更新变动商品(减少翻页量)

六、一句话总结(面试版)

淘宝店铺全量商品用 taobao.items.onsale.get+ fields指定字段 + 按 total_results判断终止翻页;必须用卖家AccessToken调用;客户端加令牌桶QPS≤免费上限,遇限流(code=7)同页退避重试,避免触发封禁。
需要我补 TOP OAuth2授权码换AccessToken完整Python代码淘宝→1688/抖音/Shopify铺货字段映射模板 吗?


群贤毕至

访客