前言
20万人抢购几瓶茅台,本人已经坚持了3个月仍未抢到,甚至一度怀疑有猫腻根本没有提供可抢购的商品,只是JD的假数据,但是直到最近通过python脚本完成了抢购才发现是真的,手动抢购真的是拼运气!可惜每人只能抢购一瓶,下面给出具体实现步骤,祝愿各位都能顺利抢购成功。
环境
python3.7
requests2.23
ios14
windows10
编码
1、获取jd时间
# url = 'https://a.jd.com//ajax/queryServerData.html'
# ret = requests.get(url).text
# print("京东时间:" )
# print(ret)
# js = json.loads(ret)
# print("js:" +js)
# return int(js["serverTime"])
# 以上代码在新版app里已经失效
# 使用下面方案
url = 'https://api.m.jd.com'
resp = requests.get(url, verify=False)
jd_timestamp = int(resp.headers.get('X-API-Request-Id')[-13:])
return jd_timestamp
2、说明,此例不展示脚本自动预约,这个我用手动预约的方案替代,非必须的代码没开发。
3、获取cookie
通过fidder配置好代理,苹果手机浏览器中下载证书,ios中证书下载完成会显示在设置顶部,点击安装完成后并在关于中选择对应的证书并信任,这步必须。这里不详细讲解如何抓包,具体流程可参考本博客中的文章。
获取的cookie可以通过配置文件配置,当然你也可以放在session管理里。
4、 获取二维码下载二维码登录
def _get_qrcode_ticket(self):
"""
通过 token 获取票据
:return:
"""
url = 'https://qr.m.jd.com/check'
payload = {
'appid': '133',
'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
'token': self.session.cookies.get('wlfstk_smdl'),
'_': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.spider_session.get_user_agent(),
'Referer': 'https://passport.jd.com/new/login.aspx',
}
resp = self.session.get(url=url, headers=headers, params=payload)
if not response_status(resp):
logger.error('获取二维码扫描结果异常')
return False
resp_json = parse_json(resp.text)
if resp_json['code'] != 200:
logger.info('Code: %s, Message: %s', resp_json['code'], resp_json['msg'])
return None
else:
logger.info('已完成手机客户端确认')
return resp_json['ticket']
def _validate_qrcode_ticket(self, ticket):
"""
通过已获取的票据进行校验
:param ticket: 已获取的票据
:return:
"""
url = 'https://passport.jd.com/uc/qrCodeTicketValidation'
headers = {
'User-Agent': self.spider_session.get_user_agent(),
'Referer': 'https://passport.jd.com/uc/login?ltype=logout',
}
resp = self.session.get(url=url, headers=headers, params={'t': ticket})
if not response_status(resp):
return False
resp_json = json.loads(resp.text)
if resp_json['returnCode'] == 0:
return True
else:
logger.info(resp_json)
return False
5、抢购
def request_seckill_url(self):
logger.info('用户:{}'.format(self.get_username()))
logger.info('商品名称:{}'.format(self.get_sku_title()))
self.timers.start()
logger.info('|||获取商品的抢购连接...')
self.seckill_url[self.sku_id] = self.get_seckill_url()
logger.info('|||访问商品的抢购连接...')
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
self.session.get(
url=self.seckill_url.get(
self.sku_id),
headers=headers,
allow_redirects=False)
def request_seckill_checkout_page(self):
# 页面结算
logger.info('访问抢购订单结算页面...')
url = 'https://marathon.jd.com/seckill/seckill.action'
payload = {
'skuId': self.sku_id,
'num': self.seckill_num,
'rid': int(time.time())
}
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
resp = self.session.get(url=url, params=payload, headers=headers, allow_redirects=False)
logger.info('------------------订单结算页面返回-------------')
url = 'https://marathon.jd.com/seckillnew/orderService/pc/submitOrder.action'
payload = {
'skuId': self.sku_id,
}
try:
self.seckill_order_data[self.sku_id] = self._get_seckill_order_data()
except Exception as e:
logger.info('抢购失败,无法获取生成订单的基本信息,接口返回:【{}】'.format(str(e)))
return False
logger.info('提交抢购订单...')
#说明,提交秒杀的url可以通过fidder抓包获取,由于链接变动频繁,直到写这篇文章时已经发生了变化
6、pip所需要的依赖
certifi2020.4.5.1
chardet3.0.4
idna2.9
lxml~=4.5.1
requests~=2.23.0
urllib31.25.9