/jdSeckill

京东茅台抢购

Primary LanguagePythonGNU General Public License v3.0GPL-3.0

截止 2021/2/1 日,该项目已无法使用!

京东:约满即止,仅限京东实名认证用户APP端抢购,2月1日10:00开始预约,2月1日12:00开始抢购(京东APP需升级至8.5.6版本及以上)

写在前面

本项目来自 huanghyw - jd_seckill,作者的项目地址我找不到了,找到了再贴上,感谢。

同时感谢两位我感谢的作者感谢的两位作者 😄:

感谢原作者 https://github.com/zhou-xiaojun/jd_mask 提供的代码

感谢 https://github.com/wlwwu/jd_maotai 进行的优化

我在这个项目上又进行了一些代码改动,改动点贴在后面。

注意:我仅测试了抢购茅台,其他商品是否可用,有待研究,下文来自作者项目介绍,稍加改动。

=============我是分割线=============

简介

通过我这段时间的使用(2020-12-12至2020-12-17),证实这个脚本确实能抢到茅台。我自己三个账号抢了四瓶,帮两个朋友抢了4瓶。大家只要确认自己配置文件没有问题,Cookie 没有失效,坚持下去总能成功的。

暗中观察

根据12月14日以来抢茅台的日志分析,大胆推断再接再厉返回Json消息中resultCode与小白信用的关系。 这里主要分析出现频率最高的9001690008

JSON 样例
{'errorMessage': '很遗憾没有抢到,再接再厉哦。', 'orderId': 0, 'resultCode': 90016, 'skuId': 0, 'success': False}
{'errorMessage': '很遗憾没有抢到,再接再厉哦。', 'orderId': 0, 'resultCode': 90008, 'skuId': 0, 'success': False}
数据统计
案例 小白信用 90016 90008 抢到耗时
张三 63.8 59.63% 40.37% 暂未抢到
李四 92.9 72.05% 27.94% 4天
王五 99.6 75.70% 24.29% 暂未抢到
赵六 103.4 91.02% 8.9% 2天
猜测

推测返回 90008 是京东的风控机制,代表这次请求直接失败,不参与抢购,小白信用越低越容易触发京东的风控。

从数据来看小白信用与风控的关系大概每十分为一个等级,所以赵六基本上没有被拦截,李四和王五的拦截几率相近,张三的拦截几率最高。

风控放行后才会进行抢购,这时候用的应该是水库计数模型,假设无法一次性拿到所有数据的情况下来尽量的做到抢购成功用户的均匀分布,这样就和概率相关了。

综上,张三想成功有点困难,小白信用是100+的用户成功几率最大。

准备工作

脚本操作流程
  • 登陆京东商城(www.jd.com
    • 用京东APP扫码给出的二维码
  • 预约茅台
    • 定时自动预约
  • 秒杀预约后等待抢购
    • 定时开始自动抢购
运行环境
第三方库

需要使用到的库已经放在 requirements.txt,使用pip 安装的可以使用指令

  • 官方安装,访问国外服务器,可能比较慢

    pip install -r requirements.txt
  • 国内清华源加速,安装很快,推荐使用

    pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/

开始使用

1. 抓取参数值:eid / fp(推荐使用谷歌浏览器)
  • 打开京东登录页面,登录后随便找个商品加入购物车

  • 右键点击检查,调试窗口内点击 Console 进入控制台,Filter 框内输入 _JdTdudfp

  • 进入购物车商品结算页面,即可从输出的 json 中获取 eidfp

2. 将抓取到的参数填入 confign.py 内对应位置
3. 运行 main.py
  • 默认是预约 + 抢购
  • 默认抢购两瓶,如果一个月内抢购过一瓶,最好修改抢购瓶数为1
    • 修改:seckill.py ==> self.seckill_num 参数,改值即可,最大为 2
  • 多进程抢购
    • 默认改为了 1 个进程
    • 可以设置进程数:main.py ==> seckill.seckill_by_proc_pool() 括号内填入想要设置的进程数即可
  • 每天提前 5 分钟运行脚本,万一 cookies 过期,需要预留一个登录的时间
  • 增加了抢购时长限制,默认设置为 2,即:程序运行 2 分钟后自动停止
    • 这个时间也可以自行修改 seckill.py ==> 搜索 minutes 修改值即可
4. 抢购结果确认

抢购是否成功通常在程序开始的一分钟内可见分晓!若两分钟还未抢购成功,基本上就是没抢到!

  • 自行搜索日志,检查关键字

    • 出现"抢购成功,订单号xxxxx",代表成功抢到了,务必半小时内支付订单!

    • 没有就明天再战 💔

  • 通过 ServerChan 下发通知到微信,需要注册,并在 config ==> sckey 填入才能生效,如果获取 sckey 请移步 ServerChan 官网查看。

// 抢购失败:
{'errorMessage': '很遗憾没有抢到,再接再厉哦。', 'orderId': 0, 'resultCode': 60074, 'skuId': 0, 'success': False}
{'errorMessage': '抱歉,您提交过快,请稍后再提交订单!', 'orderId': 0, 'resultCode': 60017, 'skuId': 0, 'success': False}
{'errorMessage': '系统正在开小差,请重试~~', 'orderId': 0, 'resultCode': 90013, 'skuId': 0, 'success': False}
// 抢购成功:
{"appUrl":"xxxxx","orderId":820227xxxxx,"pcUrl":"xxxxx","resultCode":0,"skuId":0,"success":true,"totalMoney":"xxxxx"} 

改动记录

目前的版本是改动比较大的,使用继承类的方式完成,并且拆分了登录模块,增加了一些 debug 的日志打印,更便于追踪问题吧,还有就是将相对路径全部修改为了绝对路径,嗯...

其实在这个项目之前还有一个版本,发布在其他渠道了,没有上传 github,修改了一些问题,目前也同步到这个项目,下面大概列举一下 =.=!

  • 问题 1:拿到代码后直接从根目录执行 main.py 文件时,报异常:FileNotFoundException

    原因:读取配置文件时,没有使用绝对路径,使用绝对路径,解决该问题

  • 问题2:预约逻辑问题,预约是每天 10 点 30 分以后到第二天的抢购时间之前都可预约,但是程序设计为必须到达抢购时间才可预约,也就是抢购前 500 毫秒左右

    修改:当前时间大于 10 点 30,即可进行预约

  • 问题 3:预约和抢购需要执行两次 main.py 文件,分别输入 1、2 完成对应操作

    原因:作者设计如此;我希望定时任务运行一次,即可直接完成预约+抢购,因为预约并没有时间限制,定时任务开启后,直接进行预约,然后等待抢购时间到达就好啦~

  • 问题 4:抢购时间需要每次在配置文件内手动修改为当天,如果不修改会判断当前时间永远大于抢购时间,只要运行程序就一直发起抢购

    修改:增加当天时间自动获取,如果在 10 点前运行程序,则等待到达抢购时间;如果在 10 点 30 分后手动运行程序,则直接提示抢购时间已过,不再发起请求;针对两种情况区分了提示信息

  • 问题 5:多进程抢购时,都增加了获取商品名称和用户名的逻辑

    优化:取消掉该逻辑,因为抢购的商品就一个,所以程序运行前去获取一次就可以了

  • 问题 7:抢购过程中出现「当前地区无货」的情况,直接抛出异常堆栈信息

    解决:增加这种情况下的异常信息提示,相对友好一些

  • 问题 8:日志格式过长,打开日志文件,当前屏看到的都是格式,需要向后滑才能看到真正的日志,不方便

    解决:修改日志 formatter 格式,精简信息

  • 问题 9:日志文件根据存储大小进行备份,每天的抢购信息不好区分

    优化:程序运行前可以选择是否备份文件,main.py ==> log_bak()如果备份,则将日志信息打印上昨天的日志标签,今天重写一份日志文件

  • 问题 10:作者使用了 serverChan 进行推送抢购结果到微信,该方法在多线程内,每抢购一次就发送一次消息,调用次数过于频繁,导致有时被服务拉黑(server酱对发送消息有限制,每人每天上限 500 条,相同内容 5 分钟内不能重复发送,不同内容 10 分钟内不能连续发送,每天调用接口超过1000次的用户将被系统自动拉黑)所以其实发送这么频繁,真正收不到几条消息

    解决:修改发送消息逻辑,改为:如果抢购成功,立马发送成功的消息;否则抢购程序结束后,程序读取当天的日志文件,判断是否有「抢购成功」关键字,没有就发送一条抢购失败的消息。

    获取到最终结果后,再发送消息,预约一条,抢购结果一条。由于微信上推送的内容是仅展示标题,作者是把标题固定了,所以需要点击「查看详情」才能查看结果,为了少点那一下,我就把结果直接改为标题,真的要查看详细信息了再去点击。

  • ...

写在最后

经过这段时间的测试,发现抢购结果并非与速度有直接关系,更多的是受制于京东风控、账号信息等,这就是我将默认进程设置为 1 的原因,再次强调:本项目仅供学习使用,不可用于任何商业用途~

原项目我基本手抄了一遍,然后去弄懂每一步到底是在干嘛,学习到很多,受益匪浅,再次感谢。

我代码写的很烂,这个项目的改动点又多,阅读代码过程中不足之处麻烦指出,感谢。

抢购过程中遇到任何问题,欢迎交流。

最后,希望各位都能抢购成功。。。 2⃣️0⃣️2⃣️1⃣️ 万事顺遂 !!!

2021/1/31

三天了,北京地区都是无货状态... 年前还能抢到吗?😭

2021/2/1

京东抢购策略调整如下:

约满即止,仅限京东实名认证用户APP端抢购,2月1日10:00开始预约,2月1日12:00开始抢购(京东APP需升级至8.5.6版本及以上)

今天试了一把, web 端到达预约时间后直接引流到 APP, 无法操作预约。

手机端预约

抓包查看预约请求:

  • 先判断是否已经预约 ==> isAppoint
  • 进行预约 ==> appoint

两个接口客户端都会传入 sign 参数,这是根据规则动态生成的,只有知道特定规则才能模拟。

那么,就大结局 🔚 了呀~