爬虫.防人机验证之——滑块验证

467 阅读3分钟

上篇文章介绍了数字验证码和文字点选验证的解决方法,这篇文章继续介绍滑块验证的通过方法。

前面两个实际操作比滑块难,但是用代码操作则是滑块更难,之所以把滑块单独拿出来,因为这篇滑块验证的通过方式不会用到平台工具。废话不多说,上代码

  1. 首先,需要得到背景图片和滑块图片 如图:

bg.png gap.png

  1. 计算缺口函数的x坐标
def identify_gap(self, bg_image, tp_image, out="new_image.png"):
    """
        通过cv2计算缺口位置
        :param bg_image: 有缺口的背景图片文件
        :param tp_image: 缺口小图文件图片文件
        :param out: 绘制缺口边框之后的图片
        :return: 返回缺口位置
        """
    # 读取背景图片和缺口图片
    bg_img = cv2.imread(bg_image)  # 背景图片
    tp_img = cv2.imread(tp_image)  # 缺口图片
    # 识别图片边缘
    # 因为验证码图片里面的目标缺口通常是有比较明显的边缘 所以可以借助边缘检测算法结合调整阈值来识别缺口
    # 目前应用比较广泛的边缘检测算法是Canny John F.Canny在1986年所开发的一个多级边缘检测算法 效果挺好的
    bg_edge = cv2.Canny(bg_img, 100, 200)
    tp_edge = cv2.Canny(tp_img, 100, 200)
    print(bg_edge, tp_edge)
    # 转换图片格式
    # 得到了图片边缘的灰度图,进一步将其图片格式转为RGB格式
    bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
    tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)
    # 缺口匹配
    # 一幅图像中找与另一幅图像最匹配(相似)部分 算法:cv2.TM_CCOEFF_NORMED
    # 在背景图片中搜索对应的缺口
    res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
    # res为每个位置的匹配结果,代表了匹配的概率,选出其中「概率最高」的点,即为缺口匹配的位置
    # 从中获取min_val,max_val,min_loc,max_loc分别为匹配的最小值、匹配的最大值、最小值的位置、最大值的位置
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)  # 寻找最优匹配
    # 绘制方框
    th, tw = tp_pic.shape[:2]
    tl = max_loc  # 左上角点的坐标
    br = (tl[0] + tw, tl[1] + th)  # 右下角点的坐标
    cv2.rectangle(bg_img, tl, br, (0, 0, 255), 2)  # 绘制矩形
    cv2.imwrite(out, bg_img)  # 保存在本地
    # 返回缺口的X坐标
    return tl[0]

3.滑动滑块

# 滑动函数
def move_slide(self, offset_x, offset_y, left):
    """
    执行滑动操作,模拟人类滑动鼠标的行为。

    参数:
    - offset_x: 滑动开始的x轴偏移量
    - offset_y: 滑动开始的y轴偏移量
    - left: 滑动的距离

    此函数无返回值。
    """
    # 移动鼠标到起始位置
    pyautogui.moveTo(offset_x, offset_y, duration=0.1 + random.uniform(0, 0.1 + random.randint(1, 100) / 100))
    # 按下鼠标,准备开始滑动
    pyautogui.mouseDown()
    # 调整y轴位置,模拟不规则的滑动路径
    offset_y += random.randint(9, 19)
    # 执行滑动操作,逐渐接近目标位置
    pyautogui.moveTo(offset_x + int(left * random.randint(15, 25) / 20), offset_y, duration=0.28)
    # 再次调整y轴位置,增加滑动的随机性
    offset_y += random.randint(-9, 0)
    pyautogui.moveTo(offset_x + int(left * random.randint(17, 23) / 20), offset_y,
                     duration=random.randint(20, 31) / 100)
    # 继续微调y轴位置,模拟自然的滑动行为
    offset_y += random.randint(0, 8)
    pyautogui.moveTo(offset_x + int(left * random.randint(19, 21) / 20), offset_y,
                     duration=random.randint(20, 40) / 100)
    # 接近最终位置,进行细微调整
    offset_y += random.randint(-3, 3)
    pyautogui.moveTo(left + offset_x + random.randint(-3, 3), offset_y,
                     duration=0.5 + random.randint(-10, 10) / 100)
    # 最后的调整,确保到达目标位置
    offset_y += random.randint(-2, 2)
    pyautogui.moveTo(left + offset_x + random.randint(-2, 3), offset_y, duration=0.5 + random.randint(-3, 3) / 100)
    # 释放鼠标,完成滑动操作
    pyautogui.mouseUp()
    # 等待一段时间,模拟人类操作后的停顿
    time.sleep(3)

接下来只需要调用这两个函数就行,代码复制即可使用