教你用Python写一个京东自动下单抢购脚本(Python实现京东自动抢购) 您所在的位置:网站首页 有没有京东抢购的插件手机 教你用Python写一个京东自动下单抢购脚本(Python实现京东自动抢购)

教你用Python写一个京东自动下单抢购脚本(Python实现京东自动抢购)

2024-06-21 03:59| 来源: 网络整理| 查看: 265

很多朋友都有网购抢购限量商品的经历,有时候蹲点抢怎么也抢不到,今天小编带你们学习怎么用Python写一个京东自动下单抢购脚本,以后再也不用拼手速拼网速啦,快来一起看看吧

1 问题背景

经过无数次抢购失败后,发现商家会不定时的放出少量货源,目测每次会有几台。如果我们编写一个脚本程序24小时不间断监听商品库存,一旦查询到货源便开始尝试自动下单,这样就可以极大提高我们的成功概率。

2 设计思路

京东对于商品的抢购主要分为两种:

预约抢购:到点开放购买,和普通商品下单流程一致;秒杀商品:单独的抢购接口和下单流程。

当然本次针对的预约抢购类或无货订购类,即整体下单流程和购买普通商品时一样:

登录账号 → 进入购物车 → 选择抢购商品 → 点击去结算 → 点击提交订单 → 选择付款方式并付款。

3 具体实现

由于笔者本人没有一个可以抓包的客户端,决定采用京东 WEB 端接口实现我们的脚本程序。

于是经过对京东网页下单流程的分析,将我们的脚本程序分为四个模块:账号登录模块、库存监听模块、购物车管理模块、订单管理模块。

3.1 账号登录

由于使用账号密码时有验证码限制,此处采用扫码登录方式绕过。

如对扫码登录不熟悉或感兴趣的同学可以查看周周之前的博文 扫码登录原理和实现。

本次只要针对京东登录页进行抓包分析,找到几个有用接口:

获取登录二维码

def getQRcode(self): url = 'https://qr.m.jd.com/show' payload = { 'appid': 133, 'size': 147, 't': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.userAgent, 'Referer': 'https://passport.jd.com/new/login.aspx', } resp = self.sess.get(url=url, headers=headers, params=payload) if not self.respStatus(resp): return None return resp.content

获取Ticket

def getQRcodeTicket(self): url = 'https://qr.m.jd.com/check' payload = { 'appid': '133', 'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)), 'token': self.sess.cookies.get('wlfstk_smdl'), '_': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.userAgent, 'Referer': 'https://passport.jd.com/new/login.aspx', } resp = self.sess.get(url=url, headers=headers, params=payload) if not self.respStatus(resp): return False respJson = self.parseJson(resp.text) if respJson['code'] != 200: return None else: return respJson['ticket']

验证 Ticket​​​​​​​

def getQRcodeTicket(self): url = 'https://qr.m.jd.com/check' payload = { 'appid': '133', 'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)), 'token': self.sess.cookies.get('wlfstk_smdl'), '_': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.userAgent, 'Referer': 'https://passport.jd.com/new/login.aspx', } resp = self.sess.get(url=url, headers=headers, params=payload) if not self.respStatus(resp): return False respJson = self.parseJson(resp.text) if respJson['code'] != 200: return None else: return respJson['ticket']

此时验证 Ticket 有效后使用 pickle 库将程序会话中的 cookie 保存到本地以便下次使用。

3.2 库存监听

库存监听较为简单,分析商品详情页,获取店铺ID以及商品分类属性:

获取商品详情信息​​​​​​​

def getItemDetail(self, skuId): url = 'https://item.jd.com/{}.html'.format(skuId) page = requests.get(url=url, headers=self.headers) html = etree.HTML(page.text) vender = html.xpath( '//div[@class="follow J-follow-shop"]/@data-vid')[0] cat = html.xpath('//a[@clstag="shangpin|keycount|product|mbNav-3"]/@href')[ 0].replace('//list.jd.com/list.html?cat=', '') if not vender or not cat: raise Exception('获取商品信息失败,请检查SKU是否正确') detail = dict(catId=cat, venderId=vender) return detail

查询库存​​​​​​​

def getItemStock(self, skuId, num, areaId): item = self.itemDetails.get(skuId) if not item: return False url = 'https://c0.3.cn/stock' payload = { 'skuId': skuId, 'buyNum': num, 'area': areaId, 'ch': 1, '_': str(int(time.time() * 1000)), 'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)), # get error stock state without this param 'extraParam': '{"originid":"1"}', # get 403 Forbidden without this param (obtained from the detail page) 'cat': item.get('catId'), # return seller information with this param (can't be ignored) 'venderId': item.get('venderId') } headers = { 'User-Agent': self.userAgent, 'Referer': 'https://item.jd.com/{}.html'.format(skuId), } respText = '' try: respText = requests.get( url=url, params=payload, headers=headers, timeout=self.timeout).text respJson = self.parseJson(respText) stockInfo = respJson.get('stock') skuState = stockInfo.get('skuState') # 商品是否上架 # 商品库存状态:33 -- 现货 0,34 -- 无货 36 -- 采购中 40 -- 可配货 stockState = stockInfo.get('StockState') return skuState == 1 and stockState in (33, 40) 3.3 购物车操作

无货商品加入到购物车我们是无法通过页面操作的,我们这边可以使用其他有货商品进行尝试,主要查看购物车的增删改查接口:

取消所有选中商品​​​​​​​

def uncheckCartAll(self): """ 取消所有选中商品 return 购物车信息 """ url = 'https://api.m.jd.com/api' headers = { 'User-Agent': self.userAgent, 'Content-Type': 'application/x-www-form-urlencoded', 'origin': 'https://cart.jd.com', 'referer': 'https://cart.jd.com' } data = { 'functionId': 'pcCart_jc_cartUnCheckAll', 'appid': 'JDC_mall_cart', 'body': '{"serInfo":{"area":"","user-key":""}}', 'loginType': 3 } resp = self.sess.post(url=url, headers=headers, data=data) # return self.respStatus(resp) and resp.json()['success'] return resp

加入购入车​​​​​​​

def addCartSku(self, skuId, skuNum): """ 加入购入车 skuId 商品sku skuNum 购买数量 retrun 是否成功 """ url = 'https://api.m.jd.com/api' headers = { 'User-Agent': self.userAgent, 'Content-Type': 'application/x-www-form-urlencoded', 'origin': 'https://cart.jd.com', 'referer': 'https://cart.jd.com' } data = { 'functionId': 'pcCart_jc_cartAdd', 'appid': 'JDC_mall_cart', 'body': '{\"operations\":[{\"carttype\":1,\"TheSkus\":[{\"Id\":\"' + skuId + '\",\"num\":' + str(skuNum) + '}]}]}', 'loginType': 3 } resp = self.sess.post(url=url, headers=headers, data=data) return self.respStatus(resp) and resp.json()['success']

修改购物车商品数量​​​​​​​

def changeCartSkuCount(self, skuId, skuUid, skuNum, areaId): """ 修改购物车商品数量 skuId 商品sku skuUid 商品用户关系 skuNum 购买数量 retrun 是否成功 """ url = 'https://api.m.jd.com/api' headers = { 'User-Agent': self.userAgent, 'Content-Type': 'application/x-www-form-urlencoded', 'origin': 'https://cart.jd.com', 'referer': 'https://cart.jd.com' } body = '{\"operations\":[{\"TheSkus\":[{\"Id\":\"'+skuId+'\",\"num\":'+str( skuNum)+',\"skuUuid\":\"'+skuUid+'\",\"useUuid\":false}]}],\"serInfo\":{\"area\":\"'+areaId+'\"}}' data = { 'functionId': 'pcCart_jc_changeSkuNum', 'appid': 'JDC_mall_cart', 'body': body, 'loginType': 3 } resp = self.sess.post(url=url, headers=headers, data=data) return self.respStatus(resp) and resp.json()['success']

以上是我们一次购买需要用到的最少接口,为了不破坏账户购物车中已有数据,采用一下步骤准备好购物车:

取消全部勾选(返回购物车信息);已在购物车则修改商品数量;不在购物车则加入购物车。3.4 订单操作

当我们准备好购物车之后(选中购买商品以及调整购买数量),就可以进行下一步订单相关操作:

获取结算单​​​​​​​

def getCheckoutPage(self): """获取订单结算页面信息 :return: 结算信息 dict """ url = 'http://trade.jd.com/shopping/order/getOrderInfo.action' # url = 'https://cart.jd.com/gotoOrder.action' payload = { 'rid': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.userAgent, 'Referer': 'https://cart.jd.com/cart', }

提交订单​​​​​​​

def submitOrder(self): """提交订单 :return: True/False 订单提交结果 """ url = 'https://trade.jd.com/shopping/order/submitOrder.action' # js function of submit order is included in https://trade.jd.com/shopping/misc/js/order.js?r=2018070403091 data = { 'overseaPurchaseCookies': '', 'vendorRemarks': '[]', 'submitOrderParam.sopNotPutInvoice': 'false', 'submitOrderParam.trackID': 'TestTrackId', 'submitOrderParam.ignorePriceChange': '0', 'submitOrderParam.btSupport': '0', 'riskControl': self.risk_control, 'submitOrderParam.isBestCoupon': 1, 'submitOrderParam.jxj': 1, 'submitOrderParam.trackId': self.track_id, 'submitOrderParam.eid': self.eid, 'submitOrderParam.fp': self.fp, 'submitOrderParam.needCheck': 1, } 4 完整代码

项目完整源码请看:https://github.com/zas023/JdBuyer

目前完成度较高,可以直接使用:

并提供 Windows 和 macOS 两种客户端;支持下单后微信通知触达。

5 总结

脚本自动化操作确实可以实现抢购商品,相比手动操作有较高的下单成功率,但仅靠上述代码想与某些专业抢购的服务器进行比较还是相去甚远。

到此这篇关于教你用Python写一个京东自动下单抢购脚本的文章就介绍到这了!

最后: 下方这份完整的软件测试视频学习教程已经整理上传完成,朋友们如果需要可以自行免费领取【保证100%免费】

在这里插入图片描述

 这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有