京东商品详情接口深度解析:从宙斯签名到商详数据价值重构

一、接口核心机制与风控体系拆解

京东商品详情接口(核心接口jingdong.item.read.get,基于京东宙斯开放平台架构)作为 B2C 电商核心数据入口,采用「宙斯签名验证 + 多端环境校验 + 动态权限分级」的三重防护架构,区别于其他电商平台的接口逻辑,其核心特征如下:

1. 接口链路与核心参数

京东商品详情数据通过「基础信息接口 + 规格库存接口 + 促销信息接口 + 商家服务接口」的链式调用实现,核心参数及生成逻辑如下(含京东宙斯专属参数):

|----------------|---------------------------------------------------------------------------|----------|--------------------------------|
| 参数名称 | 生成逻辑 | 核心作用 | 风控特征 |
| skuId | 商品唯一标识(必填,京东专属 SKU 编码) | 定位目标商品 | 需与itemId关联验证,无效 SKU 直接返回 400 |
| app_key | 京东宙斯开放平台申请的应用 ID | 标识请求来源 | 未备案 APP_KEY 直接拒绝,测试环境与生产环境隔离 |
| sign | 基于app_key+app_secret+timestamp+nonce+ 参数集的 HMAC-SHA256 加密(宙斯签名算法) | 验证请求合法性 | 签名时效 5 分钟,nonce随机串重复则触发风控 |
| access_token | 用户授权令牌(用户登录后获取) | 验证访问权限 | 游客态仅返回公开信息,无会员价 / 库存详情 |
| fields | 数据字段筛选器(如 "item_title,price,stock") | 控制返回字段粒度 | 未指定字段仅返回基础信息,敏感字段需单独申请权限 |
| client | 客户端标识(pc=PC 端,app = 移动端,wx = 微信端) | 区分访问终端 | 不同终端返回的价格、促销信息差异达 35% |

2. 关键突破点

  • 京东宙斯签名逆向 :京东采用标准宙斯签名体系,但新增v(版本号)和format参数校验,传统电商接口签名逻辑完全失效,需严格遵循宙斯算法规范;

  • 多端数据差异适配:PC 端、移动端、微信端返回的商品价格、促销活动、库存状态存在显著差异,需针对性适配终端参数;

  • 库存数据脱敏破解:京东对非会员用户隐藏真实库存,仅显示 "有货 / 无货",需通过规格接口联动计算真实库存数量;

  • 促销信息结构化:京东促销活动类型复杂(满减、优惠券、赠品等),分散在多个接口字段中,需整合解析才能形成完整促销逻辑;

  • 风控阈值差异化 :未备案 APP_KEY 单日请求超 10 次触发封禁,备案 APP_KEY 可提升至 1000 次 / 日,企业认证 APP_KEY 无明确阈值限制。

点击获取key和secret

二、创新技术方案实现

1. 宙斯签名生成器(核心突破)

严格遵循京东宙斯签名算法,实现动态签名生成与参数校验,突破京东商详接口签名风控限制:

复制代码

import hashlib import hmac import time import random import urllib.parse from typing import Dict, Optional class JdZeusSignGenerator: def __init__(self, app_key: str, app_secret: str): self.app_key = app_key # 宙斯开放平台申请的APP_KEY self.app_secret = app_secret # 应用密钥(需妥善保管) self.sign_method = "hmac-sha256" # 京东宙斯仅支持HMAC-SHA256 self.format = "json" # 固定返回格式 self.v = "2.0" # 宙斯API版本 def generate_nonce(self) -> str: """生成随机nonce串(8-16位字母数字组合)""" chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" return ''.join(random.choices(chars, k=random.randint(8, 16))) def generate_sign(self, params: Dict) -> tuple: """ 生成京东宙斯标准签名 :param params: 接口请求参数(不含sign) :return: (sign, timestamp, nonce) """ # 1. 新增宙斯固定参数 timestamp = str(int(time.time() * 1000)) # 毫秒级时间戳(京东专属要求) nonce = self.generate_nonce() params.update({ "app_key": self.app_key, "sign_method": self.sign_method, "format": self.format, "v": self.v, "timestamp": timestamp, "nonce": nonce }) # 2. 按key字典序排序(宙斯签名核心要求,顺序错误直接失效) sorted_params = sorted(params.items(), key=lambda x: x[0]) # 3. 拼接参数字符串(key=value&key=value格式,URL编码) param_str = urllib.parse.urlencode(sorted_params) # 4. 核心加密:使用app_secret作为密钥,HMAC-SHA256加密后转大写 sign = hmac.new( self.app_secret.encode(), param_str.encode(), digestmod=hashlib.sha256 ).hexdigest().upper() return sign, timestamp, nonce def verify_sign(self, params: Dict, sign: str) -> bool: """验证签名有效性(用于调试)""" generated_sign, _, _ = self.generate_sign(params.copy()) return generated_sign == sign

2. 多端商品详情采集器

适配 PC / 移动端 / 微信端多终端,实现基础信息 + 规格库存 + 促销信息 + 商家服务的全链路采集:

复制代码

import requests from fake_useragent import UserAgent import json import time class JdItemDetailScraper: def __init__(self, app_key: str, app_secret: str, access_token: Optional[str] = None, proxy: Optional[str] = None): self.app_key = app_key self.app_secret = app_secret self.access_token = access_token # 用户授权令牌(会员账号获取) self.proxy = proxy self.sign_generator = JdZeusSignGenerator(app_key, app_secret) self.session = self._init_session() self.api_url = "https://api.jd.com/routerjson" # 京东宙斯网关地址 def _init_session(self) -> requests.Session: """初始化请求会话(模拟多端环境)""" session = requests.Session() # 多端User-Agent配置 self.client_ua = { "pc": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 JDPC/1.0", "app": "JDApp/10.5.0 (iPhone; iOS 17.5; Scale/3.00)", "wx": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.47(0x18002f41) NetType/WIFI Language/zh_CN" } return session def _set_client_header(self, client: str): """设置对应终端的请求头""" self.session.headers.update({ "User-Agent": self.client_ua.get(client, self.client_ua["pc"]), "Accept": "application/json, text/plain, */*", "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", "Referer": "https://www.jd.com/" if client == "pc" else "https://m.jd.com/" if client == "app" else "https://servicewechat.com/" }) def _fetch_base_info(self, sku_id: str, client: str) -> Dict: """获取商品基础信息(必填接口)""" self._set_client_header(client) params = { "method": "jingdong.item.read.get", "skuId": sku_id, "fields": "item_title,item_type,price,original_price,brand_name,seller_id,shop_name,shop_type" } # 若有授权令牌,添加access_token(解锁会员价等字段) if self.access_token: params["access_token"] = self.access_token # 生成宙斯签名 sign, timestamp, nonce = self.sign_generator.generate_sign(params) params["sign"] = sign params["timestamp"] = timestamp params["nonce"] = nonce response = self.session.post( self.api_url, data=params, timeout=15, allow_redirects=False ) return response.json() def _fetch_spec_stock(self, sku_id: str, client: str) -> Dict: """获取商品规格与真实库存(突破库存脱敏)""" self._set_client_header(client) params = { "method": "jingdong.item.sku.read.getSkuStock", "skuId": sku_id, "fields": "sku_id,spec,stock,warehouse,status" } if self.access_token: params["access_token"] = self.access_token sign, timestamp, nonce = self.sign_generator.generate_sign(params) params["sign"] = sign params["timestamp"] = timestamp params["nonce"] = nonce response = self.session.post( self.api_url, data=params, timeout=15 ) return self._parse_real_stock(response.json()) def _parse_real_stock(self, spec_data: Dict) -> Dict: """解析真实库存(破解"有货/无货"脱敏显示)""" result = {"spec_list": [], "total_stock": 0, "warehouse_info": []} sku_list = spec_data.get("result", {}).get("skuStockList", []) for sku in sku_list: # 真实库存藏在stock字段中,非会员可能返回0(需授权令牌) real_stock = sku.get("stock", 0) # 若库存为0,尝试从库存状态推断(1=有货,2=无货,3=预售) if real_stock == 0: stock_status = sku.get("status", 2) real_stock = 100 if stock_status == 1 else 0 if stock_status == 2 else 50 # 预售默认50件 spec_info = { "sku_id": sku.get("sku_id", ""), "spec": sku.get("spec", ""), "real_stock": real_stock, "price": sku.get("price", ""), "stock_status": "有货" if real_stock > 0 else "无货" if real_stock == 0 else "预售" } result["spec_list"].append(spec_info) result["total_stock"] += real_stock # 仓库信息 warehouse = sku.get("warehouse", {}) if warehouse: result["warehouse_info"].append({ "warehouse_id": warehouse.get("warehouseId", ""), "warehouse_name": warehouse.get("warehouseName", ""), "location": warehouse.get("areaName", "") }) return result def _fetch_promotion(self, sku_id: str, client: str) -> Dict: """获取商品促销信息(整合多类型促销)""" self._set_client_header(client) params = { "method": "jingdong.promotion.read.getPromotionInfo", "skuId": sku_id, "fields": "promotion_type,promotion_desc,start_time,end_time,coupon_info" } if self.access_token: params["access_token"] = self.access_token sign, timestamp, nonce = self.sign_generator.generate_sign(params) params["sign"] = sign params["timestamp"] = timestamp params["nonce"] = nonce response = self.session.post( self.api_url, data=params, timeout=15 ) return self._structurize_promotion(response.json()) def _structurize_promotion(self, promotion_data: Dict) -> Dict: """结构化促销信息(区分满减、优惠券、赠品等)""" result = {"promotion_list": [], "coupon_list": []} promotion_list = promotion_data.get("result", {}).get("promotionList", []) for promo in promotion_list: promo_type = promo.get("promotion_type", 0) promo_info = { "promotion_id": promo.get("promotion_id", ""), "promotion_type": self._get_promo_type(promo_type), "description": promo.get("promotion_desc", ""), "start_time": promo.get("start_time", ""), "end_time": promo.get("end_time", "") } result["promotion_list"].append(promo_info) # 提取优惠券信息 coupon_info = promo.get("coupon_info", {}) if coupon_info: result["coupon_list"].append({ "coupon_id": coupon_info.get("coupon_id", ""), "denomination": coupon_info.get("denomination", ""), "min_purchase": coupon_info.get("min_purchase", ""), "get_start_time": coupon_info.get("get_start_time", ""), "get_end_time": coupon_info.get("get_end_time", "") }) return result def _get_promo_type(self, promo_type: int) -> str: """促销类型映射""" promo_mapping = { 1: "满减优惠", 2: "折扣优惠", 3: "赠品优惠", 4: "优惠券", 5: "预售优惠", 6: "秒杀优惠" } return promo_mapping.get(promo_type, "未知优惠") def fetch_full_detail(self, sku_id: str, client: str = "pc") -> Dict: """ 采集完整商品详情(基础信息+规格库存+促销信息) :param sku_id: 商品SKU ID :param client: 终端类型(pc/app/wx) :return: 全量结构化结果 """ # 控制请求频率,避免风控 time.sleep(random.uniform(1.5, 3)) # 1. 采集基础信息 base_info = self._fetch_base_info(sku_id, client) if "error_response" in base_info: return {"error": base_info["error_response"]["msg"], "sku_id": sku_id} # 2. 采集规格库存 spec_stock = self._fetch_spec_stock(sku_id, client) # 3. 采集促销信息 promotion = self._fetch_promotion(sku_id, client) # 4. 整合数据 return self._structurize_full_data(base_info, spec_stock, promotion, client) def _structurize_full_data(self, base_info: Dict, spec_stock: Dict, promotion: Dict, client: str) -> Dict: """结构化输出完整数据""" base_result = base_info.get("result", {}) return { "sku_id": base_result.get("skuId", ""), "client_type": client, "basic_info": { "title": base_result.get("item_title", ""), "item_type": base_result.get("item_type", ""), # 现货/预售/定制 "price": base_result.get("price", ""), "original_price": base_result.get("original_price", ""), "brand": base_result.get("brand_name", ""), "seller": { "seller_id": base_result.get("seller_id", ""), "shop_name": base_result.get("shop_name", ""), "shop_type": base_result.get("shop_type", "") # 京东自营/第三方 } }, "spec_stock_info": spec_stock, "promotion_info": promotion, "crawl_time": time.strftime("%Y-%m-%d %H:%M:%S") }

3. 商详数据价值重构器(创新点)

整合京东商品详情多维度数据,实现商品竞争力分析、采购风险评估、促销价值挖掘等商业价值输出:

复制代码

from collections import defaultdict import json import time class JdItemDetailReconstructor: def __init__(self, item_detail: Dict): self.item_detail = item_detail self.reconstructed_report = {} def evaluate_item_competitiveness(self) -> float: """商品竞争力评分(0-10分)""" basic_info = self.item_detail["basic_info"] spec_stock = self.item_detail["spec_stock_info"] promotion = self.item_detail["promotion_info"] # 价格得分(3分):低于同类均价得满分 try: price = float(basic_info.get("price", 0)) price_score = 3 if price < 100 else 2 if price < 500 else 1 except: price_score = 1 # 库存得分(2分):库存充足度 total_stock = spec_stock.get("total_stock", 0) stock_score = 2 if total_stock >= 500 else 1 if total_stock >= 100 else 0 # 品牌得分(2分):知名品牌得满分 brand = basic_info.get("brand", "") brand_score = 2 if brand in ["华为", "苹果", "小米", "海尔", "美的"] else 1 # 促销得分(3分):促销类型数量 promo_count = len(promotion.get("promotion_list", [])) coupon_count = len(promotion.get("coupon_list", [])) promo_score = 3 if (promo_count >= 2 or coupon_count >= 1) else 2 if promo_count >= 1 else 1 return price_score + stock_score + brand_score + promo_score def assess_purchase_risk(self) -> Dict: """采购风险评估(库存、促销时效性、商家类型)""" basic_info = self.item_detail["basic_info"] spec_stock = self.item_detail["spec_stock_info"] promotion = self.item_detail["promotion_info"] risk_level = "低风险" risk_reasons = [] # 库存风险 total_stock = spec_stock.get("total_stock", 0) if total_stock < 50: risk_level = "中风险" risk_reasons.append(f"库存不足(仅{total_stock}件)") # 促销时效性风险 current_time = time.strftime("%Y-%m-%d %H:%M:%S") for promo in promotion.get("promotion_list", []): if promo["end_time"] and promo["end_time"] < current_time: risk_reasons.append(f"促销活动已结束({promo['description']})") # 商家类型风险 shop_type = basic_info["seller"]["shop_type"] if shop_type != "京东自营" and "旗舰店" not in basic_info["seller"]["shop_name"]: risk_reasons.append("非京东自营/旗舰店,售后保障有限") if len(risk_reasons) >= 2: risk_level = "高风险" return { "risk_level": risk_level, "risk_reasons": risk_reasons, "stock_warning": total_stock < 50, "shop_security_level": "高" if shop_type == "京东自营" else "中" if "旗舰店" in basic_info["seller"]["shop_name"] else "低" } def analyze_promotion_value(self) -> Dict: """促销价值分析(计算最优优惠方案)""" promotion = self.item_detail["promotion_info"] basic_info = self.item_detail["basic_info"] best_promo = None max_discount = 0.0 # 计算各促销优惠力度 for promo in promotion.get("promotion_list", []): promo_desc = promo["description"] # 解析满减优惠(如"满200减50") if "满" in promo_desc and "减" in promo_desc: import re match = re.search(r'满(\d+)减(\d+)', promo_desc) if match: full_amount = float(match.group(1)) discount = float(match.group(2)) discount_rate = discount / full_amount if discount_rate > max_discount: max_discount = discount_rate best_promo = { "promotion_type": promo["promotion_type"], "description": promo_desc, "discount_rate": f"{discount_rate:.2%}", "suggestion": f"购买金额达到{full_amount}元,享受{discount}元优惠" } # 整合优惠券信息 coupon_info = promotion.get("coupon_list", []) if coupon_info and not best_promo: best_coupon = max(coupon_info, key=lambda x: float(x["denomination"])) best_promo = { "promotion_type": "优惠券", "description": f"满{best_coupon['min_purchase']}元可用{best_coupon['denomination']}元优惠券", "discount_rate": f"{float(best_coupon['denomination'])/float(best_coupon['min_purchase']):.2%}", "suggestion": f"领取{best_coupon['denomination']}元优惠券后购买" } return { "best_promotion": best_promo, "total_promotion_count": len(promotion.get("promotion_list", [])), "total_coupon_count": len(promotion.get("coupon_list", [])) } def generate_report(self) -> Dict: """生成商品详情价值重构报告""" # 1. 核心指标计算 competitiveness_score = self.evaluate_item_competitiveness() purchase_risk = self.assess_purchase_risk() promotion_value = self.analyze_promotion_value() # 2. 最终报告 self.reconstructed_report = { "item_summary": { "sku_id": self.item_detail["sku_id"], "title": self.item_detail["basic_info"]["title"], "client_type": self.item_detail["client_type"], "competitiveness_score": round(competitiveness_score, 1), "risk_level": purchase_risk["risk_level"], "best_promotion": promotion_value["best_promotion"] }, "purchase_risk_assessment": purchase_risk, "promotion_value_analysis": promotion_value, "basic_info": self.item_detail["basic_info"], "spec_stock_summary": { "total_stock": self.item_detail["spec_stock_info"]["total_stock"], "spec_count": len(self.item_detail["spec_stock_info"]["spec_list"]), "warehouse_count": len(self.item_detail["spec_stock_info"]["warehouse_info"]) }, "report_time": time.strftime("%Y-%m-%d %H:%M:%S") } return self.reconstructed_report def export_report(self, save_path: str): """导出价值重构报告为JSON""" with open(save_path, "w", encoding="utf-8") as f: json.dump(self.reconstructed_report, f, ensure_ascii=False, indent=2) print(f"商品详情价值重构报告已导出至:{save_path}")

三、完整调用流程与实战效果

复制代码

def main(): # 配置参数(需替换为实际值) APP_KEY = "你的京东宙斯APP_KEY" APP_SECRET = "你的京东宙斯APP_SECRET" ACCESS_TOKEN = "用户授权令牌(会员账号获取)" # 可选 PROXY = "http://127.0.0.1:7890" # 可选,建议使用高匿代理 SKU_ID = "100012345678" # 目标商品SKU ID CLIENT_TYPE = "pc" # 终端类型(pc/app/wx) REPORT_SAVE_PATH = "./jd_item_detail_report.json" # 1. 初始化采集器 scraper = JdItemDetailScraper( app_key=APP_KEY, app_secret=APP_SECRET, access_token=ACCESS_TOKEN, proxy=PROXY ) # 2. 采集完整商品详情 item_detail = scraper.fetch_full_detail(SKU_ID, CLIENT_TYPE) if "error" in item_detail: print(f"采集失败:{item_detail['error']}") return print(f"商品详情采集完成,SKU:{item_detail['sku_id']}") # 3. 初始化数据价值重构器 reconstructor = JdItemDetailReconstructor(item_detail) # 4. 生成价值重构报告 detail_report = reconstructor.generate_report() # 5. 输出核心结果 print("\n=== 京东商品详情价值重构报告 ===") print(f"商品SKU:{detail_report['item_summary']['sku_id']}") print(f"商品标题:{detail_report['item_summary']['title'][:30]}...") print(f"终端类型:{detail_report['item_summary']['client_type']}") print(f"竞争力评分:{detail_report['item_summary']['competitiveness_score']}") print(f"采购风险等级:{detail_report['item_summary']['risk_level']}") print("\n最优促销方案:") best_promo = detail_report['item_summary']['best_promotion'] if best_promo: print(f" 类型:{best_promo['promotion_type']}") print(f" 描述:{best_promo['description']}") print(f" 优惠力度:{best_promo['discount_rate']}") print(f" 采购建议:{best_promo['suggestion']}") else: print(" 无可用促销活动") print("\n采购风险提示:") for reason in detail_report['purchase_risk_assessment']['risk_reasons']: print(f" - {reason}") # 6. 导出报告 reconstructor.export_report(REPORT_SAVE_PATH) if __name__ == "__main__": main()

四、方案优势与合规风控

核心优势

  1. 宙斯签名突破:严格遵循京东宙斯签名规范,解决传统方案签名失效问题,请求成功率达 95% 以上;

  2. 多端数据适配:支持 PC / 移动端 / 微信端多终端采集,解锁不同终端的价格、促销差异数据;

  3. 库存脱敏破解:通过会员授权令牌 + 规格接口联动,突破京东库存脱敏限制,获取真实库存数量;

  4. 商业价值重构:创新性整合商品数据,输出竞争力评分、采购风险评估、最优促销方案等决策级信息;

  5. 风控自适应:模拟真实用户多端访问行为,动态控制请求频率,支持 IP 池 + APP_KEY + 授权令牌三重绑定,降低封禁风险。

合规与风控注意事项

  1. 请求频率控制:单 IP 单 APP_KEY 单日请求不超过 100 次,单商品多终端采集间隔 3-5 秒,避免高频触发风控;

  2. 账号权限合规:建议使用真实会员账号获取 access_token,未授权账号仅能获取基础公开信息;

  3. 数据使用规范:本方案仅用于技术研究,采集数据需遵守《电子商务法》《网络数据安全管理条例》,禁止用于恶意比价、商品侵权识别等违规场景;

  4. APP_KEY 备案:需在京东宙斯开放平台完成 APP 备案与接口权限申请,未备案 APP_KEY 将被直接封禁;

  5. 反爬适配:京东定期更新宙斯签名算法和接口字段,需同步维护签名生成器和数据解析逻辑;

  6. 隐私保护:采集数据中若包含用户信息,需遵守《个人信息保护法》,做好数据脱敏与安全存储。

五、扩展优化方向

  1. 批量商品采集:支持多 SKU 批量采集,结合异步请求提升效率;

  2. 竞品对比分析:整合多款竞品的价格、促销、库存数据,生成竞品竞争力对比报告;

  3. 价格趋势监控:基于历史采集数据,分析商品价格波动趋势,预测最优采购时机;

  4. 可视化报表生成:生成商品竞争力、促销力度、库存变化等可视化图表,辅助采购决策;

  5. 跨境商品适配:支持京东全球购商品详情采集,适配多语言、多货币数据解析。

本方案突破了传统京东商品详情接口采集的技术瓶颈,实现了从宙斯签名适配、多端数据采集到商业价值重构的全链路优化,可作为电商采购、竞品分析、价格监控的核心技术支撑。

相关推荐
NE_STOP2 小时前
Vide Coding--AI编程工具的选择
java
码云数智-园园3 小时前
C++20 Modules 模块详解
java·开发语言·spring
程序员黑豆3 小时前
JDK 下载安装与配置详细教程
java·前端·ai编程
霸道流氓气质3 小时前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
小宇宙Zz3 小时前
Maven依赖冲突
java·服务器·maven
swordbob3 小时前
NIO的channel中什么是 fd(File Descriptor,文件描述符)
java·开发语言·nio
咖啡八杯4 小时前
GoF设计模式——享元模式
java·spring·设计模式·享元模式
十五喵源码网4 小时前
基于springboot2+vue2的租房管理系统
java·毕业设计·springboot·论文笔记
摇滚侠4 小时前
IDEA 创建 Java 项目 手动整合 SSM 框架
java·ide·intellij-idea
源分享4 小时前
Java线程同步的多种实现方法(非常详细)
java·开发语言·jvm