100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 利用python selenium+cv2破解qq空间登录滑动验证码(无法获得完整图情况)(上)

利用python selenium+cv2破解qq空间登录滑动验证码(无法获得完整图情况)(上)

时间:2020-07-28 11:59:52

相关推荐

利用python selenium+cv2破解qq空间登录滑动验证码(无法获得完整图情况)(上)

之前动手用python写了一个qq空间自动点赞的脚本,登录方法采用的是selenium获取网页截图然后返回二维码截图,用手机qq扫一扫进行登录.

然后又用flask简单的写成了网页,放到了自己的服务器上,这样每次只需要输入网址就会弹出二维码,手机qq扫一扫便可以登录,十分方便.

但由于qq空间的机制,cookie有效期为48小时.因此就必须每两天进行一次登录(有邮箱提醒).虽然还算比较方便,但是对于程序猿来说这些还不够完美.

以上为另一种思路,供大家参考,接下来我将讲述我如何利用cv2实现破解滑动验证码

1.首先,下载cv2库

根据python官方文档

我选择了

pip install opencv-contrib-python

2.通过selenium获取一定数量的验证码,看看有没有共同的规律

直接放代码,但我不知道为什么每次只能获取4次,然后就停止了.可能是tx的某种反爬侦测.

from selenium import webdriverfrom selenium.webdriver.chrome.options import Optionsimport timeimport requestsurl='/'username=123456789#其实内容无所谓因为不滑动验证码是不会post账号密码的password=123456789opt=Options()opt.add_argument('--headless')driver=webdriver.Chrome(chrome_options=opt)i=13while i<30:driver.get(url)login_frame=driver.find_element_by_id('login_frame')driver.switch_to_frame(login_frame)driver.find_element_by_xpath('/html/body/div[1]/div[9]/a[1]').click()nameI=driver.find_element_by_xpath('/html/body/div[1]/div[5]/div/div[1]/div[3]/form/div[1]/div/input').send_keys(username)pwdI=driver.find_element_by_xpath('/html/body/div[1]/div[5]/div/div[1]/div[3]/form/div[2]/div[1]/input').send_keys(password)submit=driver.find_element_by_xpath('/html/body/div[1]/div[5]/div/div[1]/div[3]/form/div[4]/a/input').click()time.sleep(1)frame=driver.find_element_by_id('tcaptcha_iframe')driver.switch_to_frame(frame)imgUse=driver.find_element_by_xpath('/html/body/div[1]/div[3]/div[2]/div[1]/div[2]/img').get_attribute('src')imgNeed=driver.find_element_by_xpath('/html/body/div[1]/div[3]/div[2]/div[1]/div[3]/img').get_attribute('src')imgU=requests.get(imgUse)imgN=requests.get(imgNeed)imgU=imgU.contentimgN=imgN.contentwith open('E:/Download/qq空间滑动验证码/'+str(i)+'.jpg','wb') as f:f.write(imgU) with open('E:/Download/qq空间滑动验证码/'+str(i)+'s.jpg','wb') as f:f.write(imgN)i+=1

这些就是我获得到的图片和小方块

放大观看每一张图

会发现每个图片的拼图部分都有一个白边

这就给了我们定位的好方法

3.利用cv库根据轮廓来分出拼图的位置----根据阈值转化成二值化图

用到函数有

cv2.imread(文件file,标记)

标记:1是彩色,0是灰度

cv2.namedWindow(窗口名,窗口模式)

窗口模式:cv2.WINDOW_AUTOSIZE(自动大小),cv2.WINDOW_NORMAL(手动大小)

cv2.imshow(窗口名,图片变量名)

字面意思,不解释

cv2.waitKey(毫秒)

没有这行的话会闪过去

cv2.threshold (图片变量名, 阈值, 填充色, 填充方法)

源图片必须是单通道,所以刚开始的cv2.read()要加参数0,表示读取灰度图

阈值在0~255之间,我不了解阈值的大小,所以进行了一番不同阈值的显示测试

填充色即字面意思

填充方法见下面链接大神的博客,我先给出截图

需要注意的是返回值是两个,需要用两个变量来接收

另一位大神关于cv阈值的简单解释

简单的利用代码看了不同阈值下的成果(ps自己也初学cv,没研究怎么一起显示)

import cv2for i in range(1,9):img=cv2.imread('./jpg/'+str(i)+'.jpg',0)#0为灰度图,注意路径,我设置的是程序所在目录的子文件夹re,img1=cv2.threshold(img,95,255,0)#返回了两个值,但我们用不上第一个返回值re,img2=cv2.threshold(img,150,255,0)re,img3=cv2.threshold(img,220,255,0)re,img4=cv2.threshold(img,240,255,0)re,img5=cv2.threshold(img,250,255,0)re,img6=cv2.threshold(img,260,255,0)cv2.namedWindow('img',cv2.WINDOW_AUTOSIZE)cv2.imshow('img',img1)cv2.waitKey(0)#不加这个的话会一闪而逝cv2.imshow('img',img2)cv2.waitKey(0)cv2.imshow('img',img3)cv2.waitKey(0)cv2.imshow('img',img4)cv2.waitKey(0)cv2.imshow('img',img5)cv2.waitKey(0)cv2.imshow('img',img6)cv2.waitKey(0)

效果如下

95

150

220

240

250

260

需要注意的是,接下来我们要使用的轮廓,只会找连续的颜色,因此阈值设置太高的话,线条不连续,会检测不到

4.获得轮廓

用到的新的函数有

cv2.findContours(图片变量(二值图),轮廓的检索模式,轮廓的近似办法)

图片变量要二值图,这也是为什么在第三步需要用到阈值

轮廓的检索模式有四种:

cv2.RETR_EXTERNAL只检测外轮廓

cv2.RETR_LIST检测的轮廓不建立等级关系

cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。

cv2.RETR_TREE建立一个等级树结构的轮廓。

轮廓的近似方法(部分):

cv2.CHAIN_APPROX_NONE存储所有的轮廓点(占内存)

cv2.CHAIN_APPROX_SIMPLE只保留终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息(省内存)

咱们采用cv2.RETR_TREEcv2.CHAIN_APPROX_NONE

注意!!!

报错:too many values to unpack说明你接收用的变量数量不对

cv2.findContours函数的返回值有过很多变化

openCV2.0版本返回值有两个

openCV3.0版本返回值有三个

openCV4.0版本返回值又变成了只有两个

我使用4.0版本,因此返回值是轮廓,轮廓的索引

其中轮廓是一个list,索引是个高级的东西.我也不知道是啥反正用不上

cv2.drawContours(图片变量(三通道), 轮廓, 第几个轮廓,颜色, 线宽度)

图片变量要三通道图,不过后来试了下灰度图也不报错了,但是灰度图不方便观察轮廓线,还是推荐三通道图

轮廓就是之前获得的那个list

第几个轮廓是个int类型的变量,-1代表所有轮廓一起加载

颜色可以是个元组,如(255,0,0)表示蓝色.或者直接int类型的255也是蓝色

线宽度,字面意思,-1表示填充模式(不懂)

import cv2for i in range(1,9):img=cv2.imread('./jpg/'+str(i)+'.jpg',0)re,img1=cv2.threshold(img,125,255,0)cv2.namedWindow('img',cv2.WINDOW_AUTOSIZE)cv2.imshow('img',img1)contours,b=cv2.findContours(img1.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)cv2.waitKey(0)for j in range(0,len(contours)-1):image=cv2.imread('./jpg/'+str(i)+'.jpg',1)#获取三通道图image=cv2.drawContours(image, contours, j, 255, 3)#绘制轮廓cv2.imshow('img',image)cv2.waitKey(0)

但是单纯的画轮廓,每张图都检测到了几百个轮廓,这可不行

随便某一个轮廓

5.轮廓的筛选

以下是看云上的openCV-Python中文教程节选片段

openCV-Python中文教程

首先,我们可以根据轮廓面积进行筛选

经过我的测试,正常的拼图面积在6000-8000之间

因此,咱们先这样

import cv2for i in range(1,9):img=cv2.imread('./jpg/'+str(i)+'.jpg',0)re,img1=cv2.threshold(img,125,255,0)cv2.namedWindow('img',cv2.WINDOW_AUTOSIZE)cv2.imshow('img',img1)contours,b=cv2.findContours(img1.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)cv2.waitKey(0)for j in range(0,len(contours)-1):area=cv2.contourArea(contours[j])if area<6000 or area>8000:continueprint(area)image=cv2.imread('./jpg/'+str(i)+'.jpg',1)image=cv2.drawContours(image, contours, j, 255, 3)#绘制轮廓cv2.imshow('img',image)cv2.waitKey(0)

这样基本就筛选出了准确的图案

但光有面积是不够的,你会发现这样的情况

这个图案的面积是7385.5,也在我们的筛选范围内

因此第二步,我们要根据图案的重心位置来进行进一步判断

根据我的测试,拼图出现的位置只在后方,即x坐标大于500的地方

因此,代码改写如下

import cv2for i in range(1,9):img=cv2.imread('./jpg/'+str(i)+'.jpg',0)re,img1=cv2.threshold(img,125,255,0)cv2.namedWindow('img',cv2.WINDOW_AUTOSIZE)cv2.imshow('img',img1)contours,b=cv2.findContours(img1.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)cv2.waitKey(0)for j in range(0,len(contours)-1):M = cv2.moments(contours[j]) # 计算第一条轮廓的各阶矩,字典形式try:#防止分母等于0报错center_x = int(M["m10"] / M["m00"])center_y = int(M["m01"] / M["m00"])except:continue#如果分母等于0,那一定不是我们的目标,因此可以直接跳过当前循环area=cv2.contourArea(contours[j])if area<6000 or area>8000 or center_x<500:continueprint(area)print(center_x)image=cv2.imread('./jpg/'+str(i)+'.jpg',1)image=cv2.drawContours(image, contours, j, 255, 3)#绘制轮廓image=cv2.circle(image, (center_x, center_y), 7, 128, -1)#绘制中心点cv2.imshow('img',image)cv2.waitKey(0)

至此,我们已经可以准确的定位到拼图的位置,接下来需要的就是计算出需要移动的距离,以及selenium模拟人的操作

我会整理下我的代码全部放到porn啊不是,全部放到github上。地址在这里:qq空间自动点赞

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。