def _monitor(isInStockApiParam): while True: resp = glb.request( '监控库存', None, glb.GET, 'https://c0.3.cn/stocks', params=isInStockApiParam, headers={'cookie': None}, redirect=False, logLvl={ glb.successLogLvl: logging.DEBUG, # 请求成功的日志等级 glb.timeoutLogLvl: logging.DEBUG, # 请求超时的日志等级 glb.tooManyFailureLogLvl: logging.DEBUG }, # 过多失败的日志等级 timeout=1.5) if resp is not None: try: for itemId, value in resp.json().items(): if value['skuState'] == 0 or value['StockState'] not in ( 33, 40): glb.runTimeItems[itemId][glb.isInStock] = False else: glb.runTimeItems[itemId][glb.isInStock] = True if canBuy(itemId): Thread(target=buy, args=(itemId, )).start() except JSONDecodeError: continue
def _monitor(isInStockApiParam): while True: resp = glb.request( '监控库存', None, glb.GET, 'https://c0.3.cn/stocks', params=isInStockApiParam, headers={'cookie': None}, logLvl={ glb.successLogLvl: logging.DEBUG, # 请求成功的日志等级 glb.timeoutLogLvl: logging.DEBUG, # 请求超时的日志等级 glb.tooManyFailureLogLvl: logging.DEBUG }, # 过多失败的日志等级 timeout=1.5) if resp is not None: try: for itemId, value in resp.json().items(): if value['skuState'] == 0 or value['StockState'] not in ( 33, 40): glb.items[itemId]['inStock'] = False else: logging.warning('{} 有货'.format(itemId)) glb.items[itemId]['inStock'] = True buy(itemId) except JSONDecodeError: continue
def _checkSnappingUp(): for itemId in glb.runTimeItems.keys(): resp = glb.request( '检查是否为抢购商品', None, glb.GET, 'https://yushou.jd.com/youshouinfo.action', params={'sku': itemId}, headers={ 'referer': 'https://item.jd.com/{}.html'.format(itemId), 'cookie': None }, logLvl={ glb.successLogLvl: logging.DEBUG, # 请求成功的日志等级 glb.timeoutLogLvl: logging.DEBUG, # 请求超时的日志等级 glb.tooManyFailureLogLvl: logging.DEBUG }, # 过多失败的日志等级 timeout=3) if resp is None or resp.text[:1] != '{': continue if resp.text != '{"error":"pss info is null"}': if not glb.runTimeItems[itemId][glb.isSnappingUp]: logging.warning('{} 是抢购商品, 不自动购买'.format(itemId)) glb.runTimeItems[itemId][glb.isSnappingUp] = True else: if glb.runTimeItems[itemId][glb.isSnappingUp]: logging.warning('{} 不是抢购商品, 会自动购买'.format(itemId)) glb.runTimeItems[itemId][glb.isSnappingUp] = False if canBuy(itemId): Thread(target=buy, args=(itemId, )).start()
def _monitor(isInStockApiParam): while True: resp = glb.request( '监控库存', glb.GET, 'https://c0.3.cn/stocks', params=isInStockApiParam, headers={'cookie': None}, logLvl={ glb.successLogLvl: logging.DEBUG, # 请求成功的日志等级 glb.timeoutLogLvl: logging.DEBUG, # 请求超时的日志等级 glb.tooManyFailureLogLvl: logging.DEBUG }, # 过多失败的日志等级 timeout=1.5) if resp is None: continue try: for itemId, value in resp.json().items(): if value['skuState'] == 0: # isInStockApiParams['skuIds'] = re.sub('{},?'.format(itemId), '', isInStockApiParams['skuIds']) glb.config['items'][itemId] = False glb.items[itemId] = False continue if value['StockState'] in (33, 40): logging.warning('{} 有货'.format(itemId)) glb.items[itemId] = True # Thread(target=buy, args=(itemId,)).start() buy(itemId) else: glb.items[itemId] = False except JSONDecodeError: continue
def checkLogin(self): return glb.request( '检测登录', glb.GET, 'https://passport.jd.com/loginservice.aspx?method=Login', headers={'Referer': 'https://www.jd.com/'}, sess=self.sess, logLvl={glb.successLogLvl: logging.DEBUG}, timeout=5)
def checkSnappingUp(): while True: for itemId in glb.config['items'].keys(): resp = glb.request( '检查是否为抢购商品', None, glb.GET, 'https://yushou.jd.com/youshouinfo.action', params={'sku': itemId}, headers={ 'referer': 'https://item.jd.com/{}.html'.format(itemId), 'cookie': None }, logLvl={ glb.successLogLvl: logging.DEBUG, # 请求成功的日志等级 glb.timeoutLogLvl: logging.DEBUG, # 请求超时的日志等级 glb.tooManyFailureLogLvl: logging.DEBUG }, # 过多失败的日志等级 timeout=5) if resp is not None and resp.text != '{"error":"pss info is null"}': glb.items[itemId]['snappingUp'] = True time.sleep(60 * 10)
def buy(self, itemId): while True: if not monitor.canBuy(itemId): return if not self.isBuying: break self.isBuying = True success = [False] logging.warning('开始购买 ({})'.format(', '.join((self.id, itemId)))) try: # 添加到购物车 if glb.request('添加到购物车 ({})'.format(', '.join((self.id, itemId))), self.sess, glb.GET, 'https://cart.jd.com/gate.action', params={ 'pid': itemId, 'pcount': 1, 'ptype': 1 }, redirect=False, logLvl={ glb.defaultLogLvl: logging.ERROR, glb.redirectLogLvl: logging.DEBUG }, timeout=3) is None: return logging.warning('添加到购物车 ({}) 成功'.format(', '.join( (self.id, itemId)))) def getOrderInfoCheck(_resp, args): if re.search('showCheckCode" value="(.+)"', _resp.text).group(1) == 'true': logging.warning('结算 ({}) 需要通过图形验证码'.format(', '.join( (args[0].id, args[1])))) time.sleep(1) return True return False # 结算 resp = glb.request( '结算 ({})'.format(', '.join((self.id, itemId))), self.sess, glb.GET, 'https://trade.jd.com/shopping/order/getOrderInfo.action', checkFuc=getOrderInfoCheck, args=(self, itemId), redirect=False, logLvl={glb.defaultLogLvl: logging.ERROR}, timeout=3) if resp is None: return riskControl = re.search('riskControl" value="(.+?)"', resp.text).group(1) def submitOrderCheck(_resp, args): respObj = _resp.json() if respObj['resultCode'] in (60123, 600157): logging.error('提交订单 ({}) 失败 (message: {})'.format( ', '.join((args[0].id, args[1])), respObj['message'])) return False elif respObj['resultCode'] is 600158: logging.error('提交订单 ({}) 失败 (无货)'.format(', '.join( (args[0].id, args[1])))) glb.runTimeItems[args[1]][glb.isInStock] = False return False elif respObj['resultCode'] is 60017: logging.error('提交订单 ({}) 失败 (请求过于频繁), 睡眠5s'.format( ', '.join((args[0].id, args[1])))) time.sleep(5) return True elif respObj['success'] is True: logging.error( '\n\n\n提交订单 ({}) 成功!!!!!!!!!!!!!!!!!!!\n\n\n'.format( ', '.join((args[0].id, args[1])))) args[2][0] = True return False else: logging.error('提交订单 ({}) 失败 ({})'.format( ', '.join((args[0].id, args[1])), respObj)) return False # 提交订单 if glb.request( '提交订单 ({})'.format(', '.join((self.id, itemId))), self.sess, glb.POST, 'https://trade.jd.com/shopping/order/submitOrder.action', headers={ 'Origin': 'https://trade.jd.com', 'Referer': 'https://trade.jd.com/shopping/order/getOrderInfo.action' }, data= { 'overseaPurchaseCookies': '', 'vendorRemarks': '[]', 'submitOrderParam.sopNotPutInvoice': 'false', 'submitOrderParam.trackID': 'TestTrackId', 'submitOrderParam.ignorePriceChange': '0', 'submitOrderParam.btSupport': '0', 'submitOrderParam.eid': self.config['eid'], # https://gia.jd.com/fcf.html 'submitOrderParam.fp': self.config['fp'], 'riskControl': riskControl, 'submitOrderParam.jxj': 1, 'submitOrderParam.trackId': self.config['trackId'], # 'submitOrderParam.isBestCoupon': 1, # # 'submitOrderParam.needCheck': 1, # }, checkFuc=submitOrderCheck, args=(self, itemId, success), logLvl={glb.defaultLogLvl: logging.ERROR}, timeout=3) is None: return finally: # 失败后删除商品 if not success[0]: glb.request('从购物车删除 ({})'.format(', '.join((self.id, itemId))), self.sess, glb.POST, 'https://cart.jd.com/removeSkuFromCart.action', data={ 'venderId': '8888', 'pid': itemId, 'ptype': '1', 'packId': '0', 'targetId': '0', 't': '0', 'outSkus': '', 'random': '0.3794799431176733', 'locationId': self.config['areaId'] }, headers={ 'Content-Type': 'application/x-www-form-urlencoded', 'Origin': 'https://cart.jd.com', 'Referer': 'https://cart.jd.com/cart.action' }, timeout=5) self.isBuying = False
def buy(self, itemId): while self.isBuying: if not glb.items[itemId]: return self.isBuying = True success = False try: # TODO: 查看是否限购 # 添加到购物车 if glb.request('添加到购物车({})'.format(', '.join((self.id, itemId))), glb.GET, 'https://cart.jd.com/gate.action', params={ 'pid': itemId, 'pcount': 1, 'ptype': 1 }, sess=self.sess, redirect=False, logLvl={ glb.defaultLogLvl: logging.ERROR, glb.redirectLogLvl: logging.DEBUG }, timeout=3) is None: return def getOrderInfoCheck(_resp, args): if re.search('showCheckCode" value="(.+)"', _resp.text).group(1) == 'true': logging.warning('结算({}) 需要通过图形验证码'.format(', '.join( (args[0].id, itemId)))) time.sleep(1) return True # 结算 resp = glb.request( '结算({})'.format(', '.join((self.id, itemId))), glb.GET, 'https://trade.jd.com/shopping/order/getOrderInfo.action', sess=self.sess, checkFuc=getOrderInfoCheck, args=[self], logLvl={glb.defaultLogLvl: logging.ERROR}, timeout=3) if resp is None: return self.config['riskControl'] = re.search( 'riskControl" value="(.+?)"', resp.text).group(1) logging.info('riskControl: {}'.format(self.config['riskControl'])) def submitOrderCheck(_resp, args): if _resp.json()['resultCode'] in (60123, 600157, 600158): logging.error('提交订单({}) 失败({})'.format( ', '.join((args[0].id, itemId)), _resp.json['message'])) return False elif _resp.json()['resultCode'] is 60017: logging.error('提交订单({}) 请求过于频繁'.format(', '.join( (args[0].id, itemId)))) time.sleep(5) return True elif _resp.json()['success'] is True: logging.error('提交订单({}) 成功'.format(', '.join( (args[0].id, itemId)))) args[1] = True return False # 提交订单 if glb.request( '提交订单({})'.format(', '.join((self.id, itemId))), glb.POST, 'https://trade.jd.com/shopping/order/submitOrder.action', headers={ 'Origin': 'https://trade.jd.com', 'Referer': 'https://trade.jd.com/shopping/order/getOrderInfo.action' }, data={ 'overseaPurchaseCookies': '', 'vendorRemarks': '[]', 'submitOrderParam.sopNotPutInvoice': 'false', 'submitOrderParam.trackID': 'TestTrackId', 'submitOrderParam.ignorePriceChange': '0', 'submitOrderParam.btSupport': '0', # https://gia.jd.com/fcf.html 'submitOrderParam.eid': self.config['eid'], # 几乎不变 'submitOrderParam.fp': self.config['fp'], # 几乎不变 'riskControl': self.config['riskControl'], 'submitOrderParam.jxj': 1, 'submitOrderParam.trackId': self.config['trackId'], 'submitOrderParam.isBestCoupon': 1, # 'submitOrderParam.needCheck': 1, # }, checkFuc=submitOrderCheck, args=[self, success], logLvl={glb.defaultLogLvl: logging.ERROR}, timeout=3) is None: return # 失败后删除商品 finally: if not success: glb.request('remove from cart ({})'.format(', '.join( (itemId, self.id))), glb.POST, 'https://cart.jd.com/removeSkuFromCart.action', data={ 'venderId': '8888', 'pid': itemId, 'ptype': '1', 'packId': '0', 'targetId': '0', 't': '0', 'outSkus': '', 'random': '0.3794799431176733', 'locationId': glb.config['area'] }, headers={ 'Content-Type': 'application/x-www-form-urlencoded', 'Origin': 'https://cart.jd.com', 'Referer': 'https://cart.jd.com/cart.action' }, sess=self.sess, timeout=5) self.isBuying = False