×

📦《京东商品详情API(jingdong.ware.read.get)Java/Python调用实战与JSON返回解析》(附Python源码)

万邦科技Lex 万邦科技Lex 发表于2026-07-02 09:24:14 浏览25 评论0

抢沙发发表评论

📦《京东商品详情API(jingdong.ware.read.get)Java/Python调用实战与JSON返回解析》(附Python源码)

京东POP商家/ISV获取商品(SPU/SKU)详情用 jingdong.ware.read.get(老版本也叫 360buy.ware.get),返回标题、价格、库存、SKU规格、主图、类目等结构化数据,官方免费额度内零成本,比爬京东商品页稳定且不触发风控。

一、接口关键信息

项目
说明
API Method
jingdong.ware.read.get(推荐)或旧版 jingdong.ware.get
网关
生产 https://api.jd.com/routerjson
沙箱 https://api.sandbox.jd.com/routerjson
必传
wareId(京东商品ID / wareId)、fields(指定返回字段,强烈建议显式传
可选
access_token(查自己店铺商品SKU库存需传卖家Token;公开字段可不传)
权限
应用→接口权限→申请 jingdong.ware.read.get
返回根
{jingdong_ware_read_get_response: {ware: {...}}}
⚠️ 京东 wareId≠ SKU ID,ware.read.get返回 SPU 信息 + skus数组(内含各 skuId/库存/规格)

二、Python完整调用封装(JOS签名 + 字段解析)

# jd_item_detail.py
"""
京东商品详情 API (jingdong.ware.read.get) 调用示例
依赖: requests  (pip install requests)
签名规则: MD5(AppSecret + KV_ASCII_sorted + AppSecret) → 大写
timestamp: 秒级(10位)  ← 与TOP不同!
"""
import hashlib
import json
import requests
from typing import Dict, List, Optional

# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
class JdItemClient:
    PROD = "https://api.jd.com/routerjson"
    SANDBOX = "https://api.sandbox.jd.com/routerjson"

    def __init__(self, app_key: str, app_secret: str, sandbox: bool = False):
        self.ak = app_key
        self.as_ = app_secret
        self.gw = self.SANDBOX if sandbox else self.PROD

    # ───── JOS MD5签名 ─────
    def _sign(self, params: Dict) -> str:
        filt = sorted((k, v) for k, v in params.items()
                       if v is not None and str(v).strip() != '' and k != 'sign')
        qs = ''.join(f"{k}{v}" for k, v in filt)
        raw = f"{self.as_}{qs}{self.as_}"
        return hashlib.md5(raw.encode('utf-8')).hexdigest().upper()

    def _call(self, method: str, biz: Dict, access_token: str = None) -> Dict:
        api_p = {
            "app_key": self.ak,
            "method": method,
            "timestamp": str(int(time.time())),   # ← 秒级!
            "format": "json",
            "v": "2.0",
            "sign_method": "md5",
            "360buy_param_json": json.dumps(biz, ensure_ascii=False, separators=(',', ':'))
        }
        if access_token:
            api_p["access_token"] = access_token
        api_p["sign"] = self._sign(api_p)

        r = requests.post(self.gw, data=api_p, timeout=15)
        r.raise_for_status()
        d = r.json()

        # 提取响应
        resp_key = method.replace(".", "_") + "_response"
        if resp_key not in d:
            for k in d:
                if k.endswith("_response"):
                    resp_key = k
                    break
        data = d.get(resp_key, d)

        # 错误检测
        if isinstance(data, dict) and "error_response" in str(data):
            err = d.get(resp_key, {}).get("error_response") or d.get("error_response")
            if err:
                raise Exception(
                    f"JOS [{err.get('code')}]: {err.get('zh_desc') or err.get('en_desc')} "
                    f"sub:{err.get('sub_code')}"
                )
            raise Exception(f"JOS unknown: {d}")
        return data

    # ───── 商品详情 ─────
    def get_ware_detail(self, ware_id: str,
                         fields: str = None,
                         access_token: str = None) -> Dict:
        """
        ware_id: 京东 SPU ID (wareId,不是 skuId)
        fields 推荐:
          "ware_id,title,item_num,brand_name,model,upc_code,cid,category,category_name,"
          "price,jd_price,market_price,stock_num,"
          "skus_json,image_path,desc,wrap,pack_list,param"
        """
        fields = fields or (
            "ware_id,title,brand_name,cid,category_name,"
            "price,jd_price,stock_num,"
            "skus_json,image_path,desc"
        )
        resp = self._call(
            "jingdong.ware.read.get",
            {"wareId": ware_id, "fields": fields},
            access_token=access_token
        )
        # 标准返回路径
        return resp.get("ware", resp)

    # ───── 解析 SKU 列表 ─────
    def parse_skus(self, ware: Dict) -> List[Dict]:
        """
        从 ware['skus_json'] (JSON字符串) 解析 SKU 数组
        """
        import json as _json
        skus_raw = ware.get("skus_json") or ""
        if not skus_raw:
            return []
        try:
            return _json.loads(skus_raw)
        except Exception:
            return []

# 封装好API供应商demo url=https://console.open.onebound.cn/console/?i=Lex
# =========================================================
# 使用示例
# =========================================================
if __name__ == "__main__":
    client = JdItemClient(
        app_key="YOUR_JD_APP_KEY",
        app_secret="YOUR_JD_APP_SECRET",
        sandbox=True   # 生产切 False;沙箱返回 mock ware_id 回显
    )

    WARE_ID = "100012345678"   # ← 替换真实京东 wareId

    try:
        ware = client.get_ware_detail(WARE_ID)
        print("✅ 商品标题:", ware.get("title"))
        print("   京东价 :", ware.get("jd_price"))
        print("   市场价 :", ware.get("price"))
        print("   主图   :", ware.get("image_path"))
        print("   库存(SPU汇总):", ware.get("stock_num"))

        skus = client.parse_skus(ware)
        print(f"   SKU数 : {len(skus)}")
        for s in skus[:3]:
            print(f"     skuId:{s.get('skuId')} 规格:{s.get('outerId','—')} "
                  f"价:{s.get('jdPrice')} 库:{s.get('stockNum')}")

        # ★ 查自己店铺SKU库存须传卖家 access_token
        # ware = client.get_ware_detail(WARE_ID, access_token="SELLER_ACCESS_TOKEN")

    except Exception as e:
        print("❌", e)
        print("→ 确认: AppKey/Secret正确、接口权限已申请、wareId有效")

三、关键返回字段解析(铺货/比价用)

JOS返回字段
含义
ERP映射
ware_id
SPU ID(京东商品ID)
外部货号 / 关联键
title
商品标题
商品名(裁剪适配平台)
jd_price
京东价(字符串)
零售价
price/ market_price
市场价/划线价
促销展示
stock_num
SPU级别库存(汇总)
参考;精确看SKU
skus_jsonskuId
子SKU ID
内部SKU匹配
skus_jsonouterId
商家编码
SKU对照
skus_jsonjdPrice
SKU京东价
多规格定价
skus_jsonstockNum
SKU可售库存(需seller token)
采购预警
image_path
主图URL
首图
cid/ category_name
后端类目ID / 名称
类目映射
desc
详情HTML(部分类目)
详情页
SKU 典型结构(解析自 skus_json字符串):
{
  "skuId": "1234567890",
  "outerId": "SKU-JD-RED-M",
  "jdPrice": "199.00",
  "stockNum": 50,
  "features": "color:红色;size:M"
}

四、Java调用核心片段(JOS Java SDK)

TaobaoClient client = new DefaultJdClient(
    "https://api.jd.com/routerjson",
    "APP_KEY", "APP_SECRET"
);

WareReadGetRequest req = new WareReadGetRequest();
req.setWareId(100012345678L);
req.setFields("ware_id,title,jd_price,stock_num,skus_json,image_path");

WareReadGetResponse rsp = client.execute(req);  // session传null查公开字段
Ware ware = rsp.getWare();

System.out.println(ware.getTitle());
System.out.println(ware.getJdPrice());
// skus_json → JSONArray 解析

五、避坑清单

现象
解决
timestamp invalid
用毫秒时间戳
JOS用秒级 int(time.time())
返回空 ware
wareId错 / 应用无权限
确认接口 jingdong.ware.read.get已申请
skus_json空 / stockNum0
公开查询不返SKU库存
卖家 AccessToken(OAuth授权)查自己店铺商品
fields不传
返回字段极少或隐式截断
显式传 fieldsskus_json,stock_num
沙箱返回 mock
正常
切生产网关看真实数据
sign mismatch
360buy_param_json值含空格或排序错
separators=(',',':')紧凑JSON,空值剔除再签名

六、面试/方案一句话

京东商品详情用 jingdong.ware.read.get(wareId, fields含skus_json)获取,JOS签名 MD5(AppSecret+KV_ASCII+AppSecret) 用秒级时间戳;公开字段可不传 session,查自己店铺 SKU 库存/商家编码须传卖家 OAuth AccessTokenskus_json是 JSON 字符串需二次解析得各 SKU 规格与库存。
需要我补 京东订单增量同步(jingdong.pop.order.search) APScheduler脚本(断点续跑+Token刷新)京东→1688/抖音铺货字段映射模板 吗?


群贤毕至

访客