基于opencv的selenium滑动验证码的实现


Posted in Python onJuly 24, 2020

基于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()

基于opencv的selenium滑动验证码的实现

基于opencv的selenium滑动验证码的实现

效果图

当然也有操作不到的图片,各位有兴趣的可以尝试并且修改其中的参数

滑动验证码

在上面我们已经找到了边缘点,并且根据交点是在左边还是右边进行计算,找到我们要滑动的最后值

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()

到此这篇关于基于opencv的selenium滑动验证码的实现的文章就介绍到这了,更多相关opencv selenium滑动验证码内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python字符串和常用数据结构知识总结
May 21 Python
django基础学习之send_mail功能
Aug 07 Python
Python笔试面试题小结
Sep 07 Python
如何利用Python开发一个简单的猜数字游戏
Sep 22 Python
Python 实现黑客帝国中的字符雨的示例代码
Feb 20 Python
python 递归调用返回None的问题及解决方法
Mar 16 Python
重写django的model下的objects模型管理器方式
May 15 Python
django admin管理工具自定义时间区间筛选器DateRangeFilter介绍
May 19 Python
python安装和pycharm环境搭建设置方法
May 27 Python
Python如何自动获取目标网站最新通知
Jun 18 Python
使用PyCharm安装pytest及requests的问题
Jul 31 Python
Python Selenium破解滑块验证码最新版(GEETEST95%以上通过率)
Jan 29 Python
详解python中GPU版本的opencv常用方法介绍
Jul 24 #Python
python定义类的简单用法
Jul 24 #Python
Python爬虫抓取指定网页图片代码实例
Jul 24 #Python
详解Flask前后端分离项目案例
Jul 24 #Python
通过实例了解Python异常处理机制底层实现
Jul 23 #Python
Python异常处理机制结构实例解析
Jul 23 #Python
使用pygame实现垃圾分类小游戏功能(已获校级二等奖)
Jul 23 #Python
You might like
php时区转换转换函数
2014/01/07 PHP
Eclipse的PHP插件PHPEclipse安装和使用
2014/07/20 PHP
php实现与erlang的二进制通讯实例解析
2014/07/23 PHP
使用PHP处理数据库数据如何将数据返回客户端并显示当前状态
2016/02/16 PHP
php实现批量修改文件名称的方法
2016/07/23 PHP
PHP面向对象程序设计之类与反射API详解
2016/12/02 PHP
Yii CDBCriteria常用方法实例小结
2017/01/19 PHP
JavaScript中的isXX系列是否继续使用的分析
2011/04/16 Javascript
JavaScript加强之自定义event事件
2013/09/21 Javascript
js表单处理中单选、多选、选择框值的获取及表单的序列化
2016/03/08 Javascript
微信小程序购物商城系统开发系列-目录结构介绍
2016/11/21 Javascript
关于vue的语法规则检测报错问题的解决
2018/05/21 Javascript
详解JavaScript中操作符和表达式
2018/09/12 Javascript
jQuery实现的简单歌词滚动功能示例
2019/01/07 jQuery
Vue的transition-group与Virtual Dom Diff算法的使用
2019/12/09 Javascript
vue+element获取el-table某行的下标,根据下标操作数组对象方式
2020/08/07 Javascript
[04:03]辉夜杯主赛事 12月25日RECAP精彩回顾
2015/12/26 DOTA
使用python BeautifulSoup库抓取58手机维修信息
2013/11/21 Python
深入Python解释器理解Python中的字节码
2015/04/01 Python
浅谈flask中的before_request与after_request
2018/01/20 Python
Python实现的批量修改文件后缀名操作示例
2018/12/07 Python
python pandas生成时间列表
2019/06/29 Python
python数据化运营的重要意义
2019/11/25 Python
详解django中Template语言
2020/02/22 Python
python tqdm库的使用
2020/11/30 Python
PHP面试题-$message和$$message的区别
2015/12/08 面试题
什么是用户模式(User Mode)与内核模式(Kernel Mode) ?
2014/07/21 面试题
医生进修自我鉴定
2014/01/19 职场文书
什么样的创业计划书可行性高?
2014/02/01 职场文书
2014学雷锋活动总结
2014/03/09 职场文书
保健品市场营销方案
2014/03/31 职场文书
监察局领导班子四风问题整改措施思想汇报
2014/10/05 职场文书
周一给客户的问候语
2015/11/10 职场文书
教师法制教育培训学习心得体会
2016/01/14 职场文书
标准版个人借条怎么写?以及什么是借条?
2019/08/28 职场文书
html form表单基础入门案例讲解
2021/07/21 HTML / CSS