def __init__(self, username: str = None, password: str = None): self.site = 'zhihu' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.login_data = { 'captcha': '', 'client_id': 'c3cef7c66a1843f8b3a9e6a1e3160e20', 'grant_type': 'password', 'lang': 'en', 'password': '', 'ref_source': 'homepage', 'signature': '', 'source': 'com.zhihu.web', 'timestamp': '', 'username': '', 'utm_source': '' } self.session = requests.session() self.session.headers = { 'accept-encoding': 'gzip, deflate, br', 'accept-language': 'zh-CN,zh;q=0.9', 'origin': 'www.zhihu.com', 'referer': 'https://www.zhihu.com/signin?next=%2F', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' '(KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36' } # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'zhilian' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.browser = None self.wait = None
def __init__(self, username: str = None, password: str = None): self.site = 'meituan' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'github' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'yy' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Referer': 'http://www.yy.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0' } # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): # 网站 self.site = 'shixiseng' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Referer': 'https://www.shixiseng.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } # 密码错误重置 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'baidu' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/601.2.7 (KHTML, like Gecko) Version/9.0.1 Safari/601.2.7', 'Referer': 'https://pan.baidu.com/', } # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'liepin' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Referer': 'https://www.liepin.com/', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36', 'DNT': '1', } # 密码错误重置初始化 self.reset_flag = False self.timestamp = str(int(time.time() * 1000))
def __init__(self, username: str = None, password: str = None, headless=False): self.site = 'toutiao' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.browser = None self.wait = None self.headless = headless # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'iqiyi' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Origin': 'http://www.iqiyi.com', 'Referer': 'http://www.iqiyi.com/iframe/loginreg?ver=1', "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36" } # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'migu' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Referer': 'https://passport.migu.cn/login?sourceid=220001&apptype=0&forceAuthn=false&isPassive=false&authType=MiguPassport&passwordControl=0&display=web&referer=http://music.migu.cn/v3&logintype=1&qq=null&weibo=null&alipay=null&weixin=null&phoneNumber=&callbackURL=http%3A%2F%2Fmusic.migu.cn%2Fv3&relayState=', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36', 'X-Requested-With': 'XMLHttpRequest' } # 密码错误重置初始化 self.reset_flag = False self.ctx = self._load_js()
def __init__(self, username: str = None, password: str = None): self.site = 'lol' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0' } # 密码错误重置初始化 self.reset_flag = False with open('encrypt.js', 'rb') as f: js = f.read().decode() self.ctx = execjs.compile(js)
def __init__(self, username: str = None, password: str = None): self.site = 'weibo' self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.username = username self.password = password self.session = requests.session() self.session.headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': 'https://weibo.com/', 'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Mobile Safari/537.36' } # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'renren' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } with open('encryptPwd.js', 'rb') as f: js = f.read().decode() self.ctx = execjs.compile(js) # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'xmly' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Host': 'www.ximalaya.com', 'Referer': 'https://www.ximalaya.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } # 密码错误重置初始化 self.reset_flag = False with open('signature.js', 'rb') as f: js = f.read().decode() self.ctx = execjs.compile(js)
def __init__(self, username: str = None, password: str = None): self.site = 'qixinbao' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Content-Type': 'application/json;charset=UTF-8', # payload提交表单参数, 请求头中必须含有 Content-Type, 并且提交方法为 json.dumps(data) 'Referer': 'https://www.qixin.com/auth/login?return_url=%2F', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36', 'X-Requested-With': 'XMLHttpRequest' } # 密码错误重置 self.reset_flag = False with open('encrypt.js', 'rb') as f: js = f.read().decode() self.ctx = execjs.compile(js) self.codes = self.get_codes()
def __init__(self, username: str = None, password: str = None): self.site = 'huya' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'content-type': 'application/json;charset=UTF-8', 'lcid': '2052', 'uri': '30001', 'Origin': 'https://udblgn.huya.com', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'qimai' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Origin': 'https://www.qimai.cn', 'Referer': 'https://www.qimai.cn/account/signin/r/%2Frank%2Findex%2Fbrand%2Ffree%2Fcountry%2Fcn%2Fgenre%2F5000%2Fdevice%2Fiphone', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = 'meituan' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Referer': 'https://epassport.meituan.com/account/unitivelogin?bg_source=3&service=waimai&platform=2&continue=http://e.waimai.meituan.com/v2/epassport/entry&left_bottom_link=%2Faccount%2Funitivesignup%3Fbg_source%3D3%26service%3Dwaimai%26platform%3D2%26continue%3Dhttp%3A%2F%2Fe.waimai.meituan.com%2Fv2%2Fepassport%2FsignUp%26extChannel%3Dwaimaie%26ext_sign_up_channel%3Dwaimaie&right_bottom_link=%2Faccount%2Funitiverecover%3Fbg_source%3D3%26service%3Dwaimai%26platform%3D2%26continue%3Dhttp%3A%2F%2Fe.waimai.meituan.com%2Fv2%2Fepassport%2FchangePwd', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36' } with open('./js/encrypt_pwd.js', 'rb') as f: self.pwd_js = f.read().decode() with open('./js/slider.js', 'rb') as f: self.slider_js = f.read().decode() with open('./js/token.js', 'rb') as f: self.token_js = f.read().decode() # 密码错误重置初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = '163email' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Content-Type': 'application/json', 'Origin': 'https://dl.reg.163.com', 'Referer': 'https://dl.reg.163.com/webzj/v1.0.1/pub/index_dl2_new.html?cd=https%3A%2F%2Fmimg.127.net%2Fp%2Ffreemail%2Findex%2Funified%2Fstatic%2F2019%2Fcss%2F&cf=urs.163.bc0e7491.css&MGID=1561887066637.6414&wdaId=&pkid=CvViHzl&product=mail163', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36', } with open('encryptEnvinfo.js', 'r') as f: self.js = f.read() self.ctx = execjs.compile(self.js) self.rtid = self.ctx.call('getRtid') # 密码错误重试初始化 self.reset_flag = False
def __init__(self, username: str = None, password: str = None): self.site = '163email' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Content-Type': 'application/json', 'Origin': 'https://dl.reg.163.com', 'Referer': 'https://mail.163.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36', } with open('encryptEnvinfo.js', 'r') as f: self.js = f.read() self.ctx = execjs.compile(self.js) self.rtid = self.ctx.call('getRtid') # 密码错误重试初始化 self.reset_flag = False
class RenrenLogin: def __init__(self, username: str = None, password: str = None): self.site = 'renren' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } with open('encryptPwd.js', 'rb') as f: js = f.read().decode() self.ctx = execjs.compile(js) # 密码错误重置初始化 self.reset_flag = False def check_islogin(self, cookies): """ 检查是否登录成功 :return: """ res = self.session.get('http://www.renren.com/home', cookies=cookies) if 'hd-name' in res.text: bsobj = BeautifulSoup(res.text, 'lxml') nickname = bsobj.select('.hd-name')[0].get_text() self.logger.info('Cookies 有效! ') self.logger.info(f'Hello, {nickname}! ') return True return False def _init_cookies(self): """ 访问首页初始化 Cookie :return: """ self.session.get('http://www.renren.com/') def _get_rkey(self): """ 获取加密所需密钥和 rkey 参数 :return: """ url = 'http://login.renren.com/ajax/getEncryptKey' res = self.session.get(url).json() if res['isEncrypt']: iv = res['e'] encryptKey = res['n'] rkey = res['rkey'] return iv, encryptKey, rkey raise Exception('获取密钥出错! ') def _encrypt_pwd(self, iv, encryptKey): return self.ctx.call('encrypt', self.password, iv, encryptKey) def _get_uniquetimestamp(self): return self.ctx.call('getUniqueTimestamp') def _show_captcha(self): """ 访问接口判断是否需要验证码 :return: """ url = 'http://www.renren.com/ajax/ShowCaptcha' data = {'email': self.username, '_rtk': 'a0cdef52'} res = self.session.post(url, data=data) if '0' in res.text: self.logger.info('此次登录无需验证码! ') return False return True def _get_verifycode(self): captcha_url = 'http://icode.renren.com/getcode.do?t=web_login&rnd=0.28838133194471105' img_data = self.session.get(captcha_url).content self.logger.info('使用超级鹰识别验证码...') ok, result = image_to_text(img_data) if ok: self.logger.info('成功识别验证码!') return result raise Exception('验证码识别失败: ', result) @loopUnlessSeccessOrMaxTry(3, sleep_time=3) def login(self): params = {'1': 1, 'uniqueTimestamp': self._get_uniquetimestamp()} login_api = 'http://www.renren.com/ajaxLogin/login?' + urlencode( params) self._init_cookies() iv, encryptKey, rkey = self._get_rkey() pwd = self._encrypt_pwd(iv, encryptKey) flag = self._show_captcha() if flag: icode = self._get_verifycode() else: icode = '' data = { 'email': self.username, 'icode': icode, 'origURL': 'http://www.renren.com/home', 'domain': 'renren.com', 'key_id': '1', 'captcha_type': 'web_login', 'password': pwd, 'rkey': rkey, 'f': 'http%3A%2F%2Fwww.renren.com%2F971788971' } self.session.headers['Referer'] = 'http://www.renren.com/SysHome.do' res = self.session.post(login_api, data=data) if 'failCode' not in res.text: self.logger.info('登录成功! ') resp = self.session.get('http://www.renren.com/home', allow_redirects=False) redirect_url = resp.headers['location'] cookies = self.session.cookies.get_dict() # 巨坑... 这里返回的 cookies 中的 t 的值需要替换为 societyguester 的值 # 真正起作用的 cookie 就是 t这个键 和 societyguester 的值, 其他 cookie 可以不要。 cookies['t'] = cookies['societyguester'] self.redis_client.save_cookies(self.site, self.username, cookies) response = self.session.get(redirect_url) bsobj = BeautifulSoup(response.text, 'lxml') nickname = bsobj.select('.hd-name')[0].get_text() self.logger.info('Hello, {}! '.format(nickname)) return True elif res.json()['failCode'] == 128: self.reset_flag = True raise Exception('账号或密码错误! ') elif res.json()['failCode'] == 512: raise Exception(res.json()['failDescription']) raise Exception('登录失败! ') @check_user() def run(self, load_cookies: bool = True): """ 主函数运行 :return: """ if load_cookies: cookies = self.redis_client.load_cookies(self.site, self.username) if cookies: if self.check_islogin(cookies): return True self.logger.warning('Cookies 已过期! ') self.login()
class ZhipinLogin: def __init__(self, username: str = None, password: str = None): self.site = 'zhipin' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) async def check_islogin(self, cookies): """ 检查登录状态: 访问首页, 出现用户名则登录成功 :param page: :return: """ url = 'https://www.zhipin.com/geek/new/index/recommend?ka=header-personal' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299' } res = requests.get(url, headers=headers, cookies=cookies) if '登录' not in res.text: self.logger.info('Cookies 有效! ') nickname = re.search('name:"(.*?)"', res.text).group(1) self.logger.info('Hello, {}! '.format(nickname)) return True return False @staticmethod def input_time_random(): return random.randint(150, 201) def retry_if_result_none(self, result): self.logger.warning('滑块判定失败, 重试!') return result is None async def login(self): browser = await launch( { 'headless': False, 'args': ['--no-sandbox', '--disable-infobars'], }, # userDataDir=r'D:\login\userdata', # 这个文件会记录pyppeteer浏览器的cookie args=['--window-size=1366, 768'] ) page = await browser.newPage() # 启动个新的浏览器页面 await page.setJavaScriptEnabled(enabled=True) # 启用js await page.setUserAgent( 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299' ) # 设置模拟浏览器 self.logger.info('尝试登录...') await page.goto('https://www.zhipin.com/user/login.html') await self.page_evaluate(page) time.sleep(2) time.sleep(1) await page.type('input[name="account"]', self.username, {'delay': self.input_time_random() - 50}) time.sleep(1) await page.type('input[name="password"]', self.password, {'delay': self.input_time_random()}) # await page.screenshot({'path': './headless-test-result.png'}) # 截图测试 time.sleep(2) self.logger.info('拉动滑块验证...') # await page.screenshot({'path': './headless-login-slide.png'}) # 截图测试 flag = await self.mouse_slide(page=page) # js拉动滑块 if flag: # await page.keyboard.press('Enter') await page.click('button.btn') await page.waitFor(20) await page.waitForNavigation() # 等待跳转 try: global error error = await page.Jeval('.dialog-con', 'node => node.textContent') # 检测是否是账号密码错误 except Exception as e: error = None self.logger.info("登录成功! ") finally: if error: error = await (await (await page.xpath('//div[@class="dialog-con"]'))[0].getProperty('textContent')).jsonValue() self.logger.info(error) else: await asyncio.sleep(3) cookies = await page.cookies() # cookies = {item['name']: item['value'] for item in cookies} self.redis_client.save_cookies(self.site, self.username, cookies) else: self.logger.error('验证失败! ') await self.page_close(browser) async def page_evaluate(self, page): await page.evaluate( '''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => undefined } }) }''') # 以下为插入中间js,将淘宝会为了检测浏览器而调用的js修改其结果。 await page.evaluate('''() =>{ window.navigator.chrome = { runtime: {}, }; }''') await page.evaluate( '''() =>{ Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] }); }''') await page.evaluate( '''() =>{ Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5,6], }); }''') async def page_close(self, browser): """ 关闭浏览器驱动 :param browser: :return: """ for _page in await browser.pages(): await _page.close() await browser.close() # @retry(retry_on_result=retry_if_result_none, ) async def mouse_slide(self, page=None): await asyncio.sleep(3) try: # 鼠标移动到滑块,按下,滑动到头(然后延时处理),松开按键 await page.hover('.btn_slide') await page.mouse.down() # 模拟按下鼠标 await page.mouse.move(2000, 0, {'delay': random.randint(1000, 2000)}) # js模拟拖动 await page.mouse.up() # 模拟松开鼠标 except Exception as e: return None, page else: await asyncio.sleep(2) slider_again = await page.Jeval('.nc-lang-cnt', 'node => node.textContent') # 判断是否通过 if slider_again != '验证通过': return None, page else: # await page.screenshot({'path': './headless-slide-result.png'}) # 截图测试 self.logger.info('验证通过! ') return 1, page @check_user() async def run(self, load_cookies: bool = True): if load_cookies: cookies = self.redis_client.load_cookies(self.site, self.username) cookies = {item['name']: item['value'] for item in cookies} if cookies: if await self.check_islogin(cookies): return True self.logger.warning('cookies 已过期! ') await self.login()
class BaiduLogin: def __init__(self, username: str = None, password: str = None): self.site = 'baidu' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/601.2.7 (KHTML, like Gecko) Version/9.0.1 Safari/601.2.7', 'Referer': 'https://pan.baidu.com/', } # 密码错误重置初始化 self.reset_flag = False def check_islogin(self, cookies): """ ... :param cookies: :return: """ pass def _init_cookies(self): """ 访问百度网盘首页初始化 cookies :return: """ self.session.get('https://pan.baidu.com/') @staticmethod def _get_gid(): return str(uuid4()).upper() def _get_token(self, gid): """ 获取登录 token 认证 :return: """ url = 'https://passport.baidu.com/v2/api/?getapi' params = { 'getapi': '', 'tpl': 'mn', 'apiver': 'v3', 'tt': str(int(time.time() * 1000)), 'class': 'login', 'gid': gid, 'loginversion': 'v4', 'logintype': 'dialogLogin', 'traceid': '', 'callback': 'bd__cbs__pivyke', } resp = self.session.get(url=url, params=params) js = parse_json(resp.text.replace("\'", "\"")) return js['data']['token'] def _get_public_key(self, gid, token): """ 获取 RSA 加密公钥 :return: """ url = 'https://passport.baidu.com/v2/getpublickey' params = { 'token': token, 'tpl': 'mn', 'apiver': 'v3', 'tt': str(int(time.time() * 1000)), 'gid': gid, 'loginversion': 'v4', 'traceid': '', 'callback': 'bd__cbs__h02h0j' } resp = self.session.get(url=url, params=params) js = parse_json(resp.text.replace("\'", "\"")) key, public_key = js.get('key'), js.get('pubkey') return key, public_key def _encrypt_pwd(self, public_key): rsa_key = RSA.importKey(public_key) encryptor = Cipher_pkcs1_v1_5.new(rsa_key) cipher = b64encode(encryptor.encrypt(self.password.encode('utf-8'))) return cipher.decode('utf-8') def _get_verifycode(self, code_string): """ 使用超级鹰识别验证码 :param pcid: :return: """ captcha_url = f'https://passport.baidu.com/cgi-bin/genimage?{code_string}' img_data = self.session.get(captcha_url).content self.logger.info('使用超级鹰识别验证码...') ok, result = image_to_text(img_data) if ok: self.logger.info('成功识别验证码!') return result raise Exception('验证码识别失败: ', result) def _verify_phone(self, authtoken, lstr, ltoken, loginproxy): """ 手机验证 :return: """ url = 'https://passport.baidu.com/v2/sapi/authwidgetverify?' params = { "authtoken": authtoken, "type": "mobile", "jsonp": "1", "apiver": "v3", "verifychannel": "", "action": "getapi", "vcode": "", "questionAndAnswer": "", "needsid": "", "rsakey": "", "countrycode": "", "subpro": "", "u": "https://www.baidu.com/", "lstr": lstr, "ltoken": ltoken, "tpl": "mn", "winsdk": "", "authAction": "", "traceid": "00BC1501", "callback": "bd__cbs__h3w9ui" } res = self.session.get(url, params=params) encode_str = res.text.replace( 'bd__cbs__h3w9ui(', '').replace(')', '').replace('{', '').replace( '}', '').replace('"', '').replace("'", '').replace(' ', '') result = { item.split(':')[0]: item.split(':')[1] for item in encode_str.split(',') } if result['errno'] == '110000': self.logger.info('成功请求验证码接口! ') params.update({ "action": "send", }) resp = self.session.get(url, params=params) encode_str = resp.text.replace('bd__cbs__h3w9ui(', '').replace( ')', '').replace('{', '').replace('}', '').replace('"', '').replace( "'", '').replace(' ', '') result = { item.split(':')[0]: item.split(':')[1] for item in encode_str.split(',') } if result['errno'] == '110000': self.logger.info('验证码发生中, 请注意接收...') time.sleep(1) verify_code = input('请输入验证码 >> \n') params.update({ "action": "check", "vcode": verify_code, }) respo = self.session.get(url, params=params) encode_str = respo.text.replace( 'bd__cbs__h3w9ui(', '').replace(')', '').replace('{', '').replace('}', '').replace( '"', '').replace("'", '').replace(' ', '') result = { item.split(':')[0]: item.split(':')[1] for item in encode_str.split(',') } if result['errno'] == '110000': self.logger.info('手机验证成功! ') response = self.session.get(loginproxy) print(response.text) return True elif result['errno'] == '110002': self.logger.error(result['msg']) return False @loopUnlessSeccessOrMaxTry(3, sleep_time=3) def login(self): self._init_cookies() gid = self._get_gid() token = self._get_token(gid) key, public_key = self._get_public_key(gid, token) pwd = self._encrypt_pwd(public_key) login_api = 'https://passport.baidu.com/v2/api/?login' data = { 'staticpage': 'https://www.baidu.com/cache/user/html/v3Jump.html', 'charset': 'UTF-8', 'token': token, 'tpl': 'netdisk', 'subpro': 'netdisk_web', 'apiver': 'v3', 'tt': str(int(time.time() * 1000)), 'codestring': '', 'safeflg': '0', 'u': 'https://www.baidu.com/', 'isPhone': 'false', 'detect': '1', 'gid': gid, 'quick_user': '******', 'logintype': 'dialogLogin', 'logLoginType': 'pc_loginDialog', 'idc': '', 'loginmerge': 'true', 'splogin': '******', 'username': self.username, 'password': pwd, 'rsakey': key, 'crypttype': '12', 'ppui_logintime': 389548, 'countrycode': '', 'loginversion': 'v4', 'traceid': '', 'callback': 'parent.bd__pcbs__oxzeyj' } for _ in range(10): resp = self.session.post(login_api, data=data) result_str = re.search(r'.*href \+= "(.*)"\+accounts', resp.text).group(1) result = { x.split('=')[0]: x.split('=')[1] for x in result_str.split('&') } if result['err_no'] == '0': self.logger.info('登录成功! ') cookies = resp.cookies.get_dict() self.redis_client.save_cookies(self.site, self.username, cookies) return True elif result['err_no'] in {'6', '257'}: code_str = result.get('codeString') self.logger.warning('请输入验证码! ') verify_code = self._get_verifycode(code_str) data.update({ 'codestring': code_str, 'verifycode': verify_code }) elif result['err_no'] == '120021': self.logger.warning('账号存在风险, 请进行手机验证! ') authtoken = result['authtoken'] lstr = result['lstr'] ltoken = result['ltoken'] loginproxy = result['loginproxy'] flag = self._verify_phone(authtoken, lstr, ltoken, loginproxy) if not flag: return elif result['err_no'] in {'4', '7'}: self.reset_flag = True raise Exception('账号或密码错误! ') @check_user() def run(self, load_cookies: bool = True): if load_cookies: cookies = self.redis_client.load_cookies(self.site, self.username) if cookies: if self.check_islogin(cookies): return True self.logger.warning('Cookies 已过期') self.login()
class IQiyiLogin: def __init__(self, username: str = None, password: str = None): self.site = 'iqiyi' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Origin': 'http://www.iqiyi.com', 'Referer': 'http://www.iqiyi.com/iframe/loginreg?ver=1', "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36" } # 密码错误重置初始化 self.reset_flag = False def check_islogin(self, cookies): url = 'http://www.iqiyi.com/u/point' res = self.session.get(url, cookies=cookies) if 'ucbannerName' in res.text: self.logger.info('Cookies 有效! ') bsobj = BeautifulSoup(res.text, 'lxml') nickname = bsobj.select('#ucbannerName')[0].get_text().strip() self.logger.info('Hello, {}! '.format(nickname)) return True return False def _encrypt_pwd(self): """ 加密密码 :return: """ with open('iqiyiPwdEncrypt.js', 'r') as f: js = f.read() ctx = execjs.compile(js) return ctx.call('rsaFun', self.password) def _get_areacode(self): """ 获取地区编码 :return: """ url = 'https://passport.iqiyi.com/apis/phone/get_support_areacode.action' data = { 'use_case': '1', 'local': '1', 'agenttype': '1', 'fromSDK': '1', 'ptid': '01010021010000000000', 'sdk_version': '1.0.0' } r = self.session.post(url, data=data).json() code_dict = r['data']['acode'] return code_dict @loopUnlessSeccessOrMaxTry(3, sleep_time=3) def login(self): """ 登录, 只有一个加密参数密码, 其他为定值 :return: """ url = 'https://passport.iqiyi.com/apis/reglogin/login.action' encrypt_pwd = self._encrypt_pwd() data = { 'email': self.username, 'fromSDK': '1', 'sdk_version': '1.0.0', 'passwd': encrypt_pwd, 'agenttype': '1', '__NEW': '1', 'checkExist': '1', 'lang': '', 'ptid': '01010021010000000000', 'nr': '1', 'verifyPhone': '1', 'area_code': '86', 'env_token': 'c225a3e03fdf4c90a9227af2f0abd8bb', 'dfp': 'a06e54c2dfe5d24ebf8aec1c2d0a8f5afb2fc70fd2a147f7ab9e5aea7cff440f9e', 'envinfo': 'eyJqbiI6Ik1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdPVzY0OyBydjo2Ny4wKSBHZWNrby8yMDEwMDEwMSBGaXJlZm94LzY3LjAiLCJjbSI6InpoLUNOIiwiZ3UiOjI0LCJ1ZiI6MSwianIiOlsxMzY2LDc2OF0sImRpIjpbMTM2Niw3MjhdLCJ6cCI6LTQ4MCwidWgiOjEsInNoIjoxLCJoZSI6MSwicnYiOiJ1bmtub3duIiwibngiOiJXaW4zMiIsIml3IjoidW5zcGVjaWZpZWQiLCJxbSI6W10sIndyIjoiOWUzYjk5MzFhNzBiMGQwZDI0NGU1ZTg1MTAyZGJiYTAiLCJ3ZyI6IjRlMzVhYWVjZTM2NTU0YTM5MGQwYWU1MDNlZDljOTM0IiwiZmsiOmZhbHNlLCJyZyI6ZmFsc2UsInh5IjpmYWxzZSwiam0iOmZhbHNlLCJiYSI6ZmFsc2UsInRtIjpbMCxmYWxzZSxmYWxzZV0sImF1Ijp0cnVlLCJtaSI6IjQ1MjY1MDUxLWM3MjItNTcyOC00OGY3LWJiMjA3N2NlMGVhMCIsImNsIjoiUENXRUIiLCJzdiI6IjEuMCIsImpnIjoiNTE3YzNiNDk0NzFlMTJiZTc0N2QzYWI3MWY1YTM1OTMiLCJmaCI6ImhydWtvdjY0OW15OGV1YnB4Ym9uMThuayIsImlmbSI6W3RydWUsNDYwLDQyMCwiaHR0cDovL3d3dy5pcWl5aS5jb20vIl0sImV4IjoiIiwicHYiOmZhbHNlfQ==' } while True: res = self.session.post(url, data=data) cookies = res.cookies.get_dict() if res.json()['code'] == 'A00000': self.logger.info('登录成功! ') self.logger.info('Hello, {}! '.format(res.json()['data']['nickname'])) self.redis_client.save_cookies(self.site, self.username, cookies) return True elif res.json()['code'] == 'P00117': self.reset_flag = True raise Exception('账号或密码错误! ') token = res.json()['data']['data']['token'] data.update({'env_token': token}) self.logger.info(f'{res.json()["msg"]}, env_token更新为: {token}') time.sleep(random.random()) def get_userinfo(self, cookies): """ 获取用户信息 :return: """ url = 'https://passport.iqiyi.com/apis/user/info.action' code_dict = self._get_areacode() with open('antiCsrf.js', 'rb') as f: js = f.read().decode() ctx = execjs.compile(js) try: auth_cookie = cookies['P00001'] anticsrf = ctx.call('getAnticsrf', auth_cookie) data = { 'agenttype': '1', 'ptid': '01010021010000000000', 'lang': '', 'fromSDK': '1', 'sdk_version': '1.0.0', 'authcookie': auth_cookie, 'antiCsrf': anticsrf, 'fields': 'insecure_account,userinfo' } r = requests.post(url, data=data) user_info = r.json()['data']['userinfo'] jointime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(user_info['jointime']))) if user_info['gender'] == 1: gender = '男' else: gender = '女' area_code = user_info['area_code'] for code in code_dict.keys(): if area_code == code: area = code_dict[code] if user_info['birthday']: birthday = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(user_info['birthday']))) user_info.update({'birthday': birthday, 'jointime': jointime, 'gender': gender, 'area': area}) # 移除地区代码 del user_info['area_code'] self.logger.info(f'您的基本信息为: {user_info}') return True except: return False @check_user() def run(self, load_cookies: bool = True): """ 主函数 :return: """ if load_cookies: cookies = self.redis_client.load_cookies(self.site, self.username) if cookies: if self.check_islogin(cookies): info_flag = input('是否显示用户信息? (yes/no) \n') if info_flag == 'yes': self.get_userinfo(cookies) return True self.logger.warning('Cookies 已过期') self.login()
class HuyaLogin: def __init__(self, username: str = None, password: str = None): self.site = 'huya' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'content-type': 'application/json;charset=UTF-8', 'lcid': '2052', 'uri': '30001', 'Origin': 'https://udblgn.huya.com', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } # 密码错误重置初始化 self.reset_flag = False def check_islogin(self, cookies): """ 检查登录, 请求用户主页若出现用户名则登录成功 :return: """ res = self.session.get('https://i.huya.com/', cookies=cookies) bsobj = BeautifulSoup(res.text, 'lxml') if bsobj.find('h2', {'class': 'uesr_n'}): nickname = bsobj.find('h2', {'class': 'uesr_n'}).get_text() self.logger.info('登录成功! ') self.logger.info('Hello, {}! '.format(nickname)) self.redis_client.save_cookies(self.site, self.username, cookies) return True return False def _get_sdid(self): url = 'https://udblgn.huya.com/web/middle/2.3/37893475/https/787b6ffa5e4c42a99091ab91d071ed2a' resp = self.session.get(url) sdid = re.search(r'HyUDBWebSDK_Exchange.init\((.*?)\);', resp.text).group(1) return sdid def encrypt(self): with open('encrypt.js', 'rb') as f: js = f.read().decode() ctx = execjs.compile(js) password = ctx.call('encryptPwd', self.password) request_id = ctx.call('getRequestId', 1) page = ctx.call('getPage', 'https://www.huya.com/l') # 页面cookie, 没有测试过期时间 context = ctx.call( 'getContext', '__yamid_tt1=0.1232795775887836; __yamid_new=C875D5606C80000176AD12EEAE0014D2; SoundValue=0.50; alphaValue=0.80; guid=3ad7b83861a9ea5c33512be62ce6b2fa; Hm_lvt_51700b6c722f5bb4cf39906a596ea41f=1558882650,1559909095,1559998946; __yasmid=0.1232795775887836; udb_passdata=3; isInLiveRoom=true; udb_guiddata=787b6ffa5e4c42a99091ab91d071ed2a; web_qrlogin_confirm_id=bf407b38-0a04-453a-8899-c93acf12f406; h_unt=1560003929; Hm_lpvt_51700b6c722f5bb4cf39906a596ea41f=1560003939; __yaoldyyuid=; _yasids=__rootsid%3DC87A02DEAC400001CC501DC016A81329; PHPSESSID=qdd0udkruqk8mi2u0unr4p53r5' ) return password, request_id, page, context @loopUnlessSeccessOrMaxTry(3, sleep_time=3) def login(self): sdid = self._get_sdid() password, request_id, page, context = self.encrypt() self.session.headers.update({ 'context': context, 'reqid': str(request_id), 'Referer': 'https://udblgn.huya.com/web/middle/2.3/854732/https/{}'.format( context.split('-')[1]) }) payload = { 'appId': "5002", 'byPass': "******", 'context': context, 'data': { 'userName': "******", 'password': password, 'domainList': "", 'behavior': "%5B%7B%22page.login%22%3A%220.073%22%7D%2C%7B%22input.l.account%22%3A%222.856%22%7D%2C%7B%22input.l.passwd%22%3A%225.37%22%7D%2C%7B%22button.UDBSdkLogin%22%3A%228.387%2C138%2C254%22%7D%5D", 'page': page, 'randomStr': "", 'remember': "1" }, 'lcid': "2052", 'requestId': str(request_id), 'sdid': str(sdid), 'smid': "", 'uri': "30001", 'version': "2.4" } url = 'https://udblgn.huya.com/web/v2/passwordLogin' res = self.session.post(url, data=json.dumps(payload)) cookies = res.cookies.get_dict() if self.check_islogin(cookies): return cookies elif res.json()['description'] == '账号或密码错误': self.reset_flag = True raise Exception('账号或密码错误! ') raise Exception('登录失败: {}'.format(res.json()['description'])) @check_user() def run(self, load_cookies: bool = True): if load_cookies: cookies = self.redis_client.load_cookies(self.site, self.username) if cookies: if self.check_islogin(cookies): return cookies self.logger.warning('Cookies 已过期') return self.login()
class LOLLogin: def __init__(self, username: str = None, password: str = None): self.site = 'lol' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Connection': 'keep-alive', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Firefox/68.0' } # 密码错误重置初始化 self.reset_flag = False with open('encrypt.js', 'rb') as f: js = f.read().decode() self.ctx = execjs.compile(js) def check_islogin(self, cookies): params = { 'use': 'zm,uid,acc', 'area': '19', 'season': 's9', 'callback': 'jQuery191005632563829884707_{}'.format(int(time.time() * 1000)), '_': int(time.time() * 1000) } url = 'https://lol.ams.game.qq.com/lol/autocms/v1/transit/LOL/LOLWeb/Official/MobilePlayerInfo,PlayerCommunityInfo,PlayerInfo,PlayerBattleSummary,PlayerHonor,PlayerProperty,PlayerRankInfo?' + urlencode( params) res = self.session.get(url, cookies=cookies) result = json.loads( re.search(r'{}\((.*?)\)'.format(params['callback']), res.text).group(1)) if result['MobilePlayerInfo']['status'] == 0: self.logger.info('Cookies 有效! ') nickname = result['MobilePlayerInfo']['msg']['res'][ 'uuid_prifle_list'][0]['nick'] self.logger.info('Hello, {}! '.format(nickname)) gamename = result['PlayerInfo']['msg']['name'] self.logger.info('你的游戏昵称: {}'.format(gamename)) self.logger.info('查看战绩请按 1, 结束请按 0 >>') flag = int(input()) if flag: seasons = result['PlayerBattleSummary']['msg']['data'][ 'item_list'] for season in seasons: self.logger.info(season) return True return True return False def _init_cookies(self): self.session.get('https://mail.qq.com/') def _get_login_sig(self): res = self.session.get( 'https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https://game.qq.com/comm-htdocs/milo/proxy.html&appid=21000501&target=top&s_url=https%3A%2F%2Flol.qq.com%2Fmain.shtml&style=20&daid=8' ) cookies = res.cookies.get_dict() login_sig = cookies['pt_login_sig'] return cookies, login_sig def _get_salt(self, login_sig): url = 'https://ssl.ptlogin2.qq.com/check?' params = { 'regmaster': '', 'pt_tea': '2', 'pt_vcode': '1', 'uin': self.username, 'appid': 21000501, 'js_ver': '19072517', 'js_type': 1, 'login_sig': login_sig, 'u1': 'https://lol.qq.com/main.shtml', 'r': self.ctx.call('get_random_num'), 'pt_uistyle': '40' } res = self.session.get(url, params=params) pt_verifysession_v1 = res.text.split(',')[3].replace("'", '') verify_code = res.text.split(',')[1].replace("'", '') salt = res.text.split(',')[2].replace("'", '') salt = salt.encode().decode('unicode_escape') ptdrvs = res.text.split(',')[5].replace("'", '').replace(')', '').strip() return pt_verifysession_v1, verify_code, salt, ptdrvs def _encrypt_pwd(self, salt, verify_code): return self.ctx.call('encrypt_pwd', self.password, salt, verify_code) @loopUnlessSeccessOrMaxTry(3, sleep_time=3) def login(self): self._init_cookies() login_api = 'https://ssl.ptlogin2.qq.com/login?' login_sig = self._get_login_sig() pt_verifysession_v1, verify_code, salt, ptdrvs = self._get_salt( login_sig) pwd = self._encrypt_pwd(salt, verify_code) params = { 'u': self.username, 'verifycode': verify_code, 'pt_vcode_v1': '0', 'pt_verifysession_v1': pt_verifysession_v1, 'p': pwd, 'pt_randsalt': '2', 'u1': 'https://lol.qq.com/main.shtml', 'ptredirect': '1', 'h': '1', 't': '1', 'g': '1', 'from_ui': '1', 'ptlang': '2052', 'action': f'1-0-{int(time.time() * 1000)}', 'js_ver': '19072517', 'js_type': '1', 'login_sig': login_sig, 'pt_uistyle': '40', 'aid': 21000501, 'daid': '8', 'ptdrvs': ptdrvs, '': '' } res = self.session.get(login_api, params=params) result = re.search(r'ptuiCB\((.*?)\)', res.text).group(1).replace("'", '') result = result.split(',') if result[0] == '0': url = result[2] resp = self.session.get(url, allow_redirects=False) if resp.status_code == 302 and resp.headers[ 'location'] == 'https://lol.qq.com/main.shtml': self.logger.info('登录成功! ') nickname = result[-1] self.logger.info('Hello, {}! '.format(nickname)) cookies = resp.cookies.get_dict() self.redis_client.save_cookies(self.site, self.username, cookies) return True raise Exception('登录失败! ') elif '密码不正确' in result[-2]: self.reset_flag = True raise Exception('账号或密码错误! ') elif '二维码登录' in res.text: self.logger.warning('为了更好的保护您的QQ,请使用扫描二维码登录! ') return False raise Exception('登录失败: {} '.format(result[-2])) @check_user() def run(self, load_cookies: bool = True): if load_cookies: cookies = self.redis_client.load_cookies(self.site, self.username) if cookies: if self.check_islogin(cookies): return True self.logger.warning('Cookies 已过期') self.login()
class ToutiaoLogin: def __init__(self, username: str = None, password: str = None, headless=False): self.site = 'toutiao' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.browser = None self.wait = None self.headless = headless # 密码错误重置初始化 self.reset_flag = False def check_islogin(self, cookies): """ 检查登录状态, 请求网站首页出现用户名则 cookies 有效 :param cookies: :return: """ url = 'https://www.toutiao.com/' headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } resp = requests.get(url, headers=headers, cookies=cookies) nickname = re.search("userName: '******',", resp.text).group(1) if nickname != '': self.logger.info('Cookies 有效! ') self.logger.info('Hello, {}! '.format(nickname)) return True return False def set_browser(self): """ 配置 selenium :return: """ options = webdriver.ChromeOptions() # 设置为开发者模式,避免被识别, 开发者模式下 webdriver 属性为 undefined options.add_experimental_option('excludeSwitches', ['enable-automation']) if self.headless: options.add_argument('--headless') self.browser = webdriver.Chrome(options=options) self.wait = WebDriverWait(self.browser, 20) @staticmethod def pic_download(url, type): """ 下载验证码图片 :param url: :param type: :return: """ img_data = requests.get(url).content with open('./{}.jpg'.format(type), 'wb') as f: f.write(img_data) @staticmethod def process_img(img1, img2): """ 图片处理 :param img1: 处理后图片 :param img2: 待处理图片 :return: """ cv2.imwrite(img1, img2) target = cv2.imread(img1) target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY) target = abs(255 - target) cv2.imwrite(img1, target) def get_distance(self, slider_url, captcha_url): """ 获取缺口距离 :param slider_url: 滑块图片 url :param captcha_url: 验证码图片 url :return: """ # 引用上面的图片下载 self.pic_download(slider_url, 'slider') time.sleep(2) # 引用上面的图片下载 self.pic_download(captcha_url, 'captcha') # 计算拼图还原距离 target = cv2.imread('slider.jpg', 0) template = cv2.imread('captcha.jpg', 0) w, h = target.shape[::-1] temp = 'temp.jpg' targ = 'targ.jpg' self.process_img(temp, template) self.process_img(targ, target) target = cv2.imread(targ) template = cv2.imread(temp) result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED) x, y = np.unravel_index(result.argmax(), result.shape) # 缺口位置 # print((y, x, y + w, x + h)) # 调用PIL Image 做测试 image = Image.open('captcha.jpg') xy = (y, x, y + w, x + h) # 切割 imagecrop = image.crop(xy) # 保存切割的缺口 imagecrop.save("new_image.jpg") # imagecrop.show() return y def get_slider(self): """ 获取滑块 :return: """ return self.wait.until( EC.element_to_be_clickable( (By.XPATH, '//img[@class="drag-button"]'))) def move_to_gap(self, distance, slider): """ 移动滑块至缺口 :param distance: 缺口距离 :param slider: 滑块对象 :return: """ has_gone_dist = 0 remaining_dist = distance # distance += randint(-10, 10) # 按下鼠标左键 ActionChains(self.browser).click_and_hold(slider).perform() time.sleep(0.5) while remaining_dist > 0: ratio = remaining_dist / distance if ratio < 0.1: # 开始阶段移动较慢 span = random.randint(3, 5) elif ratio > 0.9: # 结束阶段移动较慢 span = random.randint(5, 8) else: # 中间部分移动快 span = random.randint(15, 20) ActionChains(self.browser).move_by_offset(span, random.randint( -5, 5)).perform() remaining_dist -= span has_gone_dist += span time.sleep(random.randint(5, 20) / 100) ActionChains(self.browser).move_by_offset(remaining_dist, random.randint(-5, 5)).perform() ActionChains(self.browser).release(on_element=slider).perform() def is_element_exists(self, element): """ 判断页面元素是否存在: Xpath :param element: :return: """ try: self.browser.find_element_by_xpath(element) return True except: return False @seleniumLoopUnlessSeccessOrMaxTry(3, sleep_time=3) def login(self): """ 打开浏览器,并且输入账号密码 :return: """ self.logger.info('尝试登录...') self.browser.get('https://sso.toutiao.com/') self.logger.info('点击选择账号密码登录...') acount_login = self.wait.until( EC.presence_of_element_located( (By.XPATH, '//div[@id="login-type-account"]'))) acount_login.click() self.logger.info('输入账号...') input_username = self.wait.until( EC.presence_of_element_located((By.XPATH, '//*[@id="user-name"]'))) input_username.send_keys(self.username) time.sleep(1) self.logger.info('输入密码...') input_password = self.wait.until( EC.presence_of_element_located((By.XPATH, '//*[@id="password"]'))) input_password.send_keys(self.password) time.sleep(1) self.logger.info('点击登录...') button = self.wait.until( EC.presence_of_element_located( (By.XPATH, '//*[@id="bytedance-login-submit"]'))) button.click() time.sleep(3) # 判断是否出现滑块验证 slider_flag = self.is_element_exists('//*[@id="verify-bar-box"]') if not slider_flag: self.logger.info('未出现滑块验证! ') time.sleep(3) error_flag = self.is_element_exists('//div[@class="login-msg"]') if error_flag: msg_error = self.browser.find_element_by_xpath( '//div[@class="login-msg"]').text if '帐号或密码错误' in msg_error: self.reset_flag = True raise Exception('账号或密码错误! ') else: self.logger.error(msg_error) return None elif self.browser.current_url != "https://www.toutiao.com/": self.logger.error('登录失败! ') return None else: self.logger.info('登录成功! ') cookies = self.browser.get_cookies() cookies = { cookie['name']: cookie['value'] for cookie in cookies } self.redis_client.save_cookies(self.site, self.username, cookies) return cookies self.logger.info('出现滑块验证! ') while True: captcha_url = self.wait.until( EC.presence_of_element_located( (By.XPATH, '//*[@id="validate-big"]'))).get_attribute('src') slider_url = self.wait.until( EC.presence_of_element_located( (By.XPATH, '//img[@class="validate-block"]'))).get_attribute('src') distance = self.get_distance(slider_url, captcha_url) slider = self.get_slider() self.move_to_gap(distance, slider) time.sleep(3) error_flag = self.is_element_exists('//div[@class="login-msg"]') if error_flag: self.logger.info('验证通过! ') msg_error = self.browser.find_element_by_xpath( '//div[@class="login-msg"]').text if '帐号或密码错误' in msg_error: self.reset_flag = True raise Exception('账号或密码错误! ') else: self.logger.error(msg_error) return msg_error elif self.is_element_exists('//*[@id="verify-bar-box"]'): self.logger.warning('验证失败, 重试! ') time.sleep(0.5) else: self.logger.info('验证通过, 登录成功! ') cookies = self.browser.get_cookies() cookies = { cookie['name']: cookie['value'] for cookie in cookies } self.redis_client.save_cookies(self.site, self.username, cookies) return cookies time.sleep(random.randint(1, 3)) @check_user() def run(self, load_cookies: bool = True): """ 运行 :param load_cookies: 是否加载数据库中的 cookies :return: cookies """ if load_cookies: cookies = self.redis_client.load_cookies(self.site, self.username) if cookies: if self.check_islogin(cookies): return cookies self.logger.warning('Cookies 已过期') self.set_browser() cookies = self.login() self.logger.info('程序结束! ') return cookies
class OpenlawLogin: def __init__(self, username: str = None, password: str = None): self.site = 'openlaw' self.username = username self.password = password self.logger = get_logger() self.redis_client = RedisClient(self.logger) self.session = Session() self.session.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36' } # 密码错误重置初始化 self.reset_flag = False def check_islogin(self, cookies): url = 'http://openlaw.cn/user/profile.jsp' res = self.session.get(url, cookies=cookies) if 'bbp-breadcrumb-root' in res.text: self.logger.info('Cookies 有效! ') bsobj = BeautifulSoup(res.text, 'lxml') nickname = bsobj.select('.bbp-breadcrumb-root')[0].get_text() self.logger.info('Hello, {}! '.format(nickname)) return True return False def _get_csrf(self): while True: base_url = 'http://openlaw.cn/login.jsp' res = self.session.get(base_url) cookies = res.cookies.get_dict() if cookies: soup = BeautifulSoup(res.text, 'lxml') _csrf = soup.find('input', {'name': '_csrf'})['value'] return _csrf, cookies time.sleep(1) def _encrypt_pwd(self): with open('encryptPwd.js', 'rb') as f: js = f.read().decode() ctx = execjs.compile(js) encrypt_pwd = ctx.call('encrypt_pwd', self.password) return encrypt_pwd @loopUnlessSeccessOrMaxTry(3, sleep_time=3) def login(self): login_api = 'http://openlaw.cn/login' _csrf, cookies = self._get_csrf() _encrypt_pwd = self._encrypt_pwd() data = { 'username': self.username, '_csrf': _csrf, 'password': _encrypt_pwd, '_spring_security_remember_me': 'true' } res = self.session.post(login_api, data=data) bsobj = BeautifulSoup(res.text, 'lxml') if bsobj.select('.bbp-breadcrumb-root'): self.logger.info('登录成功!') nickname = bsobj.select('.bbp-breadcrumb-root')[0].get_text() self.logger.info('Hello, {}! '.format(nickname)) self.redis_client.save_cookies(self.site, self.username, cookies) return cookies elif '用户名或密码错误' in res.text: self.reset_flag = True raise Exception('账号或密码错误! ') raise Exception('登录失败! ') @check_user() def run(self, load_cookies: bool = True): if load_cookies: cookies = self.redis_client.load_cookies(self.site, self.username) if cookies: if self.check_islogin(cookies): return cookies self.logger.warning('Cookies 已过期') return self.login()
class IQiyiLogin: def __init__(self, username: str = None, password: str = None): self.site = 'iqiyi' self.logger = get_logger() self.username = username self.password = password self.redis_client = RedisClient(self.logger) self.session = requests.session() self.session.headers = { 'Accept': 'application/json, text/javascript, */*; q=0.01', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 'Origin': 'http://www.iqiyi.com', 'Referer': 'http://www.iqiyi.com/iframe/loginreg?ver=1', "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36" } # 密码错误重置初始化 self.reset_flag = False def check_islogin(self, cookies): url = 'http://www.iqiyi.com/u/point' res = self.session.get(url, cookies=cookies) if 'ucbannerName' in res.text: self.logger.info('Cookies 有效! ') bsobj = BeautifulSoup(res.text, 'lxml') nickname = bsobj.select('#ucbannerName')[0].get_text().strip() self.logger.info('Hello, {}! '.format(nickname)) return True return False def _encrypt_pwd(self): """ 加密密码 :return: """ with open('iqiyiPwdEncrypt.js', 'r') as f: js = f.read() ctx = execjs.compile(js) return ctx.call('rsaFun', self.password) def _get_areacode(self): """ 获取地区编码 :return: """ url = 'https://passport.iqiyi.com/apis/phone/get_support_areacode.action' data = { 'use_case': '1', 'local': '1', 'agenttype': '1', 'fromSDK': '1', 'ptid': '01010021010000000000', 'sdk_version': '1.0.0' } r = self.session.post(url, data=data).json() code_dict = r['data']['acode'] return code_dict def get_dfp(self): """ 获取页面初始化参数 dfp :return: """ url = 'https://cook.iqiyi.com/security/dfp_pcw/sign' data = { 'dim': 'eyJqbiI6Ik1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS83NS4wLjM3NzAuODAgU2FmYXJpLzUzNy4zNiIsImNtIjoiemgtQ04iLCJndSI6MjQsInVmIjoxLCJqciI6WzEzNjYsNzY4XSwiZGkiOlsxMzY2LDcyOF0sInpwIjotNDgwLCJ1aCI6MSwic2giOjEsImhlIjoxLCJ6byI6MSwicnYiOiJ1bmtub3duIiwibngiOiJXaW4zMiIsIml3IjoidW5rbm93biIsInFtIjpbIkNocm9tZSBQREYgUGx1Z2luOjpQb3J0YWJsZSBEb2N1bWVudCBGb3JtYXQ6OmFwcGxpY2F0aW9uL3gtZ29vZ2xlLWNocm9tZS1wZGZ cGRmIiwiQ2hyb21lIFBERiBWaWV3ZXI6Ojo6YXBwbGljYXRpb24vcGRmfnBkZiIsIk5hdGl2ZSBDbGllbnQ6Ojo6YXBwbGljYXRpb24veC1uYWNsfixhcHBsaWNhdGlvbi94LXBuYWNsfiJdLCJ3ciI6ImI3NzY2NGM3MTcwNzdhZmZmMzNhN2QyODM2ZTIzNzdjIiwid2ciOiJlZDI2NTg5MTM1MTJlNTA5MmZlMjE5NDAwOGQ3OWEwZSIsImZrIjpmYWxzZSwicmciOmZhbHNlLCJ4eSI6ZmFsc2UsImptIjpmYWxzZSwiYmEiOmZhbHNlLCJ0bSI6WzAsZmFsc2UsZmFsc2VdLCJhdSI6dHJ1ZSwibWkiOiI5YmU0OTM0MS05MTI2LTg5MjQtNjc2Ni0xOTA3Y2QxNTYxMDgiLCJjbCI6IlBDV0VCIiwic3YiOiIxLjAiLCJqZyI6IjA3NjQ4M2QwODg2NGMzNTE5MWUyNTVjNjhmNWU2YWE3IiwiZmgiOiJvazZxeWc0cXM5YWw5MTA0YjZ0OTJoODEiLCJpZm0iOltmYWxzZSxudWxsLG51bGwsbnVsbF0sImV4IjoiIiwiZHYiOiJvZmYiLCJwdiI6dHJ1ZX0=', 'plat': 'PCWEB', 'ver': '1.0', 'sig': '785042546DC84608E1DF7430A9AE021C2F6F7955', 'nifc': 'false' } result = self.session.post(url, data=data).json() if result['code'] == 0: dfp = result['result']['dfp'] print('dfp: {}'.format(dfp)) expire_time = time.strftime( "%H:%M:%S", time.localtime(result['result']['expireAt'] - int(time.time() * 1000))) print('{} 后过期'.format(expire_time)) return dfp return None @loopUnlessSeccessOrMaxTry(3, sleep_time=3) def login(self): """ 登录, 只有一个加密参数密码, 其他为定值 :return: """ url = 'https://passport.iqiyi.com/apis/reglogin/login.action' encrypt_pwd = self._encrypt_pwd() dfp = self.get_dfp() data = { 'email': self.username, 'fromSDK': '1', 'sdk_version': '1.0.0', 'passwd': encrypt_pwd, 'agenttype': '1', '__NEW': '1', 'checkExist': '1', 'lang': '', 'ptid': '01010021010000000000', 'nr': '1', 'verifyPhone': '1', 'area_code': '86', # 'env_token': 'c225a3e03fdf4c90a9227af2f0abd8bb', 'dfp': dfp, 'envinfo': 'eyJqbiI6Ik1vemlsbGEvNS4wIChXaW5kb3dzIE5UIDEwLjA7IFdpbjY0OyB4NjQpIEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIENocm9tZS83NS4wLjM3NzAuODAgU2FmYXJpLzUzNy4zNiIsImNtIjoiemgtQ04iLCJndSI6MjQsInVmIjoxLCJqciI6WzEzNjYsNzY4XSwiZGkiOlsxMzY2LDcyOF0sInpwIjotNDgwLCJ1aCI6MSwic2giOjEsImhlIjoxLCJ6byI6MSwicnYiOiJ1bmtub3duIiwibngiOiJXaW4zMiIsIml3IjoidW5rbm93biIsInFtIjpbIkNocm9tZSBQREYgUGx1Z2luOjpQb3J0YWJsZSBEb2N1bWVudCBGb3JtYXQ6OmFwcGxpY2F0aW9uL3gtZ29vZ2xlLWNocm9tZS1wZGZ cGRmIiwiQ2hyb21lIFBERiBWaWV3ZXI6Ojo6YXBwbGljYXRpb24vcGRmfnBkZiIsIk5hdGl2ZSBDbGllbnQ6Ojo6YXBwbGljYXRpb24veC1uYWNsfixhcHBsaWNhdGlvbi94LXBuYWNsfiJdLCJ3ciI6ImI3NzY2NGM3MTcwNzdhZmZmMzNhN2QyODM2ZTIzNzdjIiwid2ciOiJlZDI2NTg5MTM1MTJlNTA5MmZlMjE5NDAwOGQ3OWEwZSIsImZrIjpmYWxzZSwicmciOmZhbHNlLCJ4eSI6ZmFsc2UsImptIjpmYWxzZSwiYmEiOmZhbHNlLCJ0bSI6WzAsZmFsc2UsZmFsc2VdLCJhdSI6dHJ1ZSwibWkiOiI5YmU0OTM0MS05MTI2LTg5MjQtNjc2Ni0xOTA3Y2QxNTYxMDgiLCJjbCI6IlBDV0VCIiwic3YiOiIxLjAiLCJqZyI6IjA3NjQ4M2QwODg2NGMzNTE5MWUyNTVjNjhmNWU2YWE3IiwiZmgiOiJvazZxeWc0cXM5YWw5MTA0YjZ0OTJoODEiLCJpZm0iOltmYWxzZSxudWxsLG51bGwsbnVsbF0sImV4IjoiIiwiZHYiOiJvZmYiLCJwdiI6dHJ1ZX0=' } while True: res = self.session.post(url, data=data) cookies = res.cookies.get_dict() if res.json()['code'] == 'A00000': self.logger.info('登录成功! ') self.logger.info('Hello, {}! '.format( res.json()['data']['nickname'])) self.redis_client.save_cookies(self.site, self.username, cookies) return cookies elif res.json()['code'] == 'P00117': self.reset_flag = True raise Exception('账号或密码错误! ') token = res.json()['data']['data']['token'] data.update({'env_token': token}) self.logger.info(f'{res.json()["msg"]}, env_token更新为: {token}') time.sleep(random.random()) def get_userinfo(self, cookies): """ 获取用户信息 :return: """ url = 'https://passport.iqiyi.com/apis/user/info.action' code_dict = self._get_areacode() with open('antiCsrf.js', 'rb') as f: js = f.read().decode() ctx = execjs.compile(js) try: auth_cookie = cookies['P00001'] anticsrf = ctx.call('getAnticsrf', auth_cookie) data = { 'agenttype': '1', 'ptid': '01010021010000000000', 'lang': '', 'fromSDK': '1', 'sdk_version': '1.0.0', 'authcookie': auth_cookie, 'antiCsrf': anticsrf, 'fields': 'insecure_account,userinfo' } r = requests.post(url, data=data) user_info = r.json()['data']['userinfo'] jointime = time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime(int(user_info['jointime']))) if user_info['gender'] == 1: gender = '男' else: gender = '女' area_code = user_info['area_code'] for code in code_dict.keys(): if area_code == code: area = code_dict[code] if user_info['birthday']: birthday = time.strftime( "%Y-%m-%d %H:%M:%S", time.localtime(int(user_info['birthday']))) user_info.update({ 'birthday': birthday, 'jointime': jointime, 'gender': gender, 'area': area }) # 移除地区代码 del user_info['area_code'] self.logger.info(f'您的基本信息为: {user_info}') return True except: return False @check_user() def run(self, load_cookies: bool = True): """ 主函数 :return: """ if load_cookies: cookies = self.redis_client.load_cookies(self.site, self.username) if cookies: if self.check_islogin(cookies): info_flag = input('是否显示用户信息? (yes/no) \n') if info_flag == 'yes': self.get_userinfo(cookies) return cookies self.logger.warning('Cookies 已过期') return self.login()