这篇文章主要介绍了基于opencv的selenium滑动验证码的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
基于selenium进行动作链
由于最近很多人聊到滑动验证码怎么处理,所以决定自己动手试一下。
做一个东西前。我们首先要对这个东西的操作过程有一个大概的了解。
-
打开验证码页面。
-
鼠标放到拖动按钮上
-
对拖动按钮进行拖动
-
拖动到阴影快重合的位置。
-
放开拖动按钮。
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChainsartice = browser.find_element_by_class_name('geetest_slider_button') # 滑动按钮
action = ActionChains(browser)
action.click_and_hold(artice).perform() #按住按钮不放
action.reset_actions()
action.pause(0.01).move_by_offset(step, 0).perform() #step 为滑动的水平距离
action.release(artice).perform() # 松开按钮
上面就是本方用到的有关于ActionChains的方法。
接下来到我本次要介绍的重点,滑动距离的介绍,也就是图片求阴影区域的位置。
这里我使用了opencv库,主要流程包括
-
对图像二值化
-
对二值化的图像进行高斯模糊
-
用canny进行边缘检测
-
然后HoughLinesP霍夫变换寻找直线
-
对符合条件的直线进行处理寻找交点,进而求出我们要找的阴影快的距离
import cv2 as cv
import numpy as np
import math# 寻找直线
def FindLines(image):image = cv.cvtColor(image, cv.COLOR_BGR2GRAY) # 二值化blurred = cv.GaussianBlur(image, (5, 5), 0) # 高斯模糊canny = cv.Canny(blurred, 200, 400) # canny边缘检测lines = cv.HoughLinesP(canny, 1, np.pi / 180, 20, minLineLength=15, maxLineGap=8) # 霍夫变换寻找直线return lines[:, 0, :] # 返回直线# 这里对直线进行过滤
def FindResultLises(lines):resultLines = []for x1, y1, x2, y2 in lines:if (abs(y2 - y1) < 5 or abs(x2 - x1) < 5) and min(x1, x2) > 60: # 只要垂直于坐标轴的直线并且起始位置在60像素以上resultLines.append([x1, y1, x2, y2])return resultLines# 判断点是否在直线上
def distAbs(point_exm, list_exm):x, y = point_exmx1, y1, x2, y2 = list_exmdist_1 = math.sqrt(abs((y2 - y1) + (x2 - x1) + 1)) # 直线的长度dist_2 = math.sqrt(abs((y1 - y) + (x1 - x) + 1)) + math.sqrt(abs((y2 - y) + (x2 - x) + 1)) # 点到两直线两端点距离和return abs(dist_2 - dist_1) # 交点函数 y = kx + b 求交点位置
def findPoint(line1, line2):poit_status = Falsex1, y1, x2, y2 = line1x3, y3, x4, y4 = line2x = y = 0if (x2 - x1) == 0: # 垂直x轴k1 = Noneb1 = 0else:k1 = 1.0 * (y2 - y1) / (x2 - x1)b1 = y1 * 1.0 - k1 * x1 * 1.0if (x4 - x3) == 0:k2 = Noneb2 = 0else:k2 = 1.0 * (y4 - y3) / (x4 - x3)b2 = y3 * 1.0 - k2 * x3 * 1.0if k1 is None:if not k2 is None:x = x1y = k2 * x1 + b2poit_status = Trueelif k2 is None:x = x3y = k1 * x3 + b1poit_status = Trueelif k1 != k2:x = (b2 - b1) * 1.0 / (k1 - k2)y = k1 * x * 1.0 + b1 * 1.0poit_status = Truereturn poit_status, [x, y]# 求交点
def linePoint(resultLines):for x1, y1, x2, y2 in resultLines:for x3, y3, x4, y4 in resultLines:point_is_exist, [x, y] = findPoint([x1, y1, x2, y2], [x3, y3, x4, y4]) # 两线是否有交点if point_is_exist:dist_len1 = distAbs([x, y], [x1, y1, x2, y2])dist_len2 = distAbs([x, y], [x3, y3, x4, y4])if dist_len1 < 5 and dist_len2 < 5: # 如果误差在5内我们认为点在直线上# 判断交点在行直线中是左端点还是右端点if abs(y2 - y1) < 5:# x1是行直线if abs(x1 - x) + abs(y1 - y) < 5: # 左端点return -1, [x, y]else:return 1, [x, y]else:# x2是行直线if abs(x3 - x) + abs(y3 - y) < 5:return -1, [x, y]else:return 1, [x, y]return 0, [0, 0]if __name__ == '__main__':img = cv.imread(r'C:\Users\Administrator\Desktop\opencv\temImg.png')lines = FindLines(img)lines = FindResultLises(lines)L_or_R, point_x = linePoint(lines) # L_or_R 用于判断交点在行直线左边还是右边 后面拖动要用到xoffset = point_x[0]yoffset = point_x[1]cv.circle(img, (int(xoffset), int(yoffset)), 5, (0, 0, 255), 3)cv.imshow('circle', img)cv.waitKey(0)cv.destroyAllWindows()
效果图
当然也有操作不到的图片,各位有兴趣的可以尝试并且修改其中的参数
滑动验证码
在上面我们已经找到了边缘点,并且根据交点是在左边还是右边进行计算,找到我们要滑动的最后值
if L_or_R == 1:x_offset = xoffset - 20 # 20是阴影快一半的长度 可根据实际情况调整
else:x_offset = offset + 20
有了滑动距离,接下来就应该是滑动了
如果我们直接用 action.move_by_offset(x_offset,0).perform() 图片会图示被怪物吃了。那就是运动轨迹被检测到不是正常人的行为,因为正常人很难一拉就拉到对应的位置。
滑动轨迹算法
所以我们还要有一个模拟人的正常操作的拖动轨迹:下面是以先加速再减速的轨迹
import ramdom# 通过加速减速模拟滑动轨迹
def moveTrack(xoffset):updistance = xoffset*4/5t = 0.2v = 0steps_list = []current_offset = 0while current_offset<xoffset:if current_offset<updistance:a = 2 + random.random() * 2else:a = -random.uniform(12,13)vo = vv = vo + a * tx = vo * t + 1 / 2 * a * (t * t)x = round(x, 2)current_offset += abs(x)steps_list.append(abs(x))# 上面的 sum(steps_list) 会比实际的大一点,所以再模拟一个往回拉的动作,补平多出来的距离disparty = sum(steps_list)-xoffset last1 = round(-random.random() - disparty, 2)last2 = round(-disparty-last1, 2)steps_list.append(last1)steps_list.append(last2)return steps_list
有了轨迹 steps_list 我们就可以通过循环来拖动按钮。需要注意的一点是 每一次循环都要action.reset_actions() 不然他会把之前的距离也算进来,循环结束记得松开按钮
for step in steps_list:action.reset_actions()action.pause(0.01).move_by_offset(step, 0).perform()
action.release(artice).perform()
到此这篇关于基于opencv的selenium滑动验证码的实现的文章就介绍到这了。
最后
如果你想学习自动化测试,那么下面这套视频应该会帮到你很多
如何逼自己1个月学完自动化测试,学完即就业,小白也能信手拈来,拿走不谢,允许白嫖....
最后我这里给你们分享一下我所积累和整理的一些文档和学习资料,有需要直接领取就可以了!
以上内容,对于软件测试的朋友来说应该是最全面最完整的备战仓库了,为了更好地整理每个模块,我也参考了很多网上的优质博文和项目,力求不漏掉每一个知识点,很多朋友靠着这些内容进行复习,拿到了BATJ等大厂的offer,这个仓库也已经帮助了很多的软件测试的学习者,希望也能帮助到你。