搞定拼多多双阴影滑块验证码
回答
收藏

搞定拼多多双阴影滑块验证码

恒星
2024-03-13 20:43·浏览量:6477
恒星
发布于 2023-04-17 11:45更新于 2024-03-13 20:436477浏览

场景介绍:影刀内置了很多关于验证码的指令,足够应付众多场景的验证码校验,但是拼多多的双阴影滑块验证,由于只能捕获到一个大块元素,无法准确捕获到缺块、背景和拖拽滑块,并且背景的缺口会在用户鼠标点下拖拽滑块时随机偏移,此时显示的才是真实的缺口位置,所以目前的验证码指令就不适用了。(这里的验证码的在PC端打开手机版拼多多商城网页,弹出新网页的滑块验证,不是嵌入在某个网页内的。)

解决思路:先鼠标按下拖拽滑块,暴露出缺口的实际位置,通过元素截图分割把背景区域截取下来,用openCV模块进行缺口距离的识别,再用鼠标拖动对应距离即可。

获取拖拽滑块的坐标:

由于无法捕获到各个小元素,所以本文定位元素的思路是通过大块元素的总长度、总宽度以及元素在大块元素的相对位置去计算得出所需的元素坐标。例如拖拽滑块的位置可以通过指定从大块元素向右、向上偏移n个像素的距离,距离又可以通过大块元素的总长、宽度与滑块的相对位置系数相乘得到。横向距离:int((元素.right-元素.left)*0.1606805),纵向距离:int((元素.bottom-元素.top)*0.1985981),系数“0.1606805、0.1985981”为拖拽滑块位于大块元素的相对位置。

鼠标悬停到拖拽滑块后,再次获取相对于屏幕左上角的坐标,然后按下鼠标左键,使背景缺口变化,暴露出真实的缺口位置,并将大块元素截图下来,用于后面的裁剪和判断缺口距离。

大块元素截图如下:



用PIL模块将背景从这个截图中裁剪出来,得到:

代码:

# 裁剪背景图片

from PIL import Image

def cutbg(path):  # 传入图片路径

   img = Image.open(path)

   lp = int(float(img.size[0]) * 0.0681818)  # 左边距

   rp = int(float(img.size[0]) * 0.9301346)  # 右边距

   top = int(float(img.size[1]) * 0.0581395)  # 上边距

   button = int(float(img.size[1]) * 0.6523255)  # 下边距

   box1 = (lp, top, rp, button)

   image1 = img.crop(box1)

   return image1  # 返回裁剪后的图片对象

把背景再次裁剪,得到左边的滑块部分和右边的缺口部分:

                     


代码:

# 把背景图片分割成缺块部分和缺口部分(一分为二)

def cut_ab(img, save_path_a, save_path_b):  # 传入背景图片对象以及裁剪后图片保存路径

   img_a = img.copy()

   lp = int(float(img.size[0]) * 0.03125)  # 左边距

   rp = int(float(img.size[0]) * 0.1953125)  # 右边距

   box1 = (lp, 0, rp, int(img.size[1]))

   image_a = img_a.crop(box1)

   image_a.save(save_path_a)

   lp = int(float(img.size[0]) * 0.1953125)  # 左边距

   rp = int(img.size[0])  # 右边距

   box1 = (lp, 0, rp, int(img.size[1]))

   image_b = img.crop(box1)

   image_b.save(save_path_b)

识别缺口距离:

代码:

# 识别图片返回缺口距离

import cv2

def get_x(path_a,path_b):

   bg_img = cv2.imread(path_b)  # 读取背景图片

   tp_img = cv2.imread(path_a)  # 读取滑块图片

   bg_edge = cv2.Canny(bg_img, 100, 200)  # 识别出图片的边缘

   tp_edge = cv2.Canny(tp_img, 100, 200)  # 识别出图片的边缘

   bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)  # 将其图片格式转为RGB格式

   tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)  # 将其图片格式转为RGB格式

   

   res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)  # 缺口匹配

   min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)  # 寻找最优匹配

# 缺口的位置X轴坐标为max_loc[0]

# 左边滑块图片宽度为tp_img.shape[1]

# 两者相加,为缺口距离滑块的距离

   x = max_loc[0] + int(tp_img.shape[1])  

   return x  # 返回缺口距离

用main函数调用上面的函数:

import os

def main(path_img):  # 传入截图的大块元素的图片路径

desk_path = os.path.join(os.path.expanduser('~'),"Desktop")  # 这里调用了os模块获取桌面路径

   path_a = desk_path + r"\yanzhengmaA.png"

   path_b = desk_path + r"\yanzhengmaB.png"

   img = cutbg(path_img)

   cut_ab(img,path_a,path_b)

   X = get_x(path_a,path_b)

到这里,最关键的缺口距离已经拿到了,后面只需要将该距离传给移动鼠标指令,移动到对应位置弹起鼠标左键,验证即可完成。


完成效果:

收藏12
全部回答1
最新
发布回答
回答