您好,欢迎访问一九零五行业门户网

如何使用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
获取ticketdef 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']

验证 ticketdef 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, }
以上就是如何使用python编写自动抢购京东下单脚本?的详细内容。
其它类似信息

推荐信息