首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >京东商品搜索列表API开发实录:Python 签名、分页与异常处理

京东商品搜索列表API开发实录:Python 签名、分页与异常处理

原创
作者头像
用户1597063760
发布于 2026-10-21 14:18:29
发布于 2026-10-21 14:18:29
290
举报
文章被收录于专栏:经验经验

摘要:本文记录京东JD.item_search 商品搜索接口完整开发过程,覆盖开放平台签名算法、分页循环拉取、超时 / 签名错误 / 限流等异常处理方案,附可直接调试的 Python 代码,适合竞品采集、电商市场调研场景,告别爬虫。

一、接口前置说明

接口标识:JD.item_search (Taobaoapi2014前往体验)

网关地址: c0b.cc/R4rbK2

用途:关键词检索京东商品列表,支持类目、价格、排序筛选

二、签名规则拆解(京东开放平台通用)

  1. 剔除参数中值为空的 key
  2. 参数按照 key 字典序升序排序
  3. 按key+value直接拼接成字符串,末尾拼接 app_secret
  4. MD5 加密,结果转为大写,作为 sign

很多人调不通,基本都是排序错、时间时区不对、空格多了。

三、完整 Python 实现(签名 + 分页 + 异常捕获)

代码语言:javascript
复制
import hashlib
import requests
import time
from typing import Optional, Dict, List

class JdUnionSearchApi:
    def __init__(self, app_key: str, app_secret: str):
        self.app_key = app_key
        self.app_secret = app_secret
        self.gateway = "https://api.jd.com/routerjson"

    @staticmethod
    def get_sign(params: Dict[str, str], secret: str) -> str:
        # 按key升序排序
        sorted_pairs = sorted(params.items(), key=lambda x: x[0])
        raw_str = "".join([f"{k}{v}" for k, v in sorted_pairs]) + secret
        md5_val = hashlib.md5(raw_str.encode("utf-8")).hexdigest()
        return md5_val.upper()

    def search_goods(self,
                     keyword: str,
                     page_index: int = 1,
                     page_size: int = 20,
                     sort: Optional[str] = None,
                     cid: Optional[str] = None,
                     price_start: Optional[int] = None,
                     price_end: Optional[int] = None
                     ) -> dict:
        """单次搜索一页商品"""
        params = {
            "method": "jd.union.open.goods.search",
            "app_key": self.app_key,
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
            "keyword": keyword,
            "pageIndex": str(page_index),
            "pageSize": str(page_size)
        }
        # 可选参数,不为空才加入
        if sort:
            params["sort"] = sort
        if cid:
            params["cid"] = cid
        if price_start is not None:
            params["priceStart"] = str(price_start)
        if price_end is not None:
            params["priceEnd"] = str(price_end)

        params["sign"] = self.get_sign(params, self.app_secret)
        try:
            resp = requests.get(self.gateway, params=params, timeout=10)
            resp.raise_for_status()
            return resp.json()
        except requests.exceptions.Timeout:
            return {"code": -1, "msg": "请求超时"}
        except requests.exceptions.HTTPError as e:
            return {"code": -2, "msg": f"HTTP异常:{str(e)}"}
        except Exception as e:
            return {"code": -99, "msg": f"未知异常:{str(e)}"}

    def fetch_all_pages(self, keyword: str, max_page: int = 5, sleep_sec: float = 1.2, **kwargs) -> List[dict]:
        """循环分页拉取,内置限流休眠,防止被封"""
        all_goods = []
        for page in range(1, max_page + 1):
            res = self.search_goods(keyword=keyword, page_index=page, **kwargs)
            if res.get("code", 0) != 0:
                print(f"第{page}页请求失败:{res.get('msg')}")
                break
            # 根据京东返回结构提取商品数组,这里根据实际返回调整key
            data = res.get("jd_union_open_goods_search_response", {})
            result = data.get("result", {})
            goods_list = result.get("goodsList", [])
            if not goods_list:
                print(f"第{page}页无商品,停止翻页")
                break
            all_goods.extend(goods_list)
            print(f"成功获取第{page}页,本页{len(goods_list)}条")
            time.sleep(sleep_sec)
        return all_goods


if __name__ == "__main__":
    # 替换为自己的密钥
    ak = "YOUR_APP_KEY"
    sk = "YOUR_APP_SECRET"
    api = JdUnionSearchApi(ak, sk)
    goods = api.fetch_all_pages(keyword="无线充电器", max_page=3, page_size=20)
    print(f"一共拿到商品:{len(goods)} 条")

四、异常分类处理思路(生产重点)

  1. 签名错误(sign invalid)
    • 排查:时间戳时区、参数是否有多余空格、是否漏删空值参数、排序是否字典序
  2. 接口返回无数据
    • 关键词是否合规、类目 ID 是否正确、价格区间是否没有商品;部分排序模式下返回量会变少
  3. 频繁返回拒绝访问 / 403
    • 触发平台限流,加大sleep_sec,分布式场景建议做令牌桶限流
  4. 偶尔超时
    • 增加重试装饰器,设置最大重试次数,不要无限重试
  5. 字段不稳定、部分字段偶尔缺失
    • 取字段时全部用 .get(),不要直接下标取值,防止 KeyError 崩溃

五、分页踩坑实录

  • 京东这个接口不支持无限深度翻页,pageIndex 拉到后面会返回空,属于平台限制,不是 bug
  • 总数量是估算值,不能用来精确判断还有多少页
  • pageSize 有上限,不要盲目设置很大,容易被拦截

六、落地业务延伸

拿到商品列表 skuId 后,可以串联:

  • 京东商品详情 API:获取原价、券后价、库存
  • 评论 API:抓取评价做 NLP 情感分析
  • 数据入库,定时任务做价格监控、竞品榜单、选品看板

七、开发小结

京东联盟搜索接口相比爬虫稳定很多,但签名、时区、限流是三大高频卡点。工程化时建议单独封装签名工具、统一异常码、增加日志、做请求间隔控制。整套链路可以直接用于跨境选品、竞品价格监控、电商市场数据采集。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、接口前置说明
  • 二、签名规则拆解(京东开放平台通用)
  • 三、完整 Python 实现(签名 + 分页 + 异常捕获)
  • 四、异常分类处理思路(生产重点)
  • 五、分页踩坑实录
  • 六、落地业务延伸
  • 七、开发小结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档