提示: 部分模块方法未自定义,就没贴了哈! 不过贴了注释javascript
#!/usr/bin/env python3 # -*- coding:utf-8 -*- # @Time: 2019/9/17 16:26 # @Author: 余浪人 # @email: yulangren520@gmail.com import asyncio import random from time import sleep import requests, base64, json, re from lxml import etree from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 as pk from pyppeteer import launch from conf import SpiderConf from my_mysql import mysql from my_redis import redis_write, redisCli session = requests.session() # 声明一个session prefix = SpiderConf.ZG_PREFIX # 前缀 baseUrl = 'https://passport.meituan.com' get_url = 'https://passport.meituan.com/account/unitivelogin?service=phoenix&continue=https%3A%2F%2Fwww.zhenguo.com%2Fauth%2Fauthenticated%2F%3Fcontinue%3D%252F&risk_partner=93' # 登陆地址 proxies = { "http": "http://113.138.138.244:3617", # 添加代理 } # 生成加密密码串 def createPassword(password: str): # 核心 网站加密前端采用非对称加密 public_key = '''-----BEGIN RSA PRIVATE KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRD8YahHualjGxPMzeIWnAqVGMIrWrrkr5L7gw+5XT55iIuYXZYLaUFMTOD9iSyfKlL9mvD3ReUX6Lieph3ajJAPPGEuSHwoj5PN1UiQXK3wzAPKcpwrrA2V4Agu1/RZsyIuzboXgcPexyUYxYUTJH48DeYBGJe2GrYtsmzuIu6QIDAQAB\n-----END RSA PRIVATE KEY----- ''' # 目前的公钥 pass_word = password.encode(encoding='utf-8') rsaKey = RSA.importKey(public_key) cipher = pk.new(rsaKey) cipherText = base64.b64encode(cipher.encrypt(pass_word)).decode('utf-8') return cipherText # 返回转换后的密码串> 用于登陆密码参数 # 登陆> 正常POST def baseLogin(account, password, requestCode=None, responseCode=None): # 常规登陆 global cookie headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'} # 头 response = session.get(get_url, headers=headers, proxies=proxies) # 获取登陆页面 cookie = requests.utils.dict_from_cookiejar(response.cookies) # 将获取到的cookie字典化 html_obj = etree.HTML(response.text) # 树对象 postUrl = baseUrl + ''.join(html_obj.xpath('//form[@id="J-normal-form"]/@action')) # 提取并构造完整url csrf = ''.join(html_obj.xpath('//span[@id="csrf"]/text()')) headers['Referer'] = get_url headers['X-CSRF-Token'] = csrf headers['X-Client'] = 'javascript' headers['X-Requested-With'] = 'XMLHttpRequest' param_data = { 'ountrycode': '86', 'email': account, 'password': password, 'origin': 'account-login', 'csrf': csrf, 'requestCode': requestCode, 'responseCode': responseCode, # 须要滑动验证码后获得 } # 构造登陆参数 response = session.post(postUrl, data=param_data, headers=headers, proxies=proxies) # 登陆请求 rawData = response.json() # 接收json响应 return rawData, response # 登陆用户信息获取 def acquireInfo(resData: dict, account: str, passWord: str): data = resData.get('data') token = data.get('token') # 登陆成功token _continue = data.get('continue') # 成功后跳转地址 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' } param_data = { 'token': token, 'expire': '0', 'isdialog': '0', 'autologin': '0', 'logintype': 'normal', } response = session.post(_continue, data=param_data, headers=headers, proxies=proxies) if response.status_code == 200: html = etree.HTML(response.text) # 树对象 imgUrl = 'https:' + ''.join(html.xpath('//img[@class="navbarDropdown__avatar"]/@src')) # 头像地址 userName = 'https:' + ''.join(html.xpath('//span[@class="navbarDropdown__text"]/text()')) # 昵称 userId = ''.join(''.join(html.xpath('//a[text()="个人主页"]/@href')).split('/')[-2:-1]) # 提取用户信息 response = session.get('https://www.zhenguo.com/?logout=1', headers=headers, proxies=proxies) if response.status_code == 200: cookies = requests.utils.dict_from_cookiejar(response.cookies) cookies['time_out'] = 30 cookies['_userID_'] = userId cookies['_userName_'] = userName cookies.update(cookie) # 添加自定义信息,方便获取及作自动cookie续期 redis_write(prefix, account, cookies) # cookie 存入reids mysql.autoUser(prefix, account, passWord, '榛果民宿', userImg=imgUrl, nickname=userName) # 用户存mysql 用户作自动登陆 return True # 成功返回True print('登陆成功, cookie获取失败!') return print('登陆后页面获取失败!') # 登陆入口 def loginMain(account: str, passWord: str): password = createPassword(passWord) rawData, response = baseLogin(account, password) if 'success' in json.dumps(rawData) and not rawData.get('success'): error = rawData.get('error').get('message') # 错误信息 errorCode = rawData.get('error').get('code') # 错误码 if errorCode == 101190: # 风控验证 >滑动验证码 responseData = gmailLogin(account, password) # 调用pyppeteer模拟登陆 elif errorCode == 101157: # 短信验证码 # dynamicStu = dynamicVerif(rawData) # 登陆短信验证时处理 responseData = {"status": 1, "msg": '动态验证失败,请稍后登陆!'} elif errorCode == 101005: # 密码错误 responseData = {"status": 1, "msg": error} elif errorCode == 101144: # 频繁提交 responseData = {"status": 1, "msg": error} else: responseData = {"status": 1, "msg": '登陆错误,请从新登陆!'} else: # 能够添加其余错误信息处理 loginStu = acquireInfo(rawData, account, passWord) responseData = {"status": 0, "msg": f'{account}: 登陆成功!'} if loginStu else {"status": 1, "msg": f'{account}: 异常,登陆失败!'} return responseData
须要其余方法能够邮件或留言哟!html