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.sess.post(url=select_url, data=data) remove_resp = self.sess.post(url=remove_url, data=data) if (not response_status(select_resp)) or ( not response_status(remove_resp)): print(get_current_time(), '购物车清空失败') return False print(get_current_time(), '购物车清空成功') return True except Exception as e: print(get_current_time(), e) return False
def _get_qrcode(self): """ 缓存并展示登录二维码 :return: """ url = 'https://passport.suning.com/ids/qrLoginUuidGenerate.htm?image=true&yys=%s' % str( time.time() * 1000)[:-5] headers = { 'User-Agent': self.spider_session.get_user_agent(), 'Referer': 'https://passport.suning.com/ids/login', } logger.info('登录二维码地址: %s' % url) resp = self.session.get(url=url, headers=headers) if not response_status(resp): logger.info('获取二维码失败') return False save_image(resp, self.qrcode_img_file) logger.info('二维码获取成功,请打开苏宁APP扫描') open_image(self.qrcode_img_file) if global_config.getRaw('messenger', 'email_enable') == 'true': email.send('二维码获取成功,请打开京东APP扫描', "<img src='cid:qr_code.png'>", [email.mail_user], 'qr_code.png') return True
def _get_qrcode(self): """ 缓存并展示登录二维码 :return: """ url = 'https://qr.m.jd.com/show' payload = { 'appid': 133, 'size': 147, 't': 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.info('获取二维码失败') return False img_file_name = '{}{}'.format('./cookies/', self.qrcode_img_file) save_image(resp, img_file_name) logger.info('二维码获取成功,请打开京东APP扫描') open_image(img_file_name) if global_config.getRaw('messenger', 'email_enable') == 'true': receivers = global_config.getRaw('messenger', 'email_receiver') email.send('二维码获取成功,请打开京东APP扫描', "<img src='cid:./cookies/qr_code.png'>", receivers.split(','), img_file_name) return True
def get_cart_detail(self): """获取购物车商品详情 :return: """ url = 'https://cart.jd.com/cart.action' cart_detail_format = '商品名称:{0}----单价:{1}----数量:{2}----总价:{3}' try: resp = self.sess.get(url=url) if not response_status(resp): print(get_current_time(), '获取购物车信息失败') return soup = BeautifulSoup(resp.text, "html.parser") print('************************购物车商品详情************************') for item in soup.select('div.item-form'): name = get_tag_value(item.select('div.p-name a')) price = get_tag_value(item.select('div.p-price strong')) quantity = get_tag_value( item.select('div.quantity-form input'), 'value') total_price = get_tag_value(item.select('div.p-sum strong')) print( cart_detail_format.format(name, price, quantity, total_price)) except Exception as e: print(get_current_time(), e)
def _get_qrcode(self): """ 缓存并展示登录二维码 :return: """ url = 'https://qr.m.jd.com/show' payload = { 'appid': 133, 'size': 300, 't': 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.info('获取二维码失败') return False save_image(resp, self.qrcode_img_file) logger.info('二维码获取成功,请打开京东APP扫描') open_image(add_bg_for_qr(self.qrcode_img_file)) if global_config.getRaw('messenger', 'email_enable') == 'true': email.send('二维码获取成功,请打开京东APP扫描', "<img src='cid:qr_code.png'>", [email.mail_user], 'qr_code.png') return True
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 _get_QRcode_ticket(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': USER_AGENT, 'Referer': 'https://passport.jd.com/new/login.aspx', } resp = self.sess.get(url=url, headers=headers, params=payload) if not response_status(resp): print(get_current_time(), '获取二维码扫描结果出错') return False resp_json = parse_json(resp.text) if resp_json['code'] != 200: print( get_current_time(), 'Code: {0}, Message: {1}'.format(resp_json['code'], resp_json['msg'])) return None else: print(get_current_time(), '已完成手机客户端确认') return resp_json['ticket']
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: res = self.session.get(url='https:' + reserve_url) if response_status(res): logger.info('预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约') if global_config.getRaw('messenger', 'enable') == 'true': success_message = "预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约" send_wechat(success_message) break except Exception as e: logger.error('预约失败正在重试...')
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 page_detail_captcha(session, isId): url = 'https://captcha.jd.com/verify/image' acid = '{}_{}'.format(random.random(), random.random()) payload = { 'acid': acid, 'srcid': 'trackWeb', 'is': isId, } headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Referer": "https://trade.jd.com/shopping/order/getOrderInfo.action", "Connection": "keep-alive", 'Host': 'captcha.jd.com', } try: resp = session.get(url=url, params=payload, headers=headers) if not response_status(resp): logger.error('获取订单验证码失败') return '' logger.info('解析验证码开始') image = Image.open(BytesIO(resp.content)) image.save('captcha.jpg') result = analysis_captcha(resp.content) if not result: logger.error('解析订单验证码失败') return '' global submit_captcha_text, submit_captcha_rid submit_captcha_text = result submit_captcha_rid = acid return result except Exception as e: logger.error('订单验证码获取异常:%s', e) return ''
def _get_qrcode(self): """ 缓存并展示登录二维码 :return: """ url = 'https://qr.m.jd.com/show' payload = { 'appid': 133, 'size': 147, 't': 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.info('获取二维码失败') return False save_image(resp, self.qrcode_img_file) logger.info('二维码获取成功,请打开京东APP扫描') open_image(self.qrcode_img_file) return True
def login_by_username(self): if self.is_login: print(get_current_time(), '登录成功') return True username = input('账号:') password = input('密码:') if (not username) or (not password): print(get_current_time(), '用户名或密码不能为空') return False self.username = username data = self._get_login_data() uuid = data['uuid'] auth_code = '' if self._need_auth_code(username): print(get_current_time(), '本次登录需要验证码') auth_code = self._get_auth_code(uuid) else: print(get_current_time(), '本次登录不需要验证码') login_url = "https://passport.jd.com/uc/loginService" payload = { 'uuid': uuid, 'version': 2015, 'r': random.random(), } data['authcode'] = auth_code data['loginname'] = username data['nloginpwd'] = encrypt_pwd(password) headers = { 'User-Agent': USER_AGENT, 'Origin': 'https://passport.jd.com', } resp = self.sess.post(url=login_url, data=data, headers=headers, params=payload) if not response_status(resp): print(get_current_time(), '登录失败') return False if not self._get_login_result(resp): return False # login success print(get_current_time(), '登录成功') self.nick_name = self.get_user_info() self._save_cookies() self.is_login = True return True
def analysis_captcha(session, captchaUrl, pic): for i in range(1, 10): try: url = captchaUrl resp = session.post(url, pic) if not response_status(resp): logger.error('解析验证码失败') continue logger.info('解析验证码[%s]', resp.text) return resp.text except Exception as e: print(traceback.format_exc()) continue return ''
def get_checkout_page_detail(self): """访问订单结算页面 该方法会打印出订单结算页面的详细信息:商品名称、价格、数量、库存状态等。 如果只是想下单商品,可以不调用该方法。 :return: """ url = 'http://trade.jd.com/shopping/order/getOrderInfo.action' # url = 'https://cart.jd.com/gotoOrder.action' payload = { 'rid': str(int(time.time() * 1000)), } try: resp = self.sess.get(url=url, params=payload) if not response_status(resp): print(get_current_time(), '获取订单结算页信息失败') return soup = BeautifulSoup(resp.text, "html.parser") self.risk_control = get_tag_value(soup.select('input#riskControl'), 'value') print('************************订单结算页详情************************') items = soup.select('div.goods-list div.goods-items')[1:] checkout_item_detail = '商品名称:{0}----单价:{1}----数量:{2}----库存状态:{3}' for item in items: name = get_tag_value(item.select('div.p-name a')) div_tag = item.select('div.p-price')[0] price = get_tag_value(div_tag.select('strong.jd-price'))[ 2:] # remove '¥ ' from the begin of price quantity = get_tag_value(div_tag.select('span.p-num'))[ 1:] # remove 'x' from the begin of quantity state = get_tag_value( div_tag.select('span.p-state')) # in stock or out of stock print(checkout_item_detail.format(name, price, quantity, state)) sum_price = soup.find('span', id='sumPayPriceId').text[ 1:] # remove '¥' from the begin of sum price address = soup.find('span', id='sendAddr').text[ 5:] # remove '收件人:' from the begin of receiver receiver = soup.find('span', id='sendMobile').text[ 4:] # remove '寄送至: ' from the begin of address print('应付总额:{0}'.format(sum_price)) print('收货地址:{0}----收件人:{1}'.format(address, receiver)) except Exception as e: print(get_current_time(), e)
def _validate_QRcode_ticket(self, ticket): url = 'https://passport.jd.com/uc/qrCodeTicketValidation' headers = { 'User-Agent': USER_AGENT, 'Referer': 'https://passport.jd.com/uc/login?ltype=logout', } resp = self.sess.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: print(get_current_time(), resp_json) return False
def _need_auth_code(self, username): url = 'https://passport.jd.com/uc/showAuthCode' data = { 'loginName': username, } payload = { 'version': 2015, 'r': random.random(), } resp = self.sess.post(url, params=payload, data=data, headers=self.headers) if not response_status(resp): print('获取是否需要验证码失败') return False resp_json = json.loads(resp.text[1:-1]) # ({"verifycode":true}) return resp_json['verifycode']
def _get_QRcode(self): url = 'https://qr.m.jd.com/show' payload = { 'appid': 133, 'size': 147, 't': str(int(time.time() * 1000)), } headers = { 'User-Agent': USER_AGENT, 'Referer': 'https://passport.jd.com/new/login.aspx', } resp = self.sess.get(url=url, headers=headers, params=payload) if not response_status(resp): print(get_current_time(), '获取二维码失败') return False QRCode_file = 'QRcode.png' save_image(resp, QRCode_file) print(get_current_time(), '二维码获取成功,请打开京东APP扫描') open_image(QRCode_file) return True
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
def _get_auth_code(self, uuid): image_file = os.path.join(os.getcwd(), 'jd_authcode.jpg') url = 'https://authcode.jd.com/verify/image' payload = { 'a': 1, 'acid': uuid, 'uid': uuid, 'yys': str(int(time.time() * 1000)), } headers = { 'User-Agent': USER_AGENT, 'Referer': 'https://passport.jd.com/uc/login', } resp = self.sess.get(url, params=payload, headers=headers) if not response_status(resp): print('获取验证码失败') return '' save_image(resp, image_file) open_image(image_file) return input('验证码:')
def get_checkout_page_detail(session): """获取订单结算页面信息 该方法会返回订单结算页面的详细信息:商品名称、价格、数量、库存状态等。 :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": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/531.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3", "Referer": "https://cart.jd.com/cart.action", "Connection": "keep-alive", 'Host': 'trade.jd.com', } try: resp = session.get(url=url, params=payload, headers=headers) if not response_status(resp): logger.error('获取订单结算页信息失败') return '' if '刷新太频繁了' in resp.text: return '刷新太频繁了' soup = BeautifulSoup(resp.text, "html.parser") risk_control = get_tag_value(soup.select('input#riskControl'), 'value') showCheckCode = get_tag_value(soup.select('input#showCheckCode'), 'value') if showCheckCode in ['false', 'False', 'FALSE']: pass else: if showCheckCode == 'true': logger.info('提交订单需要验证码') global is_Submit_captcha, encryptClientInfo encryptClientInfo = get_tag_value( soup.select('input#encryptClientInfo'), 'value') is_Submit_captcha = True order_detail = { 'address': soup.find('span', id='sendAddr').text[5:], # remove '寄送至: ' from the begin 'receiver': soup.find( 'span', id='sendMobile').text[4:], # remove '收件人:' from the begin 'total_price': soup.find( 'span', id='sumPayPriceId').text[1:], # remove '¥' from the begin 'items': [] } logger.info("下单信息:%s", order_detail) return risk_control except requests.exceptions.RequestException as e: logger.error('订单结算页面获取异常:%s' % e) except Exception as e: logger.error('下单页面数据解析异常:%s', e) return ''
def get_order_info(self, unpaid=True): """查询订单信息 :param unpaid: 只显示未付款订单,可选参数,默认为True :return: """ if not self.is_login: print(get_current_time(), '请先登录再查询订单!') return url = 'https://order.jd.com/center/list.action' payload = { 'search': 0, 'd': 1, 's': 4096, } # Orders for nearly three months headers = { 'User-Agent': USER_AGENT, 'Referer': 'https://passport.jd.com/uc/login?ltype=logout', } try: resp = self.sess.get(url=url, params=payload, headers=headers) if not response_status(resp): print(get_current_time(), '获取订单页信息失败') return soup = BeautifulSoup(resp.text, "html.parser") print('************************订单列表页查询************************') order_table = soup.find('table', {'class': 'order-tb'}) table_bodies = order_table.select('tbody') exist_order = False for table_body in table_bodies: # get order status order_status = get_tag_value( table_body.select('span.order-status')).replace( "订单状态:", "") # check if order is waiting for payment # wait_payment = bool(table_body.select('a.btn-pay')) wait_payment = "等待付款" in order_status # only show unpaid orders if unpaid=True if unpaid and (not wait_payment): continue exist_order = True # get order_time, order_id tr_th = table_body.select('tr.tr-th')[0] order_time = get_tag_value(tr_th.select('span.dealtime')) order_id = get_tag_value(tr_th.select('span.number a')) # get sum_price, pay_method sum_price = '' pay_method = '' amount_div = table_body.find('div', {'class': 'amount'}) if amount_div: spans = amount_div.select('span') pay_method = get_tag_value(spans, index=1) # if the order is waiting for payment, the price after the discount is shown. sum_price = get_tag_value(amount_div.select('strong'), index=1)[1:] if wait_payment \ else get_tag_value(spans, index=0)[4:] # get name and quantity of items in order items_dict = dict( ) # {'item_id_1': quantity_1, 'item_id_2': quantity_2, ...} tr_bds = table_body.select('tr.tr-bd') for tr_bd in tr_bds: item = tr_bd.find('div', {'class': 'goods-item'}) if not item: break item_id = item.get('class')[1][2:] quantity = get_tag_value( tr_bd.select('div.goods-number'))[1:] items_dict[item_id] = quantity order_info_format = '下单时间:{0}----订单号:{1}----商品列表:{2}----订单状态:{3}----总金额:{4}元----付款方式:{5}' print( order_info_format.format(order_time, order_id, parse_items_dict(items_dict), order_status, sum_price, pay_method)) if not exist_order: print(get_current_time(), '订单查询为空') except Exception as e: print(get_current_time(), e)