Python selenium 模拟登录bilibili
Python selenium 模拟登录bilibili
Selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。
在登录bilibili的时候,会有一个拖动图片的验证——极验验证码。我们用selenium在Chrome中打开bilibili的登录页面。然后填写登录账号和密码。再点击登录按钮,页面弹出极验验证码,通过js获取两张图片(一张完整的图片,一张有缺口的图片),这两张图片是用canvas画出来的。所有我们用toDataURL(“image/png”)方法拿到的是base64格式的图片。将这两张图片的用PIL中的Image来获转化之后的图片。比较两张图片的像素点,从而计算出拖动块需要移动的距离。
流程图
总体框架
class LoginBiliBili:def __init__(self, username, password):"""初始化数据:param username: bilibili账号:param password: 密码"""def open(self):"""打开浏览器, 进入登陆界面输入用户名, 密码点击登陆:return: None"""def get_geetest_image(self):"""获取极验验证码图片:return: c_image(王者验证图) ic_image(有缺失的验证图)"""def is_pixel_similar(self, c_image, ic_image, x, y):"""比较两张图片的像素点注意: 像素点比较是有偏差的, 需要允许一定范围的误差,我们可以设置一个阈值:param ic_image::param c_image::param x::param y::return: 当像素点不相同时, 返回 False"""def get_slice_gap(self, c_image, ic_image):"""获取缺口的偏移量通过比较两张图片的所有像素点, 获取两张图片是从哪里开始不同从而得到 移动块 要在 x 方向移动的距离:param c_image: 完整的图片:param ic_image: 有缺失的图片:return: 缺口的偏移量"""def drag_slider(self, gap):"""拖动滑块:param gap: 需要拖动的距离:return: None"""def login_success(self):"""判断是否登陆成功:return: 成功返回 True 失败返回False"""def login(self):"""开始:return: None"""if __name__ == '__main__':login = LoginBiliBili('*******', '******')login.login()
初始化数据方法
将一些初始化数据在__init__()函数中定义
def __init__(self, username, password):"""初始化数据:param username: bilibili账号:param password: 密码"""self.username = usernameself.password = password# 定义浏览器self.browser = webdriver.Chrome()# 定义显示等待self.wait = WebDriverWait(self.browser, 50)# bilibili登录urlself.url = 'https://passport.bilibili.com/login'
打开浏览器方法
此方法用来打开浏览器,在进入登陆页面之后,自动输入用户名,密码。以及点击的登录按钮
def open(self):"""打开浏览器, 进入登陆界面输入用户名, 密码点击登陆:return: None"""# 打开浏览器, 进入登陆界面self.browser.get(self.url)# 用户名输入框username_input_box = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="login-username"]')))# 清空用户名输入框username_input_box.clear()# 将自己的用户名输入到用户名输入框username_input_box.send_keys(self.username)# 密码输入框password_input_box = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="login-passwd"]')))# 清空密码输入框password_input_box.clear()# 将自己的密码输入到密码输入框password_input_box.send_keys(self.password)# 登录按钮login_button = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="geetest-wrap"]/ul/li[5]/a[1]')))# 点击登录login_button.click()# 休眠, 让验证码图片加载出来time.sleep(2)
拿极验验证码图片方法
如何拿到极验验证码图片是我们进行模拟登录的关键一步,这里的极验验证码是由canvas绘制的两张图片,所有我们需要用js去获取图片。
def get_geetest_image(self):"""获取极验验证码图片:return: c_image(王者验证图) ic_image(有缺失的验证图)""""""完整的验证图页面源码:<canvas class="geetest_canvas_fullbg geetest_fade geetest_absolute" height="160" width="260" style="display: none;"></canvas>"""# 执行js 拿到canvas画布里面的图片数据js = 'return document.getElementsByClassName("geetest_canvas_fullbg")[0].toDataURL("image/png");'# 图片数据complete_img_data = self.browser.execute_script(js)# base64 编码的图片信息complete_img_base64 = complete_img_data.split(',')[1]# 转成bytes类型complete_img = base64.b64decode(complete_img_base64)# 加载图片 return 回去对比c_image = Image.open(BytesIO(complete_img))# c_image.show()# 保存图片 (可不必保存)c_image.save('c_image.png')"""有缺失的验证码图页面源码:<canvas class="geetest_canvas_bg geetest_absolute" height="160" width="260"></canvas>"""# 执行js 拿到canvas画布里的图片数据js = 'return document.getElementsByClassName("geetest_canvas_bg")[0].toDataURL("image/png");'# 图片数据incomplete_img_data = self.browser.execute_script(js)# base64 编码的图片信息incomplete_img_base64 = incomplete_img_data.split(',')[1]# 转为bytes类型incomplete_img = base64.b64decode(incomplete_img_base64)# 直接加载图片 return 回去对比ic_image = Image.open(BytesIO(incomplete_img))# ic_image.show()# 保存图片(可不必保存)ic_image.save('ic_image.png')return c_image, ic_image
# 对比像素点方法 和 获取移动距离方法
这两个方法我们要将它们联系起来,我们通过对比图片横向和纵向的像素点,来确定两张图片是从哪里开始不同的。当然,我们只需要得知水平方向哪里开始不同的(滑块只需要在水平方向移动)
def is_pixel_similar(self, c_image, ic_image, x, y):"""比较两张图片的像素点注意: 像素点比较是有偏差的, 需要允许一定范围的误差,我们可以设置一个阈值:param ic_image::param c_image::param x::param y::return: 当像素点不相同时, 返回 False"""# 获取两张图片执行位置的像素点c_pixel = c_image.load()[x, y]ic_pixel = ic_image.load()[x, y]# 阈值 允许误差threshold = 10# 对比if abs(c_pixel[0] - ic_pixel[0]) < threshold and \abs(c_pixel[1] - ic_pixel[1]) < threshold and \abs(c_pixel[2] - ic_pixel[2]) < threshold:return Truereturn Falsedef get_slice_gap(self, c_image, ic_image):"""获取缺口的偏移量通过比较两张图片的所有像素点, 获取两张图片是从哪里开始不同从而得到 移动块 要在 x 方向移动的距离:param c_image: 完整的图片:param ic_image: 有缺失的图片:return: 缺口的偏移量"""# ic_image.size:['width', 'height']for x in range(c_image.size[0]):for y in range(c_image.size[1]):if not self.is_pixel_similar(c_image, ic_image, x, y):# 移动块只在水平方向移动 只需返回 xreturn x
拖动滑块方法
然后就是拖动滑块了.
def drag_slider(self, gap):"""拖动滑块:param gap: 需要拖动的距离:return: None"""slider = self.wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div[2]/div[2]/div[6]/div/div[1]/div[2]/div[2]')))# 抓住滑块ActionChains(self.browser).click_and_hold(on_element=slider).perform()# 移动 只在水平方向上移动ActionChains(self.browser).move_by_offset(xoffset=gap, yoffset=0).perform()# 释放滑块ActionChains(self.browser).release().perform()
由于对比像素点有一定的误差,不一定会一次成功,所有我们会需要一个循环来进行多次验证,在判断成功登录之后,才结束进程.
判断是否登录
def login_success(self):"""判断是否登陆成功:return: 成功返回 True 失败返回False"""try:# 登录成功后 界面上会有一个消息按钮return bool(WebDriverWait(self.browser, 5).until(EC.presence_of_element_located((By.XPATH, '//a[@title="消息"]'))))except TimeoutException:return False
开始登录
def login(self):"""开始:return: None"""# 打开浏览器, 输入账号 密码, 点击登陆self.open()# 获取验证图 ic_image(有缺失的验证图) c_image(完整的验证图)c_image, ic_image = self.get_geetest_image()# 获取缺口的偏移量gap = self.get_slice_gap(c_image, ic_image)print(f'缺口的偏移量为:{gap}')# 拖动滑块# TODO 这边一直有一定的误差 暂时用测量工具解决self.drag_slider(gap-8)time.sleep(3)if self.login_success():print('登陆成功')else:self.login()
完整的代码
class LoginBiliBili:def __init__(self, username, password):"""初始化数据:param username: bilibili账号:param password: 密码"""self.username = usernameself.password = password# 定义浏览器self.browser = webdriver.Chrome()# 定义显示等待self.wait = WebDriverWait(self.browser, 50)# bilibili登录urlself.url = 'https://passport.bilibili.com/login'def open(self):"""打开浏览器, 进入登陆界面输入用户名, 密码点击登陆:return: None"""# 打开浏览器, 进入登陆界面self.browser.get(self.url)# 用户名输入框username_input_box = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="login-username"]')))# 清空用户名输入框username_input_box.clear()# 将自己的用户名输入到用户名输入框username_input_box.send_keys(self.username)# 密码输入框password_input_box = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="login-passwd"]')))# 清空密码输入框password_input_box.clear()# 将自己的密码输入到密码输入框password_input_box.send_keys(self.password)# 登录按钮login_button = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="geetest-wrap"]/ul/li[5]/a[1]')))# 点击登录login_button.click()# 休眠, 让验证码图片加载出来time.sleep(2)def get_geetest_image(self):"""获取极验验证码图片:return: c_image(王者验证图) ic_image(有缺失的验证图)""""""完整的验证图页面源码:<canvas class="geetest_canvas_fullbg geetest_fade geetest_absolute" height="160" width="260" style="display: none;"></canvas>"""# 执行js 拿到canvas画布里面的图片数据js = 'return document.getElementsByClassName("geetest_canvas_fullbg")[0].toDataURL("image/png");'# 图片数据complete_img_data = self.browser.execute_script(js)# base64 编码的图片信息complete_img_base64 = complete_img_data.split(',')[1]# 转成bytes类型complete_img = base64.b64decode(complete_img_base64)# 加载图片 return 回去对比c_image = Image.open(BytesIO(complete_img))# c_image.show()# 保存图片 (可不必保存)c_image.save('c_image.png')"""有缺失的验证码图页面源码:<canvas class="geetest_canvas_bg geetest_absolute" height="160" width="260"></canvas>"""# 执行js 拿到canvas画布里的图片数据js = 'return document.getElementsByClassName("geetest_canvas_bg")[0].toDataURL("image/png");'# 图片数据incomplete_img_data = self.browser.execute_script(js)# base64 编码的图片信息incomplete_img_base64 = incomplete_img_data.split(',')[1]# 转为bytes类型incomplete_img = base64.b64decode(incomplete_img_base64)# 直接加载图片 return 回去对比ic_image = Image.open(BytesIO(incomplete_img))# ic_image.show()# 保存图片(可不必保存)ic_image.save('ic_image.png')return c_image, ic_imagedef is_pixel_similar(self, c_image, ic_image, x, y):"""比较两张图片的像素点注意: 像素点比较是有偏差的, 需要允许一定范围的误差,我们可以设置一个阈值:param ic_image::param c_image::param x::param y::return: 当像素点不相同时, 返回 False"""# 获取两张图片执行位置的像素点c_pixel = c_image.load()[x, y]ic_pixel = ic_image.load()[x, y]# 阈值 允许误差threshold = 10# 对比if abs(c_pixel[0] - ic_pixel[0]) < threshold and \abs(c_pixel[1] - ic_pixel[1]) < threshold and \abs(c_pixel[2] - ic_pixel[2]) < threshold:return Truereturn Falsedef get_slice_gap(self, c_image, ic_image):"""获取缺口的偏移量通过比较两张图片的所有像素点, 获取两张图片是从哪里开始不同从而得到 移动块 要在 x 方向移动的距离:param c_image: 完整的图片:param ic_image: 有缺失的图片:return: 缺口的偏移量"""# ic_image.size:['width', 'height']for x in range(c_image.size[0]):for y in range(c_image.size[1]):if not self.is_pixel_similar(c_image, ic_image, x, y):# 移动块只在水平方向移动 只需返回 xreturn xdef drag_slider(self, gap):"""拖动滑块:param gap: 需要拖动的距离:return: None"""slider = self.wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div[2]/div[2]/div[6]/div/div[1]/div[2]/div[2]')))# 抓住滑块ActionChains(self.browser).click_and_hold(on_element=slider).perform()# 移动 只在水平方向上移动ActionChains(self.browser).move_by_offset(xoffset=gap, yoffset=0).perform()# 释放滑块ActionChains(self.browser).release().perform()def login_success(self):"""判断是否登陆成功:return: 成功返回 True 失败返回False"""try:# 登录成功后 界面上会有一个消息按钮return bool(WebDriverWait(self.browser, 5).until(EC.presence_of_element_located((By.XPATH, '//a[@title="消息"]'))))except TimeoutException:return Falsedef login(self):"""开始:return: None"""# 打开浏览器, 输入账号 密码, 点击登陆self.open()# 获取验证图 ic_image(有缺失的验证图) c_image(完整的验证图)c_image, ic_image = self.get_geetest_image()# 获取缺口的偏移量gap = self.get_slice_gap(c_image, ic_image)print(f'缺口的偏移量为:{gap}')# 拖动滑块# TODO 这边一直有一定的误差 暂时用测量工具解决self.drag_slider(gap-8)time.sleep(3)if self.login_success():print('登陆成功')else:self.login()if __name__ == '__main__':login = LoginBiliBili('*******', '******')login.login()
Python selenium 模拟登录bilibili相关推荐
- python访问陌生人qq空间_使用Python+Selenium模拟登录QQ空间
使用Python+Selenium模拟登录QQ空间 爬QQ空间之类的页面时大多需要进行登录,研究QQ登录规则的话,得分析大量Javascript的加密解密,这绝对能掉好几斤头发.而现在有了seleni ...
- Python selenium 模拟登录QQ空间
下面文档的脚本执行,必须要下载 谷歌浏览器对应的驱动详细的流程时 selenium的使用流程a 环境的安装 b 谷歌浏览器驱动下载地址:http://chromedriver.storage.goog ...
- python+selenium获取cookie session_Python Selenium模拟登录成功后,使用此cookie、利用requests库进行get时,提示“非法登陆”。...
一. 步骤概述 a. 模拟登录学校选课系统(使用Selenium库登陆http://xk.suibe.edu.cn/xsxk/login.xk) b. 取得cookie后传入requests的sess ...
- python爬虫-selenium模拟登录豆瓣获取cookies给requests使用
1. selenium如何切换到iframe中操作 import time from selenium import webdriverurl = "https://www.douban.c ...
- selenium模拟登录豆瓣和qq空间
selenium模拟登录豆瓣和qq空间 今天又重新学习了下selenium,模拟登录豆瓣,发现设置等待时间真的是很重要的一步,不然一直报错:selenium.common.exceptions.NoS ...
- 使用selenium模拟登录解决滑块验证问题
本次主要是使用selenium模拟登录网页端的TX新闻,本来最开始是模拟请求的,但是某一天突然发现,部分账号需要经过滑块验证才能正常登录,如果还是模拟请求,需要的参数太多了,找的心累.不过好在TX的滑 ...
- 2021春项目需求记录 python实现模拟登录+爬取NASA Modis 上的产品数据
python实现模拟登录+爬取Nasa Modis 上的产品数据 概述 需求分析 基本思路 代码 概述 3月的中旬时候参与了学校的一个大创项目,作为本科生,本人只是摸鱼打杂,负责了其中的一个功能模块: ...
- 越过验证码 selenium模拟登录B站项目实战(附源码)
实战:selenium模拟登录B站 登录验证码处理 selenium 中的难点验证码破解因为确实没有很好的方式,一般都需要通过第三方平台实现破解,本案例中使用的是超级鹰平台(收费,大概1元30次,测试 ...
- python–爬虫–模拟登录全面介绍和简例–以抓取雅卓app为例
转载请注明出处:python–爬虫–模拟登录全面介绍和简例–以抓取雅卓app为例 我们在前面的文章中已经学习了如果使用python进行数据抓取. 但我们常常会遇到一种场景,就是想要获取的页面内容或者接 ...
最新文章
- The current directory must be set to the ITT directory解决办法
- Locust接口性能测试
- 使用git将本地项目上传到github
- PHP-高并发和大流量的解决方案
- 可扩展的Web架构和分布式系统
- Nginx+PHP-FPM优化技巧总结(转发别人的,自己留着收藏个记录用)
- 你为什么不敢重构代码?听高手亲授秘笈!
- Solidworks如何在自定义的基准面上创建3D草图
- 2019118_四个化学数据分析(4)
- 【每日算法Day 87】今天我脱单了,所以大家不用做题了!
- 利用excel做简单的曲线拟合并生成公式
- xp查看计算机mac地址查询,如何查看mac地址 xp系统查看查询mac地址方法介绍
- 传奇开服教程——legend/blue引擎替换和登陆器生成教程
- 计算机一级c类题库及答案解析,全国计算机一级考试试题题库及答案
- astah——UML类图画法
- 什么是散列表(Hash Table)
- 如何将电脑上的音乐传到苹果手机上?电脑音乐导入苹果手机
- 微软surface屏幕测试软件,Soomal作品 - Microsoft 微软 Surface Go平板电脑屏幕测评报告 [Soomal]...
- 【引语练习题】Ask questions politely
- ECCV2022 | 生成对抗网络GAN论文汇总(图像转换-图像编辑-图像修复-少样本生成-3D等)...
热门文章
- 黑客攻防技术宝典(一)
- 【SAP Abap】SAP系统数据快速导出
- SAP FIORI专题之四:使用fiori element构建over page
- Mapper method ‘com.LH.mapper.EmployeeMapper.insertEmployee‘ has an unsupported return type: cla 报错
- 华恩JAVA班第22天
- 实例1QQ好友列表界面和九宫格
- Python求两数之和
- 亚马逊被关联?别怕有救
- 【php】php语法基础
- IDC评述网:2013年12月份中国域名服务商Top25