京东 item_get_app 接口深度分析及 Python 实现

简介: 京东item_get_app接口可获取商品原始详情数据,包含更丰富的字段和细节,适用于电商分析、价格追踪等场景。需通过认证获取权限,支持字段筛选和区域化数据查询。

京东的 item_get_app 接口是用于获取商品原始详情数据的核心接口,与普通的 item_get 接口相比,它返回的数据更贴近京东 APP 端展示的原始结构,包含更丰富的字段和细节信息。这些原始数据对于深度电商分析、竞品监控、价格追踪等场景具有重要价值。
一、接口核心特性分析

  1. 接口功能与定位
    核心功能:获取京东商品的原始详情数据,包括商品基础信息、价格体系、库存状态、规格参数、促销活动等完整字段
    数据特点:
    与京东 APP 端数据结构一致,保留原始字段名和层级关系
    包含普通接口不返回的内部标识和计算参数
    实时性高,反映当前商品的最新状态
    字段丰富,包含算法推荐、权重参数等内部信息
    应用场景:
    深度电商数据分析系统
    商品全生命周期监控
    价格变动实时追踪
    竞品全方位对比分析
    电商大数据挖掘与研究
  2. 认证机制
    京东开放平台采用 appkey + access_token 的认证方式:
    开发者在京东开放平台注册应用,获取 appkey 和 appsecret
    通过 appkey 和 appsecret 获取 access_token(通常有效期为 24 小时)
    每次接口调用需在请求参数中携带有效 access_token
    item_get_app 属于高级接口,需要单独申请权限
  3. 核心参数与响应结构
    请求参数
    参数名 类型 是否必填 说明
    sku_id String 是 商品 SKU ID,京东商品的唯一标识
    access_token String 是 访问令牌
    platform String 否 平台类型,如 "android"、"ios",默认 "android"
    fields String 否 需要返回的字段,默认返回全部字段
    area String 否 地区编码,用于获取区域化价格和库存
    响应核心字段
    商品基础信息:SKU ID、商品名称、品牌信息、分类信息等
    价格信息:基准价、促销价、会员价、活动价、价格计算规则等
    库存信息:实时库存、区域库存、库存状态、限购信息等
    规格参数:SKU 规格、属性组合、规格图片等
    促销信息:活动列表、优惠券、满减规则、赠品信息等
    服务信息:售后政策、配送服务、安装服务等
    多媒体信息:图片、视频、3D 模型等资源链接
    二、Python 脚本实现
    以下是调用京东 item_get_app 接口的完整 Python 实现,包含令牌获取、接口调用、数据解析等功能:
    import requests
    import time
    import json
    import logging
    import hashlib
    from typing import Dict, Optional, List
    from requests.exceptions import RequestException

配置日志

logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)

class JDItemGetAppAPI:
def init(self, appkey: str, appsecret: str):
"""
初始化京东商品详情原数据API客户端
:param appkey: 京东开放平台appkey
:param appsecret: 京东开放平台appsecret
"""
self.appkey = appkey
self.appsecret = appsecret
self.base_url = "https://api.jd.com"
self.access_token = None
self.token_expires_at = 0 # token过期时间戳
self.session = requests.Session()
self.session.headers.update({
"Content-Type": "application/json",
"User-Agent": "JDApp;android;9.5.4;android 10;scale/3.0" # 模拟京东APP请求头
})

def _get_access_token(self) -> Optional[str]:
    """获取访问令牌"""
    # 检查token是否有效
    if self.access_token and self.token_expires_at > time.time() + 60:
        return self.access_token

    logging.info("获取新的access_token")
    url = f"{self.base_url}/oauth2/token"

    params = {
        "grant_type": "client_credentials",
        "appkey": self.appkey,
        "appsecret": self.appsecret
    }

    try:
        response = self.session.get(url, params=params, timeout=10)
        response.raise_for_status()
        result = response.json()

        if "access_token" in result:
            self.access_token = result["access_token"]
            self.token_expires_at = time.time() + result.get("expires_in", 86400)  # 默认为24小时
            return self.access_token
        else:
            logging.error(f"获取access_token失败: {result.get('error_description', '未知错误')}")
            return None

    except RequestException as e:
        logging.error(f"获取access_token请求异常: {str(e)}")
        return None

def get_item_raw_data(self, 
                     sku_id: str, 
                     platform: str = "android",
                     area: str = "1_72_2799_0",  # 默认地区编码:北京
                     fields: Optional[str] = None) -> Optional[Dict]:
    """
    获取商品原始详情数据
    :param sku_id: 商品SKU ID
    :param platform: 平台类型
    :param area: 地区编码
    :param fields: 需要返回的字段
    :return: 商品原始数据
    """
    # 验证参数
    valid_platforms = ["android", "ios"]
    if platform not in valid_platforms:
        logging.error(f"无效的平台类型: {platform},支持: {valid_platforms}")
        return None

    # 获取有效的access_token
    if not self._get_access_token():
        return None

    url = f"{self.base_url}/item/get_app"

    # 构建请求参数
    params = {
        "sku_id": sku_id,
        "access_token": self.access_token,
        "platform": platform,
        "area": area,
        "timestamp": int(time.time() * 1000)  # 时间戳,毫秒级
    }

    # 添加字段筛选
    if fields:
        params["fields"] = fields

    # 生成签名(部分接口需要)
    params["sign"] = self._generate_sign(params)

    try:
        response = self.session.get(url, params=params, timeout=20)
        response.raise_for_status()
        result = response.json()

        # 检查响应状态
        if result.get("code") == 200:
            # 格式化原始数据
            return self._process_raw_data(result.get("data", {}))
        else:
            logging.error(f"获取商品数据失败: {result.get('message', '未知错误')} (错误码: {result.get('code')})")
            return None

    except RequestException as e:
        logging.error(f"获取商品数据请求异常: {str(e)}")
        return None
    except json.JSONDecodeError:
        logging.error(f"商品数据响应解析失败: {response.text[:200]}...")
        return None

def _generate_sign(self, params: Dict) -> str:
    """生成签名(部分京东接口需要)"""
    # 按参数名排序
    sorted_params = sorted(params.items(), key=lambda x: x[0])
    # 拼接参数
    sign_str = self.appsecret
    for k, v in sorted_params:
        if k != "sign":
            sign_str += f"{k}{v}"
    sign_str += self.appsecret
    # SHA256加密
    return hashlib.sha256(sign_str.encode()).hexdigest().upper()

def _process_raw_data(self, raw_data: Dict) -> Dict:
    """处理原始数据,提取关键信息并格式化"""
    # 基础信息提取
    base_info = {
        "sku_id": raw_data.get("skuId"),
        "spu_id": raw_data.get("spuId"),
        "item_id": raw_data.get("itemId"),
        "title": raw_data.get("skuName"),
        "sub_title": raw_data.get("skuSubName"),
        "brand": {
            "id": raw_data.get("brandId"),
            "name": raw_data.get("brandName")
        },
        "category": {
            "cid1": raw_data.get("cid1"),
            "cid2": raw_data.get("cid2"),
            "cid3": raw_data.get("cid3"),
            "name1": raw_data.get("cateName1"),
            "name2": raw_data.get("cateName2"),
            "name3": raw_data.get("cateName3")
        },
        "url": f"https://item.jd.com/{raw_data.get('skuId')}.html" if raw_data.get('skuId') else None
    }

    # 价格信息提取
    price_info = {
        "jd_price": self._safe_float(raw_data.get("jdPrice", {}).get("p")),  # 京东价
        "market_price": self._safe_float(raw_data.get("marketPrice", {}).get("p")),  # 市场价
        "vip_price": self._safe_float(raw_data.get("vipPrice", {}).get("p")),  # 会员价
        "plus_price": self._safe_float(raw_data.get("plusPrice", {}).get("p")),  # PLUS会员价
        "promotion_price": self._safe_float(raw_data.get("promotionPrice", {}).get("p")),  # 促销价
        "price_history": raw_data.get("priceHistory"),  # 价格历史
        "price_tags": raw_data.get("priceTags", [])  # 价格标签
    }

    # 库存信息提取
    stock_info = {
        "stock_num": self._safe_int(raw_data.get("stock", {}).get("stockNum")),  # 库存数量
        "stock_state": raw_data.get("stock", {}).get("stockState"),  # 库存状态
        "stock_state_name": raw_data.get("stock", {}).get("stockStateName"),  # 库存状态名称
        "limit_buy": self._safe_int(raw_data.get("limitBuy")),  # 限购数量
        "area_stock": raw_data.get("areaStock")  # 区域库存信息
    }

    # 规格信息提取
    sku_info = {
        "total_sku": self._safe_int(raw_data.get("totalSku")),  # 总规格数量
        "sku_list": self._format_sku_list(raw_data.get("skuList", [])),  # 规格列表
        "spec_list": self._format_spec_list(raw_data.get("specList", []))  # 规格参数
    }

    # 促销信息提取
    promotion_info = {
        "promotions": raw_data.get("promotion", {}).get("promotionList", []),  # 促销活动列表
        "coupons": raw_data.get("couponList", []),  # 优惠券列表
        "gift_list": raw_data.get("giftList", []),  # 赠品列表
        "seckill_info": raw_data.get("seckillInfo")  # 秒杀信息
    }

    # 图片信息提取
    image_info = {
        "main_images": self._extract_images(raw_data.get("mainImgList", [])),  # 主图列表
        "detail_images": self._extract_images(raw_data.get("detailImgList", [])),  # 详情图列表
        "video_url": raw_data.get("videoInfo", {}).get("videoUrl")  # 视频URL
    }

    # 服务信息提取
    service_info = {
        "after_sale_service": raw_data.get("afterSaleService"),  # 售后服务
        "delivery_service": raw_data.get("deliveryService"),  # 配送服务
        "install_service": raw_data.get("installService"),  # 安装服务
        "warranty": raw_data.get("warranty")  # 保修信息
    }

    return {
        "base_info": base_info,
        "price_info": price_info,
        "stock_info": stock_info,
        "sku_info": sku_info,
        "promotion_info": promotion_info,
        "image_info": image_info,
        "service_info": service_info,
        "raw_data": raw_data  # 保留原始数据
    }

def _safe_float(self, value) -> float:
    """安全转换为float"""
    try:
        return float(value) if value is not None else 0.0
    except (ValueError, TypeError):
        return 0.0

def _safe_int(self, value) -> int:
    """安全转换为int"""
    try:
        return int(value) if value is not None else 0
    except (ValueError, TypeError):
        return 0

def _format_sku_list(self, sku_list: List[Dict]) -> List[Dict]:
    """格式化SKU列表"""
    formatted = []
    for sku in sku_list:
        formatted.append({
            "sku_id": sku.get("skuId"),
            "name": sku.get("name"),
            "price": self._safe_float(sku.get("jdPrice", {}).get("p")),
            "stock_num": self._safe_int(sku.get("stockNum")),
            "specs": sku.get("specs"),
            "image_url": sku.get("imgUrl"),
            "status": sku.get("status")
        })
    return formatted

def _format_spec_list(self, spec_list: List[Dict]) -> List[Dict]:
    """格式化规格参数列表"""
    formatted = []
    for spec in spec_list:
        formatted.append({
            "name": spec.get("name"),
            "values": [
                {
                    "name": val.get("name"),
                    "image_url": val.get("imgUrl"),
                    "selected": val.get("selected", False)
                } for val in spec.get("valueList", [])
            ]
        })
    return formatted

def _extract_images(self, image_list: List[Dict]) -> List[str]:
    """提取图片URL列表"""
    images = []
    for img in image_list:
        if isinstance(img, dict):
            url = img.get("url")
            if url:
                images.append(url)
        elif isinstance(img, str):
            images.append(img)
    return images

def compare_prices(self, current_data: Dict, previous_data: Dict) -> Dict:
    """比较两个时间点的价格差异"""
    if not current_data or not previous_data:
        return {}

    price_changes = {}
    price_types = ["jd_price", "market_price", "vip_price", "plus_price", "promotion_price"]

    for price_type in price_types:
        current = current_data["price_info"][price_type]
        previous = previous_data["price_info"][price_type]

        if current != previous:
            change = current - previous
            change_percent = (change / previous) * 100 if previous != 0 else 0
            price_changes[price_type] = {
                "current": current,
                "previous": previous,
                "change": round(change, 2),
                "change_percent": round(change_percent, 2)
            }

    return {
        "has_change": len(price_changes) > 0,
        "changes": price_changes,
        "compared_at": time.strftime("%Y-%m-%d %H:%M:%S")
    }

示例调用

if name == "main":

# 替换为实际的appkey和appsecret(从京东开放平台获取)
APPKEY = "your_appkey"
APPSECRET = "your_appsecret"
# 替换为目标商品SKU ID
SKU_ID = "100012345678"

# 初始化API客户端
api = JDItemGetAppAPI(APPKEY, APPSECRET)

# 获取商品原始数据
item_data = api.get_item_raw_data(
    sku_id=SKU_ID,
    platform="android",
    area="1_72_2799_0"  # 北京地区编码
    # fields="skuId,skuName,jdPrice,stock"  # 可选,指定需要的字段
)

if item_data:
    print(f"=== 京东商品详情 (SKU: {SKU_ID}) ===")
    print(f"商品名称: {item_data['base_info']['title']}")
    print(f"品牌: {item_data['base_info']['brand']['name']}")
    print(f"分类: {item_data['base_info']['category']['name1']} > {item_data['base_info']['category']['name2']} > {item_data['base_info']['category']['name3']}")
    print(f"京东价: {item_data['price_info']['jd_price']}元")

    if item_data['price_info']['promotion_price'] and item_data['price_info']['promotion_price'] < item_data['price_info']['jd_price']:
        print(f"促销价: {item_data['price_info']['promotion_price']}元")

    if item_data['price_info']['vip_price'] and item_data['price_info']['vip_price'] < item_data['price_info']['jd_price']:
        print(f"会员价: {item_data['price_info']['vip_price']}元")

    print(f"库存状态: {item_data['stock_info']['stock_state_name']}")
    print(f"规格数量: {item_data['sku_info']['total_sku']}")
    print(f"主图数量: {len(item_data['image_info']['main_images'])}")
    print(f"促销活动数量: {len(item_data['promotion_info']['promotions'])}")

    # 打印前3个规格信息
    if item_data['sku_info']['sku_list']:
        print("\n规格信息:")
        for i, sku in enumerate(item_data['sku_info']['sku_list'][:3], 1):
            print(f"  {i}. {sku['name']}: {sku['price']}元 (库存: {sku['stock_num']})")

    # 打印主要促销活动
    if item_data['promotion_info']['promotions']:
        print("\n促销活动:")
        for i, promo in enumerate(item_data['promotion_info']['promotions'][:3], 1):
            print(f"  {i}. {promo.get('title')}")

三、接口调用注意事项

  1. 调用限制与规范
    权限要求:item_get_app 属于高级接口,需要向京东开放平台单独申请权限
    QPS 限制:该接口 QPS 限制通常较低(1-5 次 / 秒),需严格控制调用频率
    数据缓存:建议缓存获取的数据(缓存时间 30-60 分钟),减少重复调用
    地区编码:不同地区可能有不同的价格和库存,需正确设置 area 参数
    字段筛选:不需要全部字段时,通过 fields 参数指定所需字段,提高响应速度
  2. 常见错误及解决方案
    错误码 说明 解决方案
    401 未授权或 token 无效 重新获取 access_token,检查权限是否正确
    403 权限不足 申请item_get_app接口的访问权限
    404 商品不存在 确认 sku_id 是否正确有效
    429 调用频率超限 降低调用频率,实现请求限流
    500 服务器内部错误 实现重试机制,最多 3 次,间隔指数退避
    10002 参数错误 检查地区编码等参数是否正确
  3. 数据解析要点
    价格字段:价格相关字段可能以字符串形式返回,需转换为数值类型
    库存状态:库存状态有多种编码,需结合状态名称理解实际含义
    规格结构:规格数据结构复杂,需递归解析多层规格组合
    促销信息:促销活动有多种类型,需分别处理不同的促销规则
    图片 URL:部分图片 URL 需要拼接域名才能访问
    四、应用场景与扩展建议
    典型应用场景
    商品全信息监控系统:实时监控商品所有属性的变化
    价格趋势分析工具:追踪商品价格历史,预测价格变化
    竞品深度分析平台:全方位对比分析竞品的各项参数和策略
    库存预警系统:基于原始库存数据设置预警阈值
    电商大数据分析平台:挖掘商品数据中的关联关系和规律
    扩展建议
    实现价格变化监控:定期获取数据,对比价格变化并记录
    开发库存趋势分析:跟踪库存数量变化,预测库存耗尽时间
    构建商品特征向量:将原始数据转换为特征向量,用于机器学习
    实现多地区数据对比:获取不同地区的价格和库存,分析区域差异
    开发数据导出功能:支持将原始数据和解析后的数据导出为 CSV/Excel
    构建商品相似度计算:基于原始属性计算商品间的相似度
    通过合理使用京东 item_get_app 接口,开发者可以获取最全面的商品原始数据,为深度电商分析和决策支持提供有力保障。使用时需遵守京东开放平台的相关规定,确保数据的合法使用。
相关文章
|
20天前
|
缓存 监控 算法
唯品会item_search - 按关键字搜索 VIP 商品接口深度分析及 Python 实现
唯品会item_search接口支持通过关键词、分类、价格等条件检索商品,广泛应用于电商数据分析、竞品监控与市场调研。结合Python可实现搜索、分析、可视化及数据导出,助力精准决策。
|
20天前
|
缓存 监控 算法
苏宁item_search - 按关键字搜索商品接口深度分析及 Python 实现
苏宁item_search接口支持通过关键词、分类、价格等条件检索商品,广泛应用于电商分析、竞品监控等场景。具备多维度筛选、分页获取、数据丰富等特性,结合Python可实现搜索、分析与可视化,助力市场研究与决策。
|
20天前
|
缓存 监控 算法
苏宁item_get - 获得商品详情接口深度# 深度分析及 Python 实现
苏宁易购item_get接口可实时获取商品价格、库存、促销等详情,支持电商数据分析与竞品监控。需认证接入,遵守调用限制,适用于价格监控、销售分析等场景,助力精准营销决策。(238字)
|
19天前
|
JSON 缓存 供应链
电子元件 item_search - 按关键字搜索商品接口深度分析及 Python 实现
本文深入解析电子元件item_search接口的设计逻辑与Python实现,涵盖参数化筛选、技术指标匹配、供应链属性过滤及替代型号推荐等核心功能,助力高效精准的电子元器件搜索与采购决策。
|
19天前
|
缓存 供应链 芯片
电子元件类商品 item_get - 商品详情接口深度分析及 Python 实现
电子元件商品接口需精准返回型号参数、规格属性、认证及库存等专业数据,支持供应链管理与采购决策。本文详解其接口特性、数据结构与Python实现方案。
|
测试技术 Python
python接口自动化(五)--接口测试用例和接口测试报告模板(详解)
当今社会在测试领域,接口测试已经越来越多的被提及,被重视,而且现在好多招聘信息要对接口测试提出要求。区别于传统意义上的系统级别测试,很多测试人员在接触到接口测试的时候,也许对测试执行还可以比较顺利的上手,但一 提到相关的文档,比如测试用例和报告,就有些不知所措了。这类问题在我加入的几个测试的群里,经常看到一些人在不断提问。   今天就用这篇文章来说说接口测试用例和报告。
667 2
python接口自动化(五)--接口测试用例和接口测试报告模板(详解)
|
Web App开发 网络协议 jenkins
python接口自动化(四)--接口测试工具介绍(详解)
如果有工具,可以大大提高你的效率,可以达到事半功倍,但是不是所有工具都能够支持你完成这个任务。下面我们就来挑选几个常用和常见的工具,简单介绍一下。如果需要或者有兴趣可以在网上查看各种工具对应的资料进行深入人的学习,这里带领大家了解一下,碰到这些工具会用、了解、知道这些工具就达到目的了,不要到时候说到测试工具,一问三不知,一脸懵逼,那样就尴尬
491 1
python接口自动化(四)--接口测试工具介绍(详解)
|
安全 Java 测试技术
python接口自动化(三)--如何设计接口测试用例(详解)
上篇我们已经介绍了什么是接口测试和接口测试的意义。在开始接口测试之前,我们来想一下,如何进行接口测试的准备工作。或者说,接口测试的流程是什么?有些人就很好奇,接口测试要流程干嘛?不就是拿着接口文档直接利用接口 测试工具测试嘛。其实,如果只是三五个接口,你可以这么做一个临时的接口测试。但是,如果是上百个接口,或者,你们公司的这个项目,第一次做接口测试,那么,我们还是很有必要严格遵守接口测试的流程。
461 0
python接口自动化(三)--如何设计接口测试用例(详解)
|
存储 前端开发 安全
python接口自动化(二)--什么是接口测试、为什么要做接口测试(详解)
上一篇和大家一起科普扫盲接口后,知道什么是接口,接口类型等,对其有了大致了解之后,我们就回到主题-接口测试。
316 0
python接口自动化(二)--什么是接口测试、为什么要做接口测试(详解)

热门文章

最新文章

推荐镜像

更多