京东商品库存监控与自动下单系统:基于Python的轮询方案
2026/9/1 2:02:41 网站建设 项目流程

简介:这是一套面向Python初学者与电商自动化爱好者的学习型工具源码,聚焦京东商品库存监控与自动下单场景,解决人工盯盘耗时、缺货时无法及时抢购等痛点。资源包含61个文件,以9个核心Python脚本(如JdBuyer.py、JdSession.py、timer.py)、10个备份配置(.zbak)、36个区域ID文本(覆盖全国34省市及港澳台、海外、钓鱼岛等)、以及config.json、README.md、logo.ico等支撑文件为主,总大小仅605KB,结构清晰、模块职责分明,便于理解登录会话管理、库存轮询、订单提交与通知推送等关键逻辑。已有103人学习下载,配套提供图形界面与命令行双模式运行方案,含日志记录、异常捕获、截图辅助(assest/shootscreen.mac.png)及跨平台适配说明,适合动手实践自动化流程设计、HTTP会话维护与轻量GUI开发。 做电商相关开发的朋友应该都遇到过这种场景:某个商品库存只有那么几件,补货时间不固定,人工盯着页面刷新,手指点断也未必抢得到。我整理这套“京东商品库存监控与自动下单系统”,就是为了解决这种让人头疼的实时竞速问题。它包含完整的源码、配置说明和使用指南,能帮你自动轮询商品库存,一旦检测到可售状态,就触发后续的下单动作。下面这套方案适合有Python基础、想自己跑一套自动化监控脚本的开发者,也适合小团队在做补货提醒时直接参考。

1. 项目核心思路:库存监控到底在监控什么

1.1 明确需求边界:不能什么商品都自动下单

先得把需求边界讲清楚。监控系统不是“拿到商品链接就开始下单”那么简单,你要先界定清楚哪些商品适合自动下单。我自己实测下来,普通自营商品、第三方店铺可售商品、没有地域限购和实名要求的商品,用脚本处理比较顺手。但那些需要填写实名信息、有地区限购条件、或者每次购买数量要经过审核的商品,脚本很难处理,因为很多字段不是预设值就能填进去的,硬要自动下单只会频繁失败。

所以我在设计这套系统时,把“可自动下单的商品范围”作为配置文件里的一个说明项,里面写了三条判断规则:第一,商品详情页能看到明确的价格和库存;第二,加入购物车时不需要额外填写定制信息;第三,结算页面没有额外的验证步骤,比如手机验证。只要不满足其中任意一条,就建议只做库存监控和提醒,不要开启自动下单。这么做不是因为脚本做不了,而是从账号安全和订单成功率角度看,不划算。

1.2 技术选型:为什么用轮询而不是推送

很多第一次接触这个项目的人会问,为什么不用WebSocket直接接收库存变化推送?电商平台不会给普通用户提供这种实时推送通道,就算提供,也要申请权限、走审核流程,根本不是一个脚本能搞定的。退一步说,即使有第三方服务提供库存变化的推送,消息链路过长,延迟往往超过你的预期,等你收到通知再打开页面,货早就没了。

所以最现实的做法就是定时轮询接口,用最简单的方式“拉”数据。轮询最大的问题是频率怎么控制。频率太高,账号和当前网络出口会被平台的风控系统盯上,轻则弹验证码,重则限制登录;频率太低,则可能在看到“有货”之前货已经被别人拍走。我实测下来,普通商品3到5秒轮询一次是相对均衡的选择,既能保证响应速度,又不会让请求量失控。如果你同时监控多个SKU,最好把请求分散开,不要同一秒并发请求。

用Python来实现这个轮询逻辑,也是经过对比的。Python的requests库写起来很直接,JSON解析方便,自动重试、超时控制这些都有成熟的方案,能快速把原型跑起来。相比于Java或者Go,Python在快速迭代这个场景下优势很明显。

1.3 系统模块划分:把监控、通知和下单解耦

整个系统我拆成了四个独立模块:

模块核心职责关键输出
监控模块定时请求库存接口,解析库存状态每个SKU的库存状态、变化时间
通知模块在库存变化时推送提醒微信、邮件等渠道的消息
自动下单模块在可售时执行加购、提交订单订单号或错误信息
日志与持久化模块记录请求、下单结果,保存状态日志文件和SQLite数据

模块之间通过简单的数据接口连接,没有做成复杂的消息队列。这样设计的原因很简单:个人项目场景下,没必要引入额外的中间件,增加部署成本。四个模块各自独立后,你可以只开监控通知,不开启自动下单;也可以把自动下单改造成“人工确认后下单”的半自动模式,灵活性高很多。

这种解耦方式也让排查问题变得容易。比如某次自动下单失败了,我先看日志模块里的完整请求记录,再核对下单模块的输入参数,基本能快速定位是接口变化还是配置错误。如果一开始就把逻辑全写在一个文件里,后面改起来会非常痛苦。

2. 库存监控实现:接口、参数与数据解析

2.1 从商品链接到SKU ID:一个商品不止一个库存口径

用户拿到一条商品链接,比如 item.jd.com/100012345.html,这里的100012345是商品ID。但监控时只盯商品ID是不够的,因为一个商品往往有很多个SKU,不同颜色、不同规格、不同地区对应着不同的SKU ID和不同的库存状态。举个例子,一件手机可能“黑色”有货、“白色”无货,如果你只看商品ID,接口返回的可能是汇总状态,你根本判断不了具体是哪个型号有货。

所以第一步是从商品页面里把所有SKU的信息提取出来。常见的做法是通过解析商品详情页的HTML,或者调用获取商品详情的JSON接口。页面源码里一般会有一份SKU列表,里面包含SKU ID、规格名称、价格等信息,甚至直接包含初始库存状态。把这些信息存到配置或者数据库里,后续的库存监控就围绕SKU ID展开。我建议在配置文件里直接维护一个SKU列表,而不是程序运行时再去页面里解析,因为运行时解析增加了网络请求,还容易因为页面结构变化而失败。

2.2 库存接口的返回结构:先看清字段再写解析

库存接口的返回结构和普通详情页不一样,通常是一个JSON对象,核心部分的结构大体是这样的:

{ "skus": { "123456": { "stock": { "stockState": 33, "stockDesc": "现货", "remainNum": 5 } } } }

这里面stockState字段是最关键的,我见过的习惯性定义里,33表示现货、可购买,0表示无货,40可能表示下架或采购中。但不同接口、不同时期,这个枚举值可能有差异,所以拿到接口后第一件事就是自己打一次真实数据,把字段含义确认清楚。解析逻辑要写两层:第一层是字段存在性判断,第二层才是状态值判断。字段缺失的时候,不要直接抛异常终止整个监控进程,而是记录一条日志,留到下一轮再试。

这里有一个很容易忽略的细节:remainNum字段可能不一定会返回,或者返回的是大整数,但实际逻辑里它并不代表“库存充足”,而只是系统展示用的余量估算。所以判断有没有货,应该以stockState为主,搭配remainNum做参考,不能单独拿remainNum判断可售。

2.3 请求头与登录态:Cookie是生命线

库存监控接口通常需要携带一些基础请求头,才能返回正确数据。User-Agent要设置成浏览器常见的值,Referer要指向商品详情页或购物车页面,否则某些接口会直接拒绝请求。我习惯把这些请求头写在一个全局配置里,统一管理。

真正影响成败的是登录态。如果你用浏览器登录过京东,打开开发者工具,在Network面板里随便挑一条库存接口的请求,把请求头里的Cookie复制出来,放到配置文件里,脚本就能携带这个登录态去请求库存接口。Cookie的有效期取决于账号的活跃程度和平台的策略,可能撑几天,也可能撑几周,过期后需要重新登录并更新Cookie。我的经验是把Cookie存到一个独立文件里,脚本启动时读取,更新的时候只改文件,不用动源码。

有一点必须提醒:Cookie属于高敏感信息,不要把配置文件和代码一起提交到公开仓库,哪怕只是个人练习项目,也不要冒这个险。我在本地目录建了一个config.local.yaml,并在.gitignore里把它加进去,这样既能方便日常改动,又不会因为疏忽泄露关键凭证。

2.4 轮询频率与反限制:别把脚本写成压力测试工具

前面提到轮询频率要控制在3到5秒,这里再多说几句反限制的实践。首先,不要在代码里写一个死循环加 time.sleep(3) 就完事了,因为网络请求本身也耗时,实际间隔可能是3秒加几百毫秒,波动不大但容易被规律性识别。更好的做法是每次请求后随机睡眠一定区间,比如:

import time import random time.sleep(random.uniform(3, 5))

其次,监控多个SKU时要错开请求。比如三个SKU,可以每两秒轮询一个,而不是每秒钟同时发三个请求。并发请求会让风控系统更容易产生告警,账号一旦被要求输入验证码,整个自动监控流程都会被迫中断,损失反而更大。

另外,请求超时时间一定要设置。库存接口偶尔会卡顿,如果不设置timeout,脚本会一直等在那里,等于把监控挂死。我一般设置5秒超时,超过就放弃本轮请求,等下一轮。重试机制也要有,但只对网络超时重试,不要对业务状态码做无限重试,否则很容易触发更严厉的限制。

3. 自动下单模块:从加购到提交订单的完整链路

3.1 下单流程的“地图”:不只是点一下按钮

自动下单听起来很爽,但实际上手的复杂度和库存监控不在一个量级。浏览器里完成一次下单,至少包括:加购物车、进入购物车结算页、选择收货地址、提交订单。如果商品有优惠券、赠品、运费险等额外配置,每一步都可能多出一些接口调用。脚本模拟下单时,这些步骤全都要通过接口逐一完成,任何一步缺参数或者参数错误,都会导致下单流程中断。

所以我建议把下单流程当成一张“地图”:先花时间把每个步骤对应的接口、必要的参数、返回的错误码记录下来,再开始写代码。我在源码里维护了一个流程状态枚举,用来标记当前进行到哪一步,比如“待加购”“已加购”“待结算”“已提交”“失败”。这样可以避免流程中断后不知道卡在哪里。

3.2 核心接口调用顺序:每一步都别跳

我这里列一下典型的下单调用顺序,不是全部细节,但能给你一个方向。第一步,调用加购接口,把商品ID、SKU ID、购买数量传过去,返回结果里通常会有加购后的购物车信息。第二步,调用查询购物车接口,确认商品已经在购物车里,顺便拿到购物车版本的标识,这个标识后续提交订单时可能要用到。第三步,进入结算接口,这一步会返回一个结算凭证或者token,提交订单接口必须带上它。第四步,调用提交订单接口,传入结算凭证、地址、支付方式等,成功后会返回订单号。

每一步的返回都要记录到日志里。我踩过的最大一个坑是:加购接口返回成功了,但购物车查询接口查不到商品,导致后续全部失败。后来发现是因为加购接口返回成功只是代表“服务端接受了请求”,实际库存已经被别人锁定了,购物车列表根本不会出现这个商品。所以一定要在加购后再做一次校验,而不是直接信任加购接口的返回。

3.3 自动下单的触发条件:别让脚本连续下单

自动下单的触发条件不能只是“检测到有货就下单”,否则你会遇到两个问题:一是重复下单,二是在“根本没货”的假象上下单。我采用的做法是维护一个状态机,针对每个SKU记录上次状态和本次状态,只有“上次无货、本次有货”才触发下单。如果上次就是有货但下单失败了,不会再次触发,除非你手动重置状态。

购买数量也要小心。有些商品设置了单用户限购,比如每人限购一件,如果你配置下单数量是2,提交订单大概率会被拦截。这时候可以在代码里读取限购配置,超过限购就按限购数量提交,或者直接跳过下单并通知。我更推荐后者,因为“下单成功”和“下单被拦截”的提示差异很大,避免你后面去售后解释不清。

3.4 防重复、防误触发的工程细节

下单这种操作一旦执行,就是真金白银的订单,所以工程上一定要做防重复设计。我在代码里加了一个“下单锁”,用全局变量和线程锁实现,保证同一时间只有一个下单流程在跑。如果你有多进程部署,需要换成文件锁或者数据库锁,否则两个进程同时下单会导致重复订单。

超时和失败重试也要设计好。提交订单接口如果因为网络原因没有返回结果,你不能立即重试,因为服务端可能已经创建了订单,重试会生成重复订单。我的做法是:提交后如果超时,先把“结果未知”写入日志,然后查询订单列表接口确认是否真的下单成功,再决定是否重试。虽然加了一步查询,但能省去很多麻烦。

4. 跑通源码的完整实操记录

4.1 环境准备:Python版本与依赖安装

这套系统源码基于Python 3.8以上开发,我在3.10和3.11环境都跑过,没有遇到兼容问题。依赖库很少,核心是requests和PyYAML,requests用来发HTTP请求,PyYAML用来读取yaml格式的配置。如果有数据库持久化的需求,还需要安装sqlite3,Python自带这个库,不用额外装。

安装依赖的过程很简单:

pip install -r requirements.txt

requirements.txt里的内容大致是:

requests>=2.25.0 PyYAML>=5.4.0

如果运行环境里同时有Python 2和Python 3,记得确认pip指向的是正确的版本,否则可能装上去了,运行时却报找不到模块,这种情况我遇到过好几次。

4.2 配置文件说明:每项参数都有讲究

配置我放在config.yaml里,结构如下:

monitor: interval: 5 # 轮询间隔,单位秒,不建议低于2 skus: - "100012345" # 要监控的SKU,可以填多个 auto_order: enabled: true # 是否启用自动下单 quantity: 1 # 下单数量 max_quantity: 1 # 限购数量,超过就跳过 retry_times: 0 # 订单提交失败后的重试次数 notify: type: "wechat" # 通知渠道:wechat/email wechat_key: "" email_to: ""

interval参数不建议低于2秒,这是被账号风控逼出来的实践经验。quantity是每次下单数量,max_quantity是平台限购数量,如果quantity大于max_quantity,脚本不会自动改数量,而是直接通知你人工处理。这样设计是因为平台限购规则经常会变化,脚本自动修改数量可能踩到更多隐藏限制。

4.3 核心代码片段讲解:主循环长什么样子

这里给一个简化后的监控主循环,重点展示逻辑思路,不是完整可运行版本,因为完整源码依赖你本地抓包后填写的接口信息。

import time import random import requests def check_stock(sku_id, session, headers): """查询单个SKU的库存状态""" url = "https://xxx/stock" # 用你抓包得到的地址替换 params = {"skuId": sku_id} resp = session.get(url, params=params, headers=headers, timeout=5) data = resp.json() stock_state = data["skus"][sku_id]["stock"]["stockState"] return stock_state def main(): # 初始化配置、session和Cookie load_config() session = requests.Session() session.headers.update(build_headers()) session.cookies.update(parse_cookie(config["cookie"])) while True: for sku in config["monitor"]["skus"]: try: state = check_stock(sku, session) if is_available(state) and should_trigger(sku): place_order(sku) except Exception as e: log(f"轮询失败: {sku}, 错误: {e}") time.sleep(random.uniform(3, 5)) if __name__ == "__main__": main()

这段代码的核心就是循环里做两件事:检查库存、判断是否触发下单。其中should_trigger函数内部会判断状态机的状态变化,确保不会因为连续轮询到“有货”就反复下单。place_order函数封装了下单流程,内部包含加购、结算、提交订单三个步骤。

4.4 日志与运行验证:没有日志就不知道挂在哪

运行配置好之后,建议先开着日志跑半天。日志至少要包含这几个信息:请求时间、SKU ID、库存状态、是否触发下单、下单结果。第一次跑的时候,我在监控和下单两个关键节点都打上了日志,但忽略了把原始响应保存下来,结果遇到“页面显示有货但脚本没反应”,根本不知道是解析问题还是接口问题。后来我在异常分支里把原始响应体写入了单独的log文件,问题很快就定位到了。

还有一个验证技巧:先把auto_order.enabled设为false,只跑监控和通知,等确认库存状态解析完全正确后,再打开自动下单。这样可以避免一个解析错误导致一连串的失败重试,把账号和心情都搞坏。

5. 常见问题与排查技巧实录

5.1 登录态过期导致接口报错

现象是监控脚本一直在刷日志,但返回的都不是正常的库存信息,而是提示未登录或者错误码。排查方向很明确:Cookie过期了。处理办法是重新用浏览器登录,从Network面板复制最新的Cookie,更新到配置文件里。我建议在代码里加一个“Cookie更新时间”的提示字段,每月提醒你手动检查一次,虽然不是必须,但能避免半夜里脚本因为登录态失效而全部罢工。

5.2 接口字段解析失败

库存接口的返回结构偶尔会调整,比如字段名从stockState变成了stockStatus,或者嵌套层级变深。遇到这种情况,脚本会抛KeyError或者解析出None,如果没有容错逻辑,进程就会挂掉。最好的办法是在解析函数里做一层安全取值,取不到就写日志并跳过本轮。保留原始响应到本地文件的方式,可以让你快速对比新旧结构差异,比在线调试快很多。

5.3 下单失败,错误码各不相同

下单失败的错误码,可能对应库存不足、超出限购、商品已下架、需要验证码等不同原因。我在项目里维护了一个错误码映射表,把常见错误码对应到中文描述,再输出到日志和通知消息里。有了这个表,排查效率提升了不少。如果你是刚接触,建议先从一条具体错误码开始,通过搜索引擎或者自己凑参数测试来理解它的含义。

5.4 监控误报与漏报

监控判断“有货”不代表一定可以下单,因为库存状态和真实可售状态有时候存在时间差。反过来,监控判断“无货”时,可能只是临时被锁库存,过几十秒又释放出来。面对这些情况,我的处理原则是:以提交订单接口的返回为准,监控状态只作为触发参考。误报导致的无效下单动作,会消耗账号的信任度,所以宁可少触发,也不要盲目下单。

下面我把常见的几个问题整理成一个速查表,方便你到时候直接对照:

现象可能原因排查方向
监控一直返回未登录Cookie过期更新Cookie并重启
请求被限制频率过高调大间隔,加随机延时
接口字段解析失败接口结构变化保存原始响应对比
加购成功但购物车无货库存已被锁重新查询库存状态
提交订单返回限购超过平台限购检查max_quantity配置
下单结果未知网络超时查询订单列表确认

6. 最后分享一些实操心得

写这套系统的过程里,我最大的收获不是“抢到货”的那一刻,而是对一个重复性事务的流程化理解。人工盯库存最大的问题不是速度,而是注意力无法持续集中,脚本解决的就是这个痛点。它把“一直守着页面”变成了“事件驱动”,你可以去做别的事,等通知来了再回来处理。

另外有一条我一直坚持的原则:这类自动化能力一定要用在合规场景里。我自己只会在正常购买需求下使用,比如补货提醒、日常囤货,不会拿它去做恶意抢购、倒卖、大规模刷单,也不会故意去挑战平台的风控底线。账号安全是一方面,更关键的是,任何滥用行为都可能影响到正常用户的购物体验,这就违背了写这个项目的初衷。如果你只是学习源码怎么用,建议一直开着监控通知、关闭自动下单,先把流程跑明白再考虑开闸。

最后再分享一个配置上的小技巧:如果你同时监控多个SKU,建议把通知消息里加上商品名称和SKU名称,不然收到一条“有货了”的提醒,你还要打开网页去确认是哪一个型号,体验很割裂。改起来很简单,就是在配置里补一个name字段,触发时拼到消息里,一行代码的事,但体验提升非常明显。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询