滑动验证码最简单案例:破解qq空间(豆瓣网)滑块验证码(python+selenium实现)

news/2025/1/13 2:34:19/

破解qq空间(豆瓣网)滑块验证码

环境搭建

1、安装chrome浏览器和chromedriver

chromedriver下载连接:淘宝镜像
注意 :chromedriver的版本要与你使用的chrome版本对应
下载完成后将chromedriver.exe文件放到python.exe同一目录下。
在这里插入图片描述

2、搭建selenium环境

打开cmd,用命令直接安装

pip install selenium

然后在pycharm中的file–>settings–>project interpreter 中点击**+**号引入selenium包。
在这里插入图片描述
如果引入包后仍然报错,可以参考:关于pip安装第三方库,但PyCharm中却无法识别的问题

3、环境测试

from selenium import webdriver  # 导入webdriver包
driver = webdriver.Chrome()  # 初始化一个火狐浏览器实例:driver
driver.maximize_window()  # 最大化浏览器
driver.get("https://www.baidu.com")  # 通过get()方法,打开一个url站点

如果成功打开百度,说明环境已经搭好!

滑块验证码破解思路

计算滑块需要滑动的距离

1、方法一:对比缺口图片和原图的像素值
这个方法的关键在于如何获取到原图。一般情况下我们打开浏览器的开发者模式,可以直接定位到验证码图片的位置。根据图片的呈现方式,我大概分为两种情况:一种是使用img标签呈现,这种方式一般会把图片的路径(qq空间、豆瓣网等)或者经过加密后(京东)放入到标签中,而另一种是使用canvas呈现,这种方式就需要通过修改canvas中的display属性来呈现单独的图片,但是我们无法直接通过路径去获取图片,只能通过截图的方式。(例如:极验的滑块验证码)
2、方法二:使用opencv方法处理缺口图片
就是将缺口图片处理成黑白图片,然后再计算缺口的距离。具体请参考opencv破解滑块验证码

滑块按照怎样的轨迹滑动

1、直接匀速滑动(适用没有使用机器学习验证的网站:qq空间、豆瓣网等)
2、模拟人的动作按照先匀加速,后匀减速滑动,最后多滑一段距离再退回来。(适用于使用机器学习验证的网站:极验、京东等)具体请问度娘。

实现

 本次要讲的是方法一破解qq空间验证码,也是最简单的方法。(豆瓣网的原理一模一样,甚至连验证码图片都是一样的,不难猜测应该是使用了同样的验证码接口)方法一的关键在于我们怎么得到验证码的原图,我们把这个问题解决了其他的都好办了!
 首先我们进入qq空间登录界面,随便输入一个qq号和密码点击登录按钮就会弹出滑块验证码,只能是电脑没有记录的才行。然后跳转到控制台–>element,我们可以很容易找到缺口图片和滑块图片,但是怎么也无法找到完整图片,很头疼吧!
在这里插入图片描述
 别放弃,我们继续在控制台中找到network,再选择img,我们又发现了之前的两张图片,我们双击图片把图片路径复制下来分析一下。在这里插入图片描述
发现缺口图片路径:index=1&image=*********&img_index=1&subsid=3
滑块图片路径:index=2&image=*********&img_index=2&subsid=3
于是尝试修改两个index等于0,再访问图片路径,奇迹出现了,我们得到原图的路径,这样问题不就解决了吗?
在这里插入图片描述
 获取缺口图片和原图代码实现如下:

    def get_img(self):"""获取验证码阴影图和原图:return:"""self.driver.switch_to.frame('tcaptcha_iframe')time.sleep(3)# 获取有阴影的图片src = self.driver.find_element_by_id('slideBg').get_attribute('src')# 分析图片地址,发现原图地址可以通过阴影图地址改动获取 只需要修改一下图片路径中的index#print(src)src_bg=src.replace('index=1','index=0')src_bg=src_bg.replace('img_index=1','img_index=0')#print(src_bg)# 将图片下载到本地urlretrieve(src, 'img1.png')urlretrieve(src_bg, 'img2.png')#读取本地图片captcha1 = Image.open('img1.png')captcha2 = Image.open('img2.png')return captcha1, captcha2

 得到两张图片之后,我们是不是就可以直接进行比较计算出缺口的距离的呢?按道理没错,但是这里有一个比较坑的地方就是我们下载下来的图片比网站中的图片要大,所以我们必须将图片缩小之后再进行计算。具体代码如下:

    def resize_img(self, img):"""下载的图片把网页中的图片进行了放大,所以将图片还原成原尺寸:param img: 图片:return: 返回还原后的图片"""# 通过本地图片与原网页图片的比较,计算出的缩放比例 原图(680x390)缩小图(280x161)a = 2.428(x, y) = img.sizex_resize = int(x // a)y_resize = int(y // a)"""Image.NEAREST :低质量Image.BILINEAR:双线性Image.BICUBIC :三次样条插值Image.ANTIALIAS:高质量"""img = img.resize((x_resize, y_resize), Image.ANTIALIAS)return imgdef is_pixel_equal(self, img1, img2, x, y):"""比较两张图片同一点上的像数值,差距大于设置标准返回False:param img1: 阴影图:param img2: 原图:param x: 横坐标:param y: 纵坐标:return: 是否相等"""pixel1, pixel2 = img1.load()[x, y], img2.load()[x, y]sub_index = 100#比较RGB各分量的值if abs(pixel1[0] - pixel2[0]) < sub_index and abs(pixel1[1] - pixel2[1]) < sub_index and abs(pixel1[2] - pixel2[2]) < sub_index:return Trueelse:return Falsedef get_gap_offset(self, img1, img2):"""获取缺口的偏移量"""distance = 70for i in range(distance, img1.size[0]):for j in range(img1.size[1]):# 两张图片对比,(i,j)像素点的RGB差距,过大则该x为偏移值if not self.is_pixel_equal(img1, img2, i, j):distance = ireturn distancereturn distance

 滑块的滑动轨迹其实设计匀速运动就可以了,也可以参考代码中的轨迹设计。(是不是非常简单!!!诚不欺您!)

下面是全部实现代码:

import time
import random
from selenium import webdriver
from urllib.request import urlretrieve
from PIL import Image
from selenium.webdriver.common.action_chains import ActionChainsclass Tencent():def __init__(self):"""初始化属性,传入url地址,驱动路径,浏览器窗口最大化,伪造ua"""self.url = 'https://qzone.qq.com/'self.driver = webdriver.Chrome()self.driver.maximize_window()self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'}def input_username_password(self, account, password):"""打开浏览器,传入账号、密码,定位到登录窗口,切换登陆方式:param account::param password::return:"""self.driver.get(self.url)time.sleep(1)self.driver.switch_to.frame('login_frame')self.driver.find_element_by_id('switcher_plogin').click()time.sleep(1)self.driver.find_element_by_id('u').send_keys(account)time.sleep(0.5)self.driver.find_element_by_id('p').send_keys(password)time.sleep(0.5)self.driver.find_element_by_class_name('login_button').click()def get_img(self):"""获取验证码阴影图和原图:return:"""self.driver.switch_to.frame('tcaptcha_iframe')time.sleep(3)# 获取有阴影的图片src = self.driver.find_element_by_id('slideBg').get_attribute('src')# 分析图片地址,发现原图地址可以通过阴影图地址改动获取 只需要修改一下图片路径中的index#print(src)src_bg=src.replace('index=1','index=0')src_bg=src_bg.replace('img_index=1','img_index=0')#print(src_bg)# 将图片下载到本地urlretrieve(src, 'img1.png')urlretrieve(src_bg, 'img2.png')#读取本地图片captcha1 = Image.open('img1.png')captcha2 = Image.open('img2.png')return captcha1, captcha2def resize_img(self, img):"""下载的图片把网页中的图片进行了放大,所以将图片还原成原尺寸:param img: 图片:return: 返回还原后的图片"""# 通过本地图片与原网页图片的比较,计算出的缩放比例 原图(680x390)缩小图(280x161)a = 2.428(x, y) = img.sizex_resize = int(x // a)y_resize = int(y // a)"""Image.NEAREST :低质量Image.BILINEAR:双线性Image.BICUBIC :三次样条插值Image.ANTIALIAS:高质量"""img = img.resize((x_resize, y_resize), Image.ANTIALIAS)return imgdef is_pixel_equal(self, img1, img2, x, y):"""比较两张图片同一点上的像数值,差距大于设置标准返回False:param img1: 阴影图:param img2: 原图:param x: 横坐标:param y: 纵坐标:return: 是否相等"""pixel1, pixel2 = img1.load()[x, y], img2.load()[x, y]sub_index = 100#比较RGB各分量的值if abs(pixel1[0] - pixel2[0]) < sub_index and abs(pixel1[1] - pixel2[1]) < sub_index and abs(pixel1[2] - pixel2[2]) < sub_index:return Trueelse:return Falsedef get_gap_offset(self, img1, img2):"""获取缺口的偏移量"""distance = 70for i in range(distance, img1.size[0]):for j in range(img1.size[1]):# 两张图片对比,(i,j)像素点的RGB差距,过大则该x为偏移值if not self.is_pixel_equal(img1, img2, i, j):distance = ireturn distancereturn distancedef get_track(self, distance):"""计算滑块的移动轨迹"""# 通过观察发现滑块并不是从0开始移动,有一个初始值distance -= 30a = distance / 4track = [a, a, a, a]return trackdef shake_mouse(self):"""模拟人手释放鼠标抖动"""ActionChains(self.driver).move_by_offset(xoffset=-2, yoffset=0).perform()ActionChains(self.driver).move_by_offset(xoffset=2, yoffset=0).perform()def operate_slider(self, track):"""拖动滑块当你调用ActionChains的方法时,不会立即执行,而是会将所有的操作按顺序存放在一个队列里,当你调用perform()方法时,队列中的时间会依次执行。:param track: 运动轨迹:return:"""# 定位到拖动按钮slider_bt = self.driver.find_element_by_xpath('//div[@class="tc-drag-thumb"]')# 点击拖动按钮不放ActionChains(self.driver).click_and_hold(slider_bt).perform()# 按正向轨迹移动# move_by_offset函数是会延续上一步的结束的地方开始移动for i in track:ActionChains(self.driver).move_by_offset(xoffset=i, yoffset=0).perform()print(i)time.sleep(random.random() / 100)  # 每移动一次随机停顿0-1/100秒之间骗过了极验,通过率很高time.sleep(random.random())# 按逆向轨迹移动back_tracks = [-1, -0.5, -1]for i in back_tracks:time.sleep(random.random() / 100)ActionChains(self.driver).move_by_offset(xoffset=i, yoffset=0).perform()# 模拟人手抖动self.shake_mouse()time.sleep(random.random())# 松开滑块按钮ActionChains(self.driver).release().perform()def login(self, account, password):"""实现主要的登陆逻辑:param account:账号:param password: 密码:return:"""self.input_username_password(account, password)time.sleep(2)a, b = self.get_img()a = self.resize_img(a)b = self.resize_img(b)distance = self.get_gap_offset(a, b)track = self.get_track(distance)self.operate_slider(track)if __name__ == '__main__':qq = Tencent()account = '2178452154'password = 'B20170304430ZZH'qq.login(account, password)

其实还有个更简单的方法破解qq空间和豆瓣网这个滑块验证码,就是直接量出滑块到缺口的距离,直接固定这个值,让滑块每次都滑动这个距离。(我一个同班同学用这个方法破解了豆瓣网的滑块验证码,确信!)其实我们多刷新几次可以发现缺口的位置其实是在不断变化的,这也说明了这个验证码的设计确实太简单了!(兄弟们,把离谱打在公平上!!!)

结尾

 事情的起因是这个学期的网络安全期末大作业,刚刚开始想做一个人脸识别的注册和登录调用百度的人脸识别api接口整合到我上个学期做的vue+springboot的项目里面,写了三天前端都搭建好后面发现图片的跨域问题一直解决不了,最后因为时间关系一次伟大的尝试就此放弃。还是太菜呀QAQ~
 然后临时准备做一个破解滑块验证码来应付,刚刚开始再网上搜索也是一大堆教程,然后我花了半天时间踩坑,(ps:环境搭建第一步就把我坑惨了,最后把python环境和pycharm卸载重装了(:
 然后我很开心去网上找各种教程,开始兴奋的copy,到最后发现教程里面给的网站只要是极验的滑动验证码基本上都已经不能破解了,!!! 实现方法没错,但是极验的验证码已经使用了机器学习,只有刚刚开始可能是滑块验证码,过一两次可能就是不是滑块验证码而是其他的选字或者选图的验证码了,然后我去换极验的其他网站,如果换其他网站又得重新写自动化脚本,这个其实还好,但是又要去重新截验证图片,而且不同的网站的登录窗口位置不一样,所以GG!!!
 当时我也基本崩溃了,这么多网站我上哪找一个没有机器学习的简单的滑块验证码,对我一个小白太说真的太不友好了QAQ,但是最后还是找到了!(小声bb,幸亏腾讯这个大厂还没有使用机器学习到这上面,应该是腾讯不想使用别人的接口吧,也不知道腾讯多久才会升级这个滑块验证码,它升级之时,也就是本篇博客废除之时了。)
 折腾这么久也算是圆满结局了,作为一个小白真的太不容易了。也体会到了python的便捷性,真的是太后悔没有用python写个刷课脚本了。然后还有一点学习心得就是,学习一定要及时总结,尤其是学计算机这一块,一定要多写写博客及时总结才会促使自己不断进步,真的太后悔当初没有一直保持好这个习惯,老年人落泪呜呜呜~~~~~

参考

https://www.cnblogs.com/xtjiaoyou/archive/2020/03/22/12530851.html
http://www.mamicode.com/info-detail-2172754.html


http://www.ppmy.cn/news/370452.html

相关文章

助你更好的理解 Python 字典

助你更好的理解 Python 字典 字典是Python中的常用数据类型之一&#xff0c;可将数据存储在键/值对中&#xff0c;同 Java 中的 Map 相似。 1、什么是字典理解&#xff1f; 字典理解是创建字典的一种优雅简洁的方法。 字典理解优化 使用字典理解优化函数。 示例&#xff…

远程仓库拉不下来怎么办

因为项目需要做一个word转pdf的功能, 当我想要从阿里的仓库引入依赖时发现版本一直报错,无论怎么引入都爆红😭😭 *我将aspose的包先下载到本地,然后再安装安装到本地的maven仓库* mvn install:install-file -Dfile=C:\Users\Administrator\Downloads\aspose-words-18.…

TreeMap源码

介绍 如果我们希望Map可以保持key的大小顺序时&#xff0c;就需要利用TreeMap。底层使用了红黑树&#xff0c;左子树总小于root&#xff0c;右子树总大于root&#xff0c;具有很好的平衡性,操作速度达到log(n)。 TreeMap 相比于HashMap多实现了了NavigableMap接口&#xff08…

低代码01之构建项目框架

目录 低代码之构建框架11&#xff1a;项目初始化2&#xff1a;src / data.json 数据 &#xff08; 容器大小与渲染的表单数据 &#xff09;3&#xff1a;App.vue ( 导入editor组件传递data.json之中的数据与 向下提供组件配置数据config )4&#xff1a;src / packages / editor…

深入理解深度学习——注意力机制(Attention Mechanism):带掩码的多头注意力(Masked Multi-head Attention)

分类目录&#xff1a;《深入理解深度学习》总目录 相关文章&#xff1a; 注意力机制&#xff08;AttentionMechanism&#xff09;&#xff1a;基础知识 注意力机制&#xff08;AttentionMechanism&#xff09;&#xff1a;注意力汇聚与Nadaraya-Watson核回归 注意力机制&#…

谷歌网盘扩容 - Google Drive Upgrade

介绍 平时需要用谷歌网盘&#xff08;Google Drive&#xff09;来管理、发布一些大文件&#xff0c;但是免费的15GB很快就用完了。想开通会员&#xff0c;就是那些100GB或者更多的升级包&#xff0c;发现需要信用卡或者paypal&#xff0c;然而我并没有信用卡也无法使用paypal。…

无手机注册谷歌账户

使用edge浏览器&#xff0c;非谷歌的估计也可以

分享可用的谷歌学术(google scholar) hosts

看到知乎上的一个回答&#xff0c;用了近两个月&#xff0c;算是比较稳定。终于不用到处找镜像站了 172.245.241.129 scholar.google.com 172.245.241.129 scholar.google.com.hk 172.245.241.129 scholar.google.com.tw 172.245.241.129 scholar.google.com.sg 172.245.2…