• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

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

python 搞代码 4年前 (2022-01-09) 17次浏览 已收录 0个评论

基于selenium进行动作链

由于最近很多人聊到滑动验证码怎么处理,所以决定自己动手试一下。
做一个东西前。我们首先要对这个东西的操作过程有一个大概的了解。

  • 打开验证码页面。
  • 鼠标放到拖动按钮上
  • 对拖动按钮进行拖动
  • 本文来源gaodai$ma#com搞$代*码网2

  • 拖动到阴影快重合的位置。
  • 放开拖动按钮。
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()

效果图

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


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:基于opencv的selenium滑动验证码的实现
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址