基于 Python 实现淘宝京东商品数据 API 批量获取

在电商数据分析、竞品监控、选品优化、ERP系统对接等场景中,批量获取淘宝、京东平台的商品数据是高频需求。本文将从零开始,手把手教你用 Python 实现两大平台商品数据 API 的批量调用,涵盖前置准备、签名生成、代码封装、批量请求优化、数据解析全流程,提供可直接复制运行的代码,新手也能快速上手,避开平台调用坑点。

核心目标:通过 Python 封装淘宝、京东开放平台 API,实现多商品 ID 的批量数据抓取(支持商品标题、价格、库存、销量、图片等核心字段),解决批量调用中的限流、签名错误、数据解析混乱等常见问题,兼顾实用性和可扩展性。

一、前置准备(必做步骤)

批量调用淘宝、京东 API 的前提是完成开放平台的账号认证、应用创建和权限申请,这一步是基础,缺一不可,避免后续出现权限不足、签名失败等问题。

1.1 淘宝开放平台准备

  1. 注册并认证:访问 淘宝开放平台,注册开发者账号,完成个人/企业实名认证(企业认证可解锁更多接口权限,个人认证足够满足基础批量获取需求)。

  2. 创建应用:登录后进入「控制台」→「应用管理」→「新建应用」,填写应用名称、应用场景(如"电商数据采集"),提交审核(审核速度较快,一般1-2个工作日)。

  3. 获取核心参数:应用审核通过后,在应用详情页获取 AppKeyAppSecret(接口调用的核心凭证,请勿泄露)。

  4. 申请接口权限:在应用详情页→「接口管理」,搜索并申请以下两个核心接口(批量获取必备):

    1. taobao.item.get(单商品详情查询,基础接口,用于单个商品数据验证)

    2. taobao.item_get_batch(批量商品详情查询,核心接口,单次最多支持50个商品ID批量查询)

  5. 沙箱测试(可选):若担心正式环境调用出错,可开通沙箱环境,用沙箱账号、沙箱 AppKey 进行测试,避免触发正式环境限流。

1.2 京东开放平台准备

  1. 注册并认证:访问 京东开放平台(京东云·开放平台),注册开发者账号,完成实名认证。

  2. 创建应用:进入「开发者控制台」→「应用管理」→「创建应用」,选择应用类型(个人开发者选"第三方应用"),填写相关信息并提交审核。

  3. 获取核心参数:应用审核通过后,获取 AppKeyAppSecretAccessToken(京东 API 调用需额外获取 AccessToken,可通过平台提供的接口获取,有有效期,需定期刷新)。

  4. 申请接口权限:在应用详情页→「接口权限」,搜索并申请以下核心接口:

    1. jingdong.item.read.get(单商品详情查询,用于验证)

    2. jingdong.item.list.get(批量商品详情查询,核心接口,单次最多支持20个商品ID批量查询)

1.3 Python 环境准备

安装所需依赖库,直接执行以下命令(均为Python基础库,无需额外配置):

pip install requests # 发送HTTP请求,核心库 pip install jsonpath # 解析JSON数据(处理嵌套字段更便捷,可选) pip install tenacity # 实现重试机制,解决网络抖动、限流等问题

二、核心原理说明

淘宝、京东 API 调用的核心逻辑一致:构建请求参数 → 生成安全签名(防止请求被篡改) → 发送HTTP请求 → 解析返回的JSON数据 → 提取目标字段

关键注意点:

  • 签名机制:两大平台均要求对请求参数进行签名,签名规则略有差异,但核心都是"参数排序+密钥拼接+加密",下文代码已封装好签名逻辑,直接替换自己的参数即可。

  • 限流控制:淘宝、京东 API 均有调用频次限制(如淘宝基础接口每分钟最多100次,京东单次批量查询不超过20个ID),批量调用时需控制并发和请求间隔,避免触发限流(429错误)。

  • 数据格式:返回数据均为JSON格式,部分字段嵌套较深,需用JSONPath或原生索引提取,下文会提供两种解析方式。

三、完整代码实现(可直接复制运行)

本文采用"类封装"方式,将淘宝、京东 API 的调用逻辑分别封装为独立类,便于后续扩展和维护,支持批量传入商品ID、自动处理签名、异常捕获和重试,最终输出结构化商品数据(可直接保存为CSV/Excel)。

3.1 通用工具类(签名、重试、异常处理)

import requests import hashlib import time from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type from requests.exceptions import RequestException import jsonpath class ApiUtils: """通用API工具类:封装签名生成、重试机制、异常处理""" @staticmethod def generate_sign(params, app_secret, platform="taobao"): """ 生成淘宝/京东API签名(核心方法) :param params: 请求参数(字典) :param app_secret: 应用密钥(AppSecret) :param platform: 平台(taobao/jd) :return: 签名字符串 """ # 按参数名ASCII码升序排列(两大平台均要求) sorted_params = sorted(params.items(), key=lambda x: x[0]) # 拼接参数字符串 sign_str = app_secret + "".join([f"{k}{v}" for k, v in sorted_params]) + app_secret # MD5加密,转大写(两大平台签名加密方式一致) sign = hashlib.md5(sign_str.encode("utf-8")).hexdigest().upper() return sign @staticmethod @retry( stop=stop_after_attempt(3), # 最多重试3次 wait=wait_exponential(multiplier=1, min=1, max=5), # 指数退避:1s、2s、4s retry=retry_if_exception_type((RequestException, ConnectionError, TimeoutError)) ) def send_request(url, params=None, method="GET"): """ 发送HTTP请求,带重试机制 :param url: 请求地址 :param params: 请求参数 :param method: 请求方式(GET/POST) :return: 响应JSON数据 """ try: if method == "GET": response = requests.get(url, params=params, timeout=10) else: response = requests.post(url, data=params, timeout=10) response.raise_for_status() # 触发HTTP错误(如404、500) return response.json() except Exception as e: print(f"请求失败,原因:{str(e)},将进行重试") raise # 抛出异常,触发重试机制

3.2 淘宝API批量调用类

class TaobaoApiClient: def __init__(self, app_key, app_secret): """ 初始化淘宝API客户端 :param app_key: 淘宝AppKey :param app_secret: 淘宝AppSecret """ self.app_key = app_key self.app_secret = app_secret self.gateway = "https://eco.taobao.com/router/rest" # 淘宝API网关 self.common_params = { "app_key": self.app_key, "format": "json", "v": "2.0", "sign_method": "md5", "timestamp": time.strftime("%Y-%m-%d %H:%M:%S") # 实时时间戳 } def get_single_item(self, num_iid): """ 单个商品详情查询(用于验证) :param num_iid: 淘宝商品ID(从商品详情页URL提取) :return: 单个商品结构化数据 """ # 构建请求参数(公共参数+业务参数) params = { **self.common_params, "method": "taobao.item.get", "num_iid": num_iid, "fields": "num_iid,title,price,stock,volume,pic_url,brand,category" # 需返回的字段 } # 生成签名 params["sign"] = ApiUtils.generate_sign(params, self.app_secret, platform="taobao") # 发送请求 response = ApiUtils.send_request(self.gateway, params=params, method="GET") # 解析数据(处理异常场景) if "error_response" in response: raise Exception(f"淘宝API调用失败:{response['error_response']['msg']}") return self._parse_item_data(response["item"]) def batch_get_items(self, num_iids): """ 批量获取商品详情(核心方法) :param num_iids: 商品ID列表(最多50个) :return: 批量商品结构化数据列表 """ if len(num_iids) > 50: raise ValueError("淘宝批量查询单次最多支持50个商品ID") # 构建请求参数 params = { **self.common_params, "method": "taobao.item_get_batch", "item_ids": ",".join(num_iids), # 商品ID用逗号分隔 "fields": "num_iid,title,price,stock,volume,pic_url,brand,category" } # 生成签名 params["sign"] = ApiUtils.generate_sign(params, self.app_secret, platform="taobao") # 发送请求 response = ApiUtils.send_request(self.gateway, params=params, method="GET") # 解析数据 if "error_response" in response: raise Exception(f"淘宝批量API调用失败:{response['error_response']['msg']}") items = response.get("item_get_batch_response", {}).get("items", {}).get("item", []) return [self._parse_item_data(item) for item in items] @staticmethod def _parse_item_data(item): """解析商品数据,提取核心字段,返回结构化字典""" return { "platform": "taobao", "item_id": item.get("num_iid", ""), "title": item.get("title", ""), "price": float(item.get("price", 0.0)), # 价格转浮点数 "stock": int(item.get("stock", 0)), # 库存转整数 "sales": int(item.get("volume", 0)), # 销量转整数 "image_url": item.get("pic_url", ""), "brand": item.get("brand", ""), "category": item.get("category", "") }

3.3 京东API批量调用类

class JdApiClient: def __init__(self, app_key, app_secret, access_token): """ 初始化京东API客户端 :param app_key: 京东AppKey :param app_secret: 京东AppSecret :param access_token: 京东AccessToken(需定期刷新) """ self.app_key = app_key self.app_secret = app_secret self.access_token = access_token self.gateway = "https://api.jd.com/routerjson" # 京东API网关 self.common_params = { "app_key": self.app_key, "format": "json", "v": "2.0", "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), "access_token": self.access_token } def get_single_item(self, sku_id): """ 单个商品详情查询(用于验证) :param sku_id: 京东商品ID(从商品详情页URL提取) :return: 单个商品结构化数据 """ params = { **self.common_params, "method": "jingdong.item.read.get", "sku_id": sku_id, "fields": "sku_id,title,price,image_url,brand_info,category_info,sku_stock" } # 生成签名 params["sign"] = ApiUtils.generate_sign(params, self.app_secret, platform="jd") # 发送请求(京东API推荐用POST方式) response = ApiUtils.send_request(self.gateway, params=params, method="POST") # 解析数据 if "error_response" in response: raise Exception(f"京东API调用失败:{response['error_response']['msg']}") item = response.get("jingdong_item_read_get_response", {}).get("result", {}).get("item", {}) return self._parse_item_data(item) def batch_get_items(self, sku_ids): """ 批量获取商品详情(核心方法) :param sku_ids: 商品ID列表(最多20个) :return: 批量商品结构化数据列表 """ if len(sku_ids) > 20: raise ValueError("京东批量查询单次最多支持20个商品ID") params = { **self.common_params, "method": "jingdong.item.list.get", "sku_ids": ",".join(sku_ids), "fields": "sku_id,title,price,image_url,sku_stock" } # 生成签名 params["sign"] = ApiUtils.generate_sign(params, self.app_secret, platform="jd") # 发送请求 response = ApiUtils.send_request(self.gateway, params=params, method="POST") # 解析数据 if "error_response" in response: raise Exception(f"京东批量API调用失败:{response['error_response']['msg']}") items = response.get("jingdong_item_list_get_response", {}).get("result", {}).get("items", {}).get("item", []) return [self._parse_item_data(item) for item in items] @staticmethod def _parse_item_data(item): """解析京东商品数据,统一字段格式(与淘宝保持一致)""" return { "platform": "jd", "item_id": item.get("sku_id", ""), "title": item.get("title", ""), "price": float(item.get("price", 0.0)), "stock": int(item.get("sku_stock", 0)), "sales": 0, # 京东API需单独调用销量接口,此处暂设为0,可自行扩展 "image_url": item.get("image_url", ""), "brand": item.get("brand_info", {}).get("brand_name", ""), "category": item.get("category_info", {}).get("cid1_name", "") }

3.4 主程序(批量调用示例)

if __name__ == "__main__": # -------------------------- 配置参数(替换为自己的)-------------------------- # 淘宝配置 TAOBAO_APP_KEY = "你的淘宝AppKey" TAOBAO_APP_SECRET = "你的淘宝AppSecret" # 京东配置 JD_APP_KEY = "你的京东AppKey" JD_APP_SECRET = "你的京东AppSecret" JD_ACCESS_TOKEN = "你的京东AccessToken" # 批量商品ID(替换为自己需要查询的商品ID) TAOBAO_ITEM_IDS = ["520813250866", "123456789012", "987654321098"] # 最多50个 JD_ITEM_IDS = ["100012345678", "100087654321", "100098765432"] # 最多20个 try: # 1. 初始化客户端 taobao_client = TaobaoApiClient(TAOBAO_APP_KEY, TAOBAO_APP_SECRET) jd_client = JdApiClient(JD_APP_KEY, JD_APP_SECRET, JD_ACCESS_TOKEN) # 2. 批量获取淘宝商品数据 print("开始批量获取淘宝商品数据...") taobao_items = taobao_client.batch_get_items(TAOBAO_ITEM_IDS) print(f"淘宝商品数据获取完成,共{len(taobao_items)}个商品") # 3. 批量获取京东商品数据 print("\n开始批量获取京东商品数据...") jd_items = jd_client.batch_get_items(JD_ITEM_IDS) print(f"京东商品数据获取完成,共{len(jd_items)}个商品") # 4. 合并数据(可选),输出结构化结果 all_items = taobao_items + jd_items print("\n批量获取的所有商品数据:") for item in all_items: print(f"{item['platform']} | 商品ID:{item['item_id']} | 标题:{item['title']} | 价格:{item['price']}元 | 库存:{item['stock']}件") # 5. 保存数据到CSV(可选,便于后续分析) import csv with open("电商商品批量数据.csv", "w", encoding="utf-8-sig", newline="") as f: fieldnames = ["platform", "item_id", "title", "price", "stock", "sales", "image_url", "brand", "category"] writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() writer.writerows(all_items) print("\n数据已保存到:电商商品批量数据.csv") except Exception as e: print(f"程序执行失败:{str(e)}")

四、实战优化与避坑指南(重点)

很多开发者在批量调用 API 时,会遇到限流、签名错误、数据缺失等问题,以下优化方案和避坑点,能大幅提升程序稳定性和效率。

4.1 限流控制优化

  • 分批次调用:淘宝单次最多50个ID,京东单次最多20个ID,当需要查询的商品ID超过限制时,分批次调用,每批次之间添加间隔(如1-2秒),避免触发限流。 # 分批次处理京东商品ID(示例) ``jd_all_ids = ["100012345678", "100087654321", ...] # 假设100个ID ``batch_size = 20 # 京东单次最大批量数 ``for i in range(0, len(jd_all_ids), batch_size): `` batch_ids = jd_all_ids[i:i+batch_size] `` jd_items = jd_client.batch_get_items(batch_ids) `` time.sleep(1) # 每批次间隔1秒

  • 动态调整并发:若批量数据量极大(如1000个ID),可使用协程(aiohttp)实现并发调用,控制最大并发数(如30),提升效率的同时避免限流,具体代码可参考协程优化方案。

  • 限流后处理:若触发429限流错误,可通过响应头的X-RateLimit-Remaining字段,动态调整请求间隔和并发数,或添加更长时间的等待后重试。

4.2 常见坑点及解决方案

坑点 解决方案
签名错误(最常见) 1. 检查AppSecret大小写是否与平台一致;2. 确保参数字段按ASCII码升序排序;3. 时间戳与服务器时间差不超过5分钟;4. 避免参数值包含特殊字符(需URL编码)。
权限不足 1. 确认已申请对应接口权限;2. 个人认证接口权限有限,可升级为企业认证;3. 检查应用审核状态(需审核通过才能调用接口)。
数据解析失败(字段缺失) 1. 检查接口请求的fields参数,确保包含需要的字段;2. 部分商品可能缺失品牌、销量等字段,添加默认值(如0、空字符串);3. 复杂嵌套字段用JSONPath解析,避免索引报错。
AccessToken过期(京东专属) 1. 定期调用京东开放平台的token刷新接口,更新AccessToken;2. 在代码中添加token过期异常捕获,自动刷新并重新调用接口。
网络抖动导致请求失败 使用tenacity库实现重试机制,设置3-5次重试,指数退避等待,避免因临时网络问题导致程序中断。

4.3 功能扩展建议

  • 销量数据补充:京东API的基础批量接口不返回销量,可单独调用jingdong.sku.sales.get接口获取,整合到商品数据中。

  • 数据持久化:除了保存为CSV,可将数据存入MySQL、Redis等数据库,便于后续数据分析和查询。

  • 日志记录:添加日志模块(logging),记录每次API调用的状态、错误信息,便于问题排查。

  • 多平台适配:可扩展拼多多、亚马逊等其他电商平台的API调用,封装统一接口,实现多平台商品数据批量获取。

五、总结

本文完整实现了基于Python的淘宝、京东商品数据API批量获取,核心亮点的是:类封装设计便于扩展和维护,内置签名生成、重试机制、异常处理,解决了批量调用中的常见痛点,代码可直接复制替换参数运行,适合电商数据分析、竞品监控等多种场景。

需要注意的是,调用电商平台API时,需严格遵守平台的开发者规范,不得用于恶意爬取、违规数据采集等行为,避免应用被封禁。

如果在实际使用中遇到具体问题(如签名错误、权限申请、限流处理),可以在评论区留言,我会及时回复解答。

最后,觉得有用的话,记得点赞+收藏,关注我,后续会分享更多电商API实战、Python数据分析相关干货!

相关推荐
患得患失9492 小时前
【前端WebSocket】心跳功能,心跳重置策略、双向确认(Ping-Pong) 以及 指数退避算法(Exponential Backoff)
前端·websocket·算法
英俊潇洒美少年2 小时前
React 实现 AI 流式打字机对话:SSE 分包粘包处理 + 并发优化
前端·javascript·react.js
chQHk57BN2 小时前
前端测试入门:Jest、Cypress等测试框架使用教程
前端
数据知道2 小时前
claw-code 源码分析:大型移植的测试哲学——如何用 unittest 门禁守住「诚实未完成」的口碑?
开发语言·python·ai·claude code·claw code
Stella Blog2 小时前
狂神Java基础学习笔记Day01
java·笔记·学习
李白的天不白2 小时前
java处理跨域请求
java
遇见你...2 小时前
前端技术知识点
前端
炸炸鱼.2 小时前
Python 网络编程入门(简易版)
网络·python
云烟成雨TD2 小时前
Spring AI Alibaba 1.x 系列【11】Spring AI Models 扩展:DashScope
java·人工智能·spring
技术小黑2 小时前
TensorFlow学习系列10 | 数据增强
python·深度学习·tensorflow2