基于cv2识别图像实现jd滑动块验证

本文介绍了如何通过图像处理技术,如灰度化、二值化和矩形检测,来解决滑动验证码中的距离获取问题,并针对可能出现的异常情况进行重试和补偿。作者详细展示了从滑动图片中提取坐标的方法和处理过程。
摘要由CSDN通过智能技术生成

本教程无任何意向,纯纯的技术娱乐

虽然小概率出现问题,加入重试机制后,基本没出现过问题
注意:这里获取的距离与实际的距离不相同,本人是1920*1020的,但是与web中的比例为0.78
实际的值为(x - 13) * 281 / 360 这里的 - 13 是为了做矩形的补偿在10-13之间

出现条件:

  1. 短时间内多次失败
  2. 异常环境情况
  3. 未知

解决方案:

通过保存滑动图片,将图片进行灰度化,然后进行二值化,将图片变成黑白,获取所有矩形,并进行过滤,然后进行补偿机制

在这里插入图片描述
在这里插入图片描述

获取滑动的距离

def getXYByImage(filename: str) -> tuple[int, int]:
    """
    从滑动验证码中获取xy坐标
    """
    # 读取显示原图  
    image = cv2.imread(filename)
    cv2.imshow("Original Image", image)
    # cv2.waitKey(0)

    # V通道 灰度图  
    hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    _, _, v_channel = cv2.split(hsv_image)
    cv2.imshow('V Channel', v_channel)
    # cv2.waitKey(0)
    avg_hsv = get_avg(hsv_image)
    logger.info(f"平均灰度值为 {avg_hsv}")

    # 二值化 取灰度范围
    ret1, thres = cv2.threshold(v_channel, avg_hsv, 255, cv2.THRESH_BINARY_INV)
    cv2.imshow('Thresh', thres)
    # cv2.waitKey(0)

    # 闭运算  
    kernel = np.ones((25, 25), np.uint8)
    thres = cv2.morphologyEx(thres, cv2.MORPH_OPEN, kernel)
    cv2.imshow('MORPH_OPEN', thres)
    # cv2.waitKey(0)

    # 找到所有的矩形  
    contours, _ = cv2.findContours(thres, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    xys = []
    # 遍历所有的矩形并计算其坐标和面积,并在原图上绘制绿色边框  
    for i, contour in enumerate(contours):
        # 获取矩形的边界矩形(可能不是严格意义上的矩形,但是边界矩形)  
        x, y, w, h = cv2.boundingRect(contour)
        # 计算面积  
        area = w * h
        # 在原图上绘制绿色边框(注意:需要将图像转换为BGR格式以便正确显示颜色)  
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 1)
        # print(f"Rectangle {i + 1}: Coordinates: ({x}, {y}), Area: {area}")
        xys.append((x, y, area))

    cv2.imshow("Image with Rectangles", image)
    # cv2.imwrite(filename + "_Rectangles_.png", image)
    
    # 筛选最适合的矩形
    for x, y, a in xys:
        if 1000 <= a <= 1100:
            return x, y


def get_avg(img: cv2.typing.MatLike):
    """获取平均灰度值"""
    # 获取图像高度和宽度
    height = img.shape[0]
    width = img.shape[1]

    h_images = []
    # 图像平均灰度处理方法
    for i in range(height):
        for j in range(width):
            # 灰度值为RGB三个分量的平均值
            var = (int(img[i, j][0]) + int(img[i, j][1]) + int(img[i, j][2])) / 3
            h_images.append(var)

    max_prot = h_images[int(len(h_images) / 2):]
    max_prot.remove(min(max_prot))
    return sum(max_prot) / len(max_prot)
    

def save_base64_image(code, name=None):
    """ 保存base64 编码"""
    imagedata = base64.b64decode(code)
    file_name = os.path.join(os.path.dirname(__file__), str(time.time()) if name is None else name) + ".png"
    with open(file_name, "wb") as f:
        f.write(imagedata)
        f.close()
    return file_name

在这里插入图片描述

滑动验证


def _login_un_lock(self, locator: Locator):
    src = locator.locator(".JDJRV-bigimg > img").get_attribute("src")
    image_base64 = src[src.index(",") + 1 :]
    file_name = save_base64_image(image_base64)
    xy = getXYByImage(file_name)
    logger.info(f"x ,y 坐标为{xy}")
    if xy is None:
        self.page.reload()
        os.remove(file_name)
        return
    x, y = xy
    self.un_login_lock(int((x - 13) * 281 / 360), locator.locator(".JDJRV-slide-btn"))
    os.remove(file_name)
    
def un_login_lock(self, distance: int, locator: Locator) -> None:
    locator.blur()
    box = locator.bounding_box()
    tracks = get_track(distance)
    x = int(box["x"] + box["width"] / 2)
    y = int(box["y"] + box["height"] / 2)
    locator.hover()
    self.page.mouse.down()
    self.page.mouse.move(x, y + random.randint(10, 20), steps=12)
    for track in tracks:
        self.page.mouse.move(track + x, y + random.randint(10, 20), steps=9)
        x = x + track
        self.page.wait_for_timeout(random.randint(10, 100))
    self.page.mouse.up()
    self.page.wait_for_timeout(random.randint(2200, 3200))
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值