当前位置: 首页 > news >正文

京东比价项目开发实录:京东API接口(2025)

在电商开发的修罗场里摸爬滚打这些年,和京东商品详情 API 接口的 “较量” 堪称一部跌宕起伏的奋斗史。从申请权限时的层层关卡,到数据解析时的各种 “暗礁”,今天就把这段实战经历掰开揉碎,配上亲测有效的代码,给大伙避避雷!

还记得第一次对接京东 API,天真地以为和其他平台大同小异。结果光是申请开发者权限就碰了一鼻子灰 —— 京东对企业资质审核极为严格,营业执照、ICP 备案、应用场景说明反复修改了三轮,整整一周才收到通过通知。好不容易拿到App KeyApp Secret,签名算法又成了拦路虎。京东采用的 HMAC-SHA256 加密方式,对参数拼接顺序、URL 编码要求近乎苛刻,稍有差错就返回10001签名错误。那段时间熬夜翻看官方文档、GitHub 示例,终于啃出了签名生成函数:

python

运行

import hashlib
import hmac
import time
import urllib.parsedef generate_signature(params, app_secret):sorted_params = sorted(params.items(), key=lambda x: x[0])query_str = ""for k, v in sorted_params:if isinstance(v, list):v = ",".join(map(str, v))query_str += f"{k}{v}"sign_str = f"{app_secret}{query_str}{app_secret}"return hmac.new(app_secret.encode('utf-8'),sign_str.encode('utf-8'),hashlib.sha256).hexdigest().upper()# 使用示例
api_params = {"method": "jd.union.open.goods.query","app_key": "your_app_key","keyword": "手机","timestamp": str(int(time.time()))
}
signed_params = generate_signature(api_params, "your_app_secret")

解决了签名问题,新的 “坑” 接踵而至。京东对 API 调用频率限制十分严格,不同接口还有差异化限流策略。为了避免触发封禁,我用 Python 的asyncio结合信号量,实现了异步请求与限流控制:

python

运行

import asyncio
import aiohttpclass RateLimiter:def __init__(self, rate_limit):self.semaphore = asyncio.Semaphore(rate_limit)async def limit(self):async with self.semaphore:yieldasync def fetch_product_detail(session, sku_id, signed_params):async with RateLimiter(10).limit():url = "https://api.jd.com/routerjson"params = {**signed_params, "sku_id": sku_id}async with session.get(url, params=params) as response:return await response.json()async def main(sku_ids, signed_params):async with aiohttp.ClientSession() as session:tasks = [fetch_product_detail(session, sku, signed_params) for sku in sku_ids]results = await asyncio.gather(*tasks)return results# 示例调用
sku_ids = ["123456789", "987654321"]
signed_params = {...}  # 已签名参数
asyncio.run(main(sku_ids, signed_params))

python数据实例


"stock": {"skuId": "100031963708","realSkuId": "100031963708","ArrivalDate": "","Drd": "","sidDely": 182,"promiseResult": "20:00前付款,预计<b>明天(07月02日)</b>送达","isJDexpress": false,"StockState": 33,"rn": -1,"code": 1,"weightValue": "0.055kg","fxgCode": "0","afsCode": 1,"ir": [{"iconSrc": "京准达","iconTip": "选择京准达服务,可指定精确时间点收货;若京东责任超时,即时赔付","helpLink": "//help.jd.com/user/issue/103-983.html","iconCode": "sendpay_zhun","resultCode": 1,"showName": "京准达","picUrl": "http://m.360buyimg.com/mobilecms/jfs/t3172/266/1698067915/1634/64a0c40e/57d25fcfNd9c62bb7.png","iconType": 0,"iconServiceType": 1},{"iconSrc": "211限时达","iconTip": "上午下单,下午送达","helpLink": "https://help.jd.com/user/issue/91-953.html","iconCode": "sendpay_211","resultCode": 1,"showName": "211限时达","picUrl": "//static.360buyimg.com/item/assets/picon/zhongbiao.png","iconType": 0,"iconServiceType": 1},{"iconSrc": "明日达","iconTip": "指定时间前下单,最快明日达","helpLink": "//help.jd.com/user/issue/103-983.html","iconCode": "sendpay_nextday","resultCode": 1,"showName": "明日达","picUrl": "//static.360buyimg.com/item/assets/picon/zhongbiao.png","iconType": 0,"iconServiceType": 1},{"iconSrc": "预约送货","iconTip": "京东物流为该商品提供预约送货服务","helpLink": "//help.jd.com/user/issue/103-983.html","iconCode": "service_yysh","resultCode": 1,"showName": "预约送货","picUrl": "https://m.360buyimg.com/babel/jfs/t1/116316/15/7402/1031/5ec22ca4E713f857c/dd49784b20933cf5.png","iconType": 0,"iconServiceType": 6},{"iconSrc": "部分收货","iconTip": "如果收件人收货时发现部分货物存在缺少配件、物流损等情形,京东物流提供订单半收服务","helpLink": "https://help.jd.com/user/issue/103-983.html","iconCode": "service_bfsh","resultCode": 1,"showName": "部分收货","picUrl": "https://m.360buyimg.com/babel/jfs/t1/108073/34/18517/1071/5ec22ce0E11a3b1c5/f8ffea5f4cafa0f9.png","iconType": 0,"iconServiceType": 6},{"iconSrc": "送货上门","iconTip": "京东快递为您提供送货上门服务","helpLink": "https://help.jd.com/user/issue/254-4130.html","iconCode": "service_sssm","resultCode": 1,"showName": "送货上门","picUrl": "https://m.360buyimg.com/babel/jfs/t1/115738/37/12143/1066/5f0c7d11E4faee520/de3879572e2b2014.png","iconType": 0,"iconServiceType": 6},{"iconSrc": "59元免基础运费","iconTip": "所选地址自营订单满59元免基础运费(20kg内),超出重量加收1元/kg续重运费。","helpLink": "//help.jd.com/user/issue/103-983.html","iconCode": "free_delivery_zhong","resultCode": 1,"showName": "59元免基础运费","picUrl": "//static.360buyimg.com/item/assets/picon/mianyunfei.png","iconType": 0,"iconServiceType": 4},{"iconSrc": "京东物流","iconTip": "京东物流为您提供仓配一体供应链服务","helpLink": "https://help.jd.com/user/issue/list-81.html","iconCode": "service_jdwl","resultCode": 1,"showName": "京东物流","picUrl": "https://m.360buyimg.com/babel/jfs/t1/130756/9/11972/4289/5f8674d3Eabfebbef/bb964241bd789a72.png","iconType": 0,"iconServiceType": 4},{"iconSrc": "7天价保","iconTip": "在下单或签收7天内,商品出现降价可享受价保服务,部分特殊场景不支持价保,可点击”>"了解详细规则","helpLink": "https://help.jd.com/user/issue/291-548.html","iconCode": "service_guominwuyou","resultCode": 1,"showName": "7天价保","picUrl": "https://m.360buyimg.com/babel/jfs/t1/85923/26/10113/3475/5e144da1Ef978a914/d3d44f85b4221cf6.png","iconType": 0,"iconServiceType": 3},{"iconSrc": "自提","iconTip": "我们提供多种自提服务,包括京东自提点、自助提货柜、京东校园派、京东星配站、京东便民站等服务","helpLink": "//help.jd.com/user/issue/103-983.html","iconCode": "special_ziti","resultCode": 1,"showName": "自提","picUrl": "//static.360buyimg.com/item/assets/picon/shoutixiang.png","iconType": 0,"iconServiceType": 5}],"promiseYX": {"iconSrc": "7天无理由退货","iconTip": "支持7天无理由退货","helpLink": "http://help.jd.com/user/issue/126-3780.html","iconCode": "service_qitiantuihuo","resultCode": 1,"showName": "7天无理由退货","picUrl": "","iconType": 0,"iconServiceType": 3},"self_D": {"venderId": 1000085871,"colType": 0,"shopId": 1000085871,"shopName": "zippo京东自营旗舰店","vender": "zippo京东自营旗舰店","hotLine": "","shopWebsite": "http://zippo.jd.com","po": true,"url": "//zippo.jd.com"},"serviceInfo": "由<spanclass=hl_red>京东</span>发货,<ahref=zippo.jd.comclstag=shangpin|keycount|product|bbtnclass=hl_red>zippo京东自营旗舰店</a>提供售后服务","sid": 182,"preStore": -1,"unifiedServiceTag": {"enable": true,"freightIconCodes": ["free_delivery","free_delivery_zhong","free_delivery_fresh","free_delivery_fresh_zhong","Free_nbaoyou","Free_nsxbaoyou","free_baoyou","free_sxbaoyou"],"iconServiceTypes": ["1","5","6"],"tsfw": [{"code": "s26","desc": "在下单或签收7天内,商品出现降价可享受价保服务(商品在消费者下单后因参与百亿补贴、政府补贴等活动导致降价不支持价保),可点击“>”了解详细规则","helpUrl": "https://ihelp.jd.com/l/help/scene/getSceneDetail?id=337318","logoUrl": "//m.360buyimg.com/babel/jfs/t1/166785/27/4308/10074/60113548Ea9bb7dbb/be0bac01dccf5f52.png","name": "7天价保","shortDesc": "7天内买贵退差价","iHelpLink": "https://ihelp.jd.com/l/help/scene/getSceneDetail?id=325798","ihelpLink": "https://ihelp.jd.com/l/help/scene/getSceneDetail?id=325798","mimgUrl": "//m.360buyimg.com/babel/jfs/t1/222474/40/8926/4033/61de8162E9b3a5a0c/b11a4cc5342015b0.png","mimgUrl2": "//m.360buyimg.com/lme/jfs/t1/222228/21/20461/3101/63048db5Ef37ece2e/83f0be5658b2f25b.png"},{"code": "s141","desc": "由京东指定供应商提供售后服务","name": "供应商售后","shortDesc": "京东指定供应商售后"

python

运行

def parse_product_data(raw_data):try:return {"product_name": raw_data.get("wareInfo", {}).get("wareName", ""),"current_price": float(raw_data.get("wareInfo", {}).get("jdPrice", 0)),"original_price": float(raw_data.get("wareInfo", {}).get("marketPrice", 0)),"stock": int(raw_data.get("wareInfo", {}).get("stockNum", 0)),"brand": raw_data.get("wareInfo", {}).get("brandName", "")}except KeyError as e:print(f"字段缺失: {e}")return {}# 示例调用
raw_response = {...}  # API返回数据
parsed_data = parse_product_data(raw_response)

最惊险的一次,帮客户开发商品比价系统时,突然遇到京东接口升级,原本正常的 “商品副标题” 字段被替换成了 “shortTitle”。由于没有做字段兼容性处理,导致前端页面大量数据缺失。吃一堑长一智,后来每次调用 API 都会写版本兼容函数,动态适配字段变化:

python

运行

def adapt_data_fields(data):if "wareName" in data.get("wareInfo", {}):data["wareInfo"]["product_title"] = data["wareInfo"].pop("wareName")if "jdPrice" in data.get("wareInfo", {}):data["wareInfo"]["current_price"] = data["wareInfo"].pop("jdPrice")return data# 示例调用
adapted_data = adapt_data_fields(raw_response)

这些年踩过的坑、写过的代码,都成了宝贵的经验。如果有遇到其他问题都可以一起交流!

http://www.dtcms.com/a/331617.html

相关文章:

  • AI Agent 为什么需要记忆?
  • 我的 LeetCode 日记:Day 37 - 解锁动态规划:完全背包问题
  • 深度解析 Vue 高阶技巧:提升工程化能力的实用方案
  • 使用EvalScope对GPT-OSS-20B进行推理性能压测实战
  • Flink中的水位线
  • STL容器详解:Vector高效使用指南
  • 高效Unicode字符表示:一种创新的词表构建策略分析
  • MCP智能化问答系统实现方案
  • K8S企业级应用与DaemonSet实战解析
  • 【车联网kafka】用钟表齿轮理解 Kafka 时间轮​(第七篇)
  • Java应用快速部署Tomcat指南
  • # 2025全球AI游戏市场研究报告:行业洞察与未来趋势
  • OpenAI 的浏览器将使用 ChatGPT Agent 来控制浏览器
  • 亚马逊FCF计划:破解高单价产品转化困局的金融杠杆
  • RH134 管理基本存储知识点
  • 考研408《计算机组成原理》复习笔记,第四章(1)——指令系统概念(指令字长、N地址指令、定长和变长操作码)
  • H.264编码格式详解:Annex-B vs AVCC
  • 14、Docker Compose 安装 Redis 集群(三主三从)
  • 嵌入式学习笔记--MCU阶段--DAY12实时操作系统rt_thread1
  • Cypher注入详解:原理、类型与测试方法
  • 使用免费API开发口播数字人
  • 数智化与全球化,双轮驱动艾芬达持续引领行业变革
  • 嵌入式 - Linux软件编程:进程
  • PIDGenRc函数中lpstrRpc的由来和InitializePidVariables函数的关系
  • 什么是期权ETF分仓的意思呢?
  • 安全加固4(K8S最小化微服务安全)
  • java-JVM详解
  • 如何安装 scikit-learn Python 库
  • Azure微软云内网接入问题
  • 大规模调用淘宝商品详情 API 的分布式请求调度实践