基于opencv的selenium滑动验证码的实现
作者:_xiaolanlan 发布时间:2023-06-20 20:14:26
基于selenium进行动作链
由于最近很多人聊到滑动验证码怎么处理,所以决定自己动手试一下。
做一个东西前。我们首先要对这个东西的操作过程有一个大概的了解。
打开验证码页面。
鼠标放到拖动按钮上
对拖动按钮进行拖动
拖动到阴影快重合的位置。
放开拖动按钮。
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
artice = 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的方法。其他方法这里不过多介绍,想了解更多的请转seleniun 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_exm
x1, y1, x2, y2 = list_exm
dist_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 = False
x1, y1, x2, y2 = line1
x3, y3, x4, y4 = line2
x = y = 0
if (x2 - x1) == 0: # 垂直x轴
k1 = None
b1 = 0
else:
k1 = 1.0 * (y2 - y1) / (x2 - x1)
b1 = y1 * 1.0 - k1 * x1 * 1.0
if (x4 - x3) == 0:
k2 = None
b2 = 0
else:
k2 = 1.0 * (y4 - y3) / (x4 - x3)
b2 = y3 * 1.0 - k2 * x3 * 1.0
if k1 is None:
if not k2 is None:
x = x1
y = k2 * x1 + b2
poit_status = True
elif k2 is None:
x = x3
y = k1 * x3 + b1
poit_status = True
elif k1 != k2:
x = (b2 - b1) * 1.0 / (k1 - k2)
y = k1 * x * 1.0 + b1 * 1.0
poit_status = True
return 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/5
t = 0.2
v = 0
steps_list = []
current_offset = 0
while current_offset<xoffset:
if current_offset<updistance:
a = 2 + random.random() * 2
else:
a = -random.uniform(12,13)
vo = v
v = vo + a * t
x = 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()
来源:https://blog.csdn.net/qq_41869994/article/details/107474293
猜你喜欢
- 本文实例讲述了Python使用Selenium模块模拟浏览器抓取斗鱼直播间信息。分享给大家供大家参考,具体如下:import timefro
- 很久没有跟其他人做重构思想方面的交流了,可能大家都觉得不太好意思讨论,特别是“分离”的思想这么基础的话题,拿出来说怕会被“笑话”。做为页面重
- DateDiff 函数描述 返回两个日期之间的时间间隔。 语法 DateDiff(interval, date1, date2 [,firs
- 学习目的: 学习ADO.NET用法,并如何用DataRearder读取数据 今天练习数据库的最基本用法,如何打开数据库。首先在网站设置文件w
- 公布到网页上的Email经常会被一些工具自动提取,一些非法用户就会利用所提取的Email大肆发送垃圾邮件。这些工具大多都是查找链接中“mai
- 第一次做完主从库同步后正常,但工作过程中发现有一个库的数据库没有同步起来,在另外一个mysql(3307)中于是:1、在主库中创建一个临时库
- 对于SQL的Join,在学习起来可能是比较乱的。我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于
- 描述Python strip() 方法用于移除字符串头尾指定的字符(默认为空格)。语法strip()方法语法:str.strip([char
- 这里其实并不需要其它的什么函数来支持,只需要使用MYSQL提供的一些SQL语句就可以了。这里为了简单起见,以MYSQL的系统表USER为例,
- 正确使用字体和颜色可以让网页内容更易阅读,下面我们来看看具体的优化措施。留意颜色的对比对于视力不太好的人或者对于不太好的显示设备来说,黑地白
- 随着网页制作热潮的兴起,Dreamweaver 4.0强大的功能深受众多网页制作者的喜爱。特别是Dreamweaver 4.0中有许多第三方
- 以下测试用于去除任何字符串中连线的分隔符 代码如下:--去除字符串中连续的分隔符 declare @str nvarchar(200) de
- PDO::errorInfoPDO::errorCode — 返回最后一次操作数据库的错误信息(PHP 5 >= 5.1.0, PEC
- Truncate是SQL中的一个删除数据表内容的语句,用法是:TRUNCATE TABLE [Table Name]。下面是对Truncat
- match()方法用于从字符串中查找指定的值本方法类似于indexOf()和lastindexOf(),不同的是它返回的是指定的值,而不是指
- 检测submit事件的冒泡情况:<!doctype html><html dir="ltr" lang
- 索引是快速搜索的关键。MySQL索引的建立对于MySQL的高效运行是很重要的。下面介绍几种常见的MySQL索引类型。在数据库表中,对字段建立
- 什么是CSS Sprites?“Sprite”(精灵)这个词在计算机图形学中有它独特的定义,由于游戏、视频等画质越来越高,必须有一种技术可以
- 昨天美国雅虎正式宣布网站首页的新版,这也算互联网一件大事,尤其是对设计的朋友们。而且现在的美国雅虎的情况也不是很好的情况下有大刀阔斧的进行改
- <%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%>