def get_username(self): """获取用户信息""" url = 'http://my.suning.com/person.do' # payload = { # 'safp': 'jQuery{}'.format(random.randint(1000000, 9999999)), # '_': str(int(time.time() * 1000)), # } # https://my.suning.com/person.do?safp=d488778a.eiem.AVsm.2 headers = { 'User-Agent': self.user_agent, 'Referer': 'http://order.suning.com/order/orderList.do', } resp = self.session.get(url=url, headers=headers) # , params=payload try_count = 5 profile_name = '' while True: try: x_data = etree.HTML(resp.text) profile_eles = x_data.xpath( '//div[@class="profile-info"]//span') if len(profile_eles) > 0: profile_name = profile_eles[0].text.strip() try_count = try_count - 1 if try_count > 0: resp = self.session.get( url=url, headers=headers) # , params=payload else: break wait_some_time() except Exception as e: logger.error("获取用户名异常", e) # 响应中包含了许多用户信息,现在在其中返回昵称 return profile_name
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 clear_cart(self): """清空购物车 包括两个请求: 1.选中购物车中所有的商品 2.批量删除 :return: 清空购物车结果 True/False """ # 1.select all items 2.batch remove items select_url = 'https://cart.jd.com/selectAllItem.action' remove_url = 'https://cart.jd.com/batchRemoveSkusFromCart.action' data = { 't': 0, 'outSkus': '', 'random': random.random(), } try: #select_resp = self.session.post(url=select_url, data=data) remove_resp = self.session.post(url=remove_url, data=data) #if (not response_status(select_resp)) or (not response_status(remove_resp)): if (not response_status(remove_resp)): logger.error('购物车清空失败') return False logger.info('购物车清空成功') return True except Exception as e: logger.error(e) return False
def make_reserve(self): """商品预约""" logger.info('商品名称:{}'.format(self.get_sku_title())) url = 'https://yushou.jd.com/youshouinfo.action?' payload = { 'callback': 'fetchJSON', 'sku': self.sku_id, '_': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.default_user_agent, 'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id), } resp = self.session.get(url=url, params=payload, headers=headers) if not resp.text: logger.error('未获取返回数据') return resp_json = parse_json(resp.text) reserve_url = resp_json.get('url') self.timers = Timer(self.buy_time) self.timers.start() while self.__running.isSet(): self.__flag.wait() try: self.session.get(url='https:' + reserve_url) logger.info('预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约') success_message = "预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约" send_email(success_message) break except Exception as e: logger.error('预约失败,错误:', e) time.sleep(3)
def _get_qrcode_ticket(self): """ 通过 token 获取票据 :return: """ # 'https://passport.suning.com/ids/qrLoginStateProbe?callback=jQuery17207490926503827557_1609730767292' url = 'https://passport.suning.com/ids/qrLoginStateProbe?callback=jQuery{}_{}'.format( random.randint(1000000, 9999999), int(round(time.time() * 1000))) headers = { 'User-Agent': self.spider_session.get_user_agent(), 'Referer': 'https://order.suning.com/order/orderList.do', 'X-Requested-With': 'XMLHttpRequest' } data = { 'uuid': self.session.cookies.get_dict().get('ids_qr_uuid'), 'service': '', 'terminal': 'PC' } resp = self.session.post(url=url, data=data, headers=headers) if not response_status(resp): logger.error('获取二维码扫描结果异常') return False if 'Set-Cookie' in resp.headers: if resp.headers['Set-Cookie'].find('nick') > -1: logger.info('已完成手机客户端确认') return True logger.info('Result: %s' % resp.text) return False
def make_reserve(self): """商品预约""" logger.info('商品名称:{}'.format(self.get_sku_title())) url = 'https://yushou.jd.com/youshouinfo.action?' payload = { 'callback': 'fetchJSON', 'sku': self.sku_id, '_': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.user_agent, 'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id), } resp = self.session.get(url=url, params=payload, headers=headers) resp_json = parse_json(resp.text) reserve_url = resp_json.get('url') self.timers.start() while True: try: self.session.get(url='https:' + reserve_url) logger.info('预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约') if global_config.getRaw('messenger', 'enable') == 'true': success_message = "预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约" send_wechat(success_message) break except Exception as e: logger.error('预约失败正在重试...')
def parse_json(s): print('parse_json', s) try: begin = s.find('{') end = s.rfind('}') + 1 return Dict(json.loads(s[begin:end])) except Exception as e: logger.error(e) return
def stop(self): self.pushButton_4.setEnabled(True) self.pushButton_5.setEnabled(False) while True: try: thread = self.queue_stop.get(timeout=0.1) if thread.isAlive(): thread.stop() except Exception as e: logger.error(e) break
def submit_seckill_order(self): """提交抢购(秒杀)订单 :return: 抢购结果 True/False """ url = 'https://marathon.jd.com/seckillnew/orderService/pc/submitOrder.action' payload = { 'skuId': self.sku_id, } self.seckill_order_data[self.sku_id] = self._get_seckill_order_data() logger.info('提交抢购订单...') self.push_log('提交抢购订单...') headers = { 'User-Agent': self.default_user_agent, 'Host': 'marathon.jd.com', 'Referer': 'https://marathon.jd.com/seckill/seckill.action?skuId={0}&num={1}&rid={2}' .format(self.sku_id, self.seckill_num, int(time.time())), } resp = self.session.post(url=url, params=payload, data=self.seckill_order_data.get(self.sku_id), headers=headers) if not resp.text: logger.error('未获取返回数据') return resp_json = parse_json(resp.text) # 返回信息 # 抢购失败: # {'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"} if resp_json and resp_json.get('success'): order_id = resp_json.get('orderId') total_money = resp_json.get('totalMoney') pay_url = 'https:' + resp_json.get('pcUrl') logger.info('抢购成功,订单号:{}, 总价:{}, 电脑端付款链接:{}'.format( order_id, total_money, pay_url)) success_message = "抢购成功,订单号:{}, 总价:{}, 电脑端付款链接:{}".format( order_id, total_money, pay_url) self.push_order_code(str(order_id)) send_email(success_message) return True else: err_msg = '抢购失败,返回信息:{}'.format(str(resp_json)) logger.error(err_msg) self.push_log(err_msg) error_message = '抢购失败,返回信息:{}'.format(resp_json) if resp_json and resp_json.get('resultCode'): self.push_err_code(resp_json.get('resultCode')) return False
def __seckill(self): """ 抢购 """ self.login() while self.__running.isSet(): self.__flag.wait() try: self.request_seckill_url() self.request_seckill_checkout_page() self.submit_seckill_order() except Exception as e: logger.error('抢购发生异常,稍后继续执行!', e) self.wati_some_time()
def make_reserve(self): """商品预约""" logger.info('商品名称:{}'.format(self.get_sku_title())) url = 'https://yushou.jd.com/youshouinfo.action?' payload = { 'callback': 'fetchJSON', 'sku': self.sku_id, '_': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.user_agent, 'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id), } resp = self.session.get(url=url, params=payload, headers=headers) resp_json = parse_json(resp.text) reserve_url = resp_json.get('url') # self.timers.start() while True: try: self.session.get(url='https:' + reserve_url) resp_text = self.session.get(url='https:' + reserve_url).text resp_html = etree.HTML(resp_text) result_msg = "".join([ t.strip() for t in resp_html.xpath( "//div[@class='bd-right']/./*[@class='bd-right-result']/text()" ) ]) if len( resp_html.xpath( "//div[@class='bd-right']/./*[@class='bd-right-result']/text()" )) > 0 else "未匹配到预约消息" if "预约成功" in resp_text: logger.info('预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约') logger.info(result_msg) self.reserve_statue = True if global_config.getRaw('messenger', 'enable') == 'true': success_message = "预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约" send_wechat(success_message) break elif "预约失败" in resp_text: logger.info('预约失败,超过最大购买数量/已经预约过!') logger.info(result_msg) self.reserve_statue = True break else: logger.info('预约返回其他未知提示!') logger.info(result_msg) self.reserve_statue = True break except Exception as e: logger.error('预约失败正在重试...', e)
def refresh_count(self): if self.count <= 0: self.time.stop() while True: try: thread = self.queue.get(timeout=0.01) self.queue_stop.put(thread) if not thread.isAlive(): thread.start() except Exception as e: logger.error(e) self.add_log('所有线程启动成功') break return self.count -= 1 self.lcdNumber.display(self.count)
def make_reserve(self): """商品预约""" logger.info('商品名称:{}'.format(self.get_sku_title())) url = 'https://yushou.jd.com/youshouinfo.action?' payload = { 'callback': 'fetchJSON', 'sku': self.sku_id, '_': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.user_agent, 'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id), } resp = self.session.get(url=url, params=payload, headers=headers) resp_json = parse_json(resp.text) reserve_url = resp_json.get('url') self.timers.start() while True: try: self.session.get(url='https:' + reserve_url) logger.info('预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约') requests.post( "https://sc.ftqq.com/SCU67992Tb6d106e75a7e8fa6f00c53c9bf7f7bb05de8bce100ce2.send", data={ "text": "茅台预约成功啦", "desp": """茅台预约成功啦 ![image](https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1601019829813&di=f40ea308a5fb36b99d793cd74785b24c&imgtype=0&src=http%3A%2F%2Fpic.feizl.com%2Fupload%2Fallimg%2F170704%2F4881tnxkewt5mq.jpg) """ }) if global_config.getRaw('messenger', 'enable') == 'true': success_message = "预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约" send_wechat(success_message) requests.post( "https://sc.ftqq.com/SCU67992Tb6d106e75a7e8fa6f00c53c9bf7f7bb05de8bce100ce2.send", data={ "text": "茅台预约成功啦", "desp": """茅台预约成功啦 ![image](https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1601019829813&di=f40ea308a5fb36b99d793cd74785b24c&imgtype=0&src=http%3A%2F%2Fpic.feizl.com%2Fupload%2Fallimg%2F170704%2F4881tnxkewt5mq.jpg) """ }) break except Exception as e: logger.error('预约失败正在重试...')
def _validate_cookies(self): """ 验证cookies是否有效(是否登陆) 通过访问用户订单列表页进行判断:若未登录,将会重定向到登陆页面。 :return: cookies是否有效 True/False """ url = 'https://order.jd.com/center/list.action' payload = { 'rid': str(int(time.time() * 1000)), } try: resp = self.session.get(url=url, params=payload, allow_redirects=False) if resp.status_code == requests.codes.OK: return True except Exception as e: logger.error("验证cookies是否有效发生异常", e) return False
def get_seckill_url(self): """获取商品的抢购链接 点击"抢购"按钮后,会有两次302跳转,最后到达订单结算页面 这里返回第一次跳转后的页面url,作为商品的抢购链接 :return: 商品的抢购链接 """ url = 'https://itemko.jd.com/itemShowBtn' payload = { 'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)), 'skuId': self.sku_id, 'from': 'pc', '_': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.default_user_agent, 'Host': 'itemko.jd.com', 'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id), } while self.__running.isSet(): self.__flag.wait() resp = self.session.get(url=url, headers=headers, params=payload) print('resp', resp.text) if not resp.text: logger.error('未获取返回数据') return resp_json = parse_json(resp.text) if resp_json.get('url'): # https://divide.jd.com/user_routing?skuId=8654289&sn=c3f4ececd8461f0e4d7267e96a91e0e0&from=pc router_url = 'https:' + resp_json.get('url') # https://marathon.jd.com/captcha.html?skuId=8654289&sn=c3f4ececd8461f0e4d7267e96a91e0e0&from=pc seckill_url = router_url.replace( 'divide', 'marathon').replace( 'user_routing', 'captcha.html') if seckill_url: msg = "抢购链接获取成功: %s", seckill_url logger.info(msg) self.push_log(msg) return seckill_url else: msg = "抢购链接获取失败" return else: logger.info("抢购链接获取失败,稍后自动重试") self.push_log("抢购链接获取失败,稍后自动重试") self.wati_some_time()
def request_seckill_url(self): """访问商品的抢购链接(用于设置cookie等""" logger.info('用户:{}'.format(self.get_username())) logger.info('商品名称:{}'.format(self.get_sku_title())) self.timers.start() self.seckill_url[self.sku_id] = self.get_seckill_url() if not self.seckill_url[self.sku_id]: logger.error("无法获取商品抢购链接") return else: 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 _validate_cookies(self): """ 验证cookies是否有效(是否登陆) 通过访问用户订单列表页进行判断:若未登录,将会重定向到登陆页面。 :return: cookies是否有效 True/False """ url = 'https://order.suning.com/order/orderList.do' # url = 'https://www.suning.com/' try: resp = self.session.get(url=url, allow_redirects=True) if resp.url.find('suning.com/ids/login') < 0: return True # if resp.status_code == requests.codes.MOVED_PERMANENTLY: # self.session.get(resp.headers['Location']) # if resp.status_code == requests.codes.OK: # return True except Exception as e: logger.error("验证cookies是否有效发生异常", e) return False
def _get_seckill_init_info(self): """获取秒杀初始化信息(包括:地址,发票,token) :return: 初始化信息组成的dict """ logger.info('获取秒杀初始化信息...') url = 'https://marathon.jd.com/seckillnew/orderService/pc/init.action' data = { 'sku': self.sku_id, 'num': self.seckill_num, 'isModifyAddress': 'false', } headers = { 'User-Agent': self.default_user_agent, 'Host': 'marathon.jd.com', } resp = self.session.post(url=url, data=data, headers=headers) if not resp.text: logger.error('秒杀初始化信息未获取返回数据') self.push_log('秒杀初始化信息未获取返回数据') return return parse_json(resp.text)
def get_username(self): """获取用户信息""" url = 'https://passport.jd.com/user/petName/getUserInfoForMiniJd.action' payload = { 'callback': 'jQuery'.format(random.randint(1000000, 9999999)), '_': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.default_user_agent, 'Referer': 'https://order.jd.com/center/list.action', } resp = self.session.get(url=url, params=payload, headers=headers) try_count = 5 while not resp.text.startswith("jQuery"): try_count = try_count - 1 if try_count > 0: resp = self.session.get(url=url, params=payload, headers=headers) else: break self.wati_some_time() # 响应中包含了许多用户信息,现在在其中返回昵称 # jQuery2381773({"imgUrl":"//storage.360buyimg.com/i.imageUpload/xxx.jpg","lastLoginTime":"","nickName":"xxx","plusStatus":"0","realName":"xxx","userLevel":x,"userScoreVO":{"accountScore":xx,"activityScore":xx,"consumptionScore":xxxxx,"default":false,"financeScore":xxx,"pin":"xxx","riskScore":x,"totalScore":xxxxx}}) if not resp.text: logger.error('未获取返回数据') self.push_log('未获取返回数据') return logger.info('测试登录返回resp.text', parse_json(resp.text)) nick_name = parse_json(resp.text).get('nickName') if not nick_name: self.widget.signal_login.emit(self.cookies, '登录失败', 3) else: self.push_log('登录成功') self.widget.signal_login.emit(self.cookies, nick_name, 1) self.widget.signal_login.emit(self.cookies, '登录成功', 3) return nick_name
def make_reserve(self): """商品预约""" logger.info('商品名称:{}'.format(self.get_sku_title())) url = 'https://yushou.jd.com/youshouinfo.action?' payload = { 'callback': 'fetchJSON', 'sku': self.sku_id, '_': str(int(time.time() * 1000)), } headers = { 'User-Agent': self.user_agent, 'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id), } resp = self.session.get(url=url, params=payload, headers=headers) resp_json = parse_json(resp.text) reserve_url = resp_json.get('url') # 从api设定预约和抢购开始时间 reserve_stime = resp_json.get('yueStime') buy_stime = resp_json.get('qiangStime') self.timers.init_time(reserve_stime) self.timers.start('预约') while self.timers.enabled(): try: res = self.session.get(url='https:' + reserve_url) # 从api设定抢购开始时间 self.timers.init_time(buy_stime) if res.text.find("预约成功,已获得抢购资格") > 0: message = '预约成功,已获得抢购资格' if self.wechat_enable == 'true': send_wechat(message) if self.bark_enable == 'true': send_bark(message, 'detail') else: message = '您已成功预约过了,无需重复预约' logger.info(message) break except Exception as e: logger.error('预约失败正在重试...') wait_some_time()
def __init__(self, message): super().__init__(message) logger.error(message)