〖Python网络爬虫实战㊶〗- 极验滑块介绍(三)

 最近更新

〖Python网络爬虫实战㊵〗- 极验滑块介绍(二)

极验验证码

目前,许多网站采取各种各样的措施来反爬虫,其中一个措施便是使用验证码。随着技术的发展,验证码的花样越来越多。验证码最初是几个数字组合的简单的图形验证码,后来加入了英文字母和混淆曲线。有的网站还可能看到中文字符的验证码,这使得识别愈发困难。我们今天来介绍极验验证码。

前言

我们上一篇和大家介绍了怎么去处理图片的还原,今天,我们来说说怎么去计算滑块移动的距离,我们可以通过open-cv来识别,或者其他识别库来识别,我们还可以对比两个图片的像素点。这些都可以直接用别人写好的代码,我这里就不过多赘述。

滑块距离计算

第一种是cv2方法,我找到别人写的比较好的,亲测可用,至于相关库的安装,自己去搜教程。

import io
from PIL import Image
import cv2
import numpy as np

# 将 Image 转换为 Mat,通过 flag 可以控制颜色
def pilImgToCv2(img: Image.Image, flag=cv2.COLOR_RGB2BGR):
    return cv2.cvtColor(np.asarray(img), flag)

# 弹窗查看图片
def showImg(bg: cv2.Mat, name='test', delay=0):
    cv2.imshow(name, bg)
    cv2.waitKey(delay)
    cv2.destroyAllWindows()


def getDistance(img: Image.Image, slice: Image.Image):
    # 通过 pilImgToCv2 将图片置灰
    # 背景图和滑块图都需要做相同处理
    grayImg = pilImgToCv2(img, cv2.COLOR_BGR2GRAY)
    # showImg(grayImg) # 可以通过它来看处理后的图片效果
    graySlice = pilImgToCv2(slice, cv2.COLOR_BGR2GRAY)
    # 做边缘检测进一步降低干扰,阈值可以自行调整
    grayImg = cv2.Canny(grayImg, 255, 255)
    # showImg(grayImg) # 可以通过它来看处理后的图片效果
    graySlice = cv2.Canny(graySlice, 255, 255)
    # 通过模板匹配两张图片,找出缺口的位置
    result = cv2.matchTemplate(grayImg, graySlice, cv2.TM_CCOEFF_NORMED)
    maxLoc = cv2.minMaxLoc(result)[3]
    # 匹配出来的滑动距离
    distance = maxLoc[0]
    # 下面的逻辑是在图片画出一个矩形框来标记匹配到的位置,可以直观的看到匹配结果,去掉也可以的
    sliceHeight, sliceWidth = graySlice.shape[:2]
    # 左上角
    x, y = maxLoc
    # 右下角
    x2, y2 = x + sliceWidth, y + sliceHeight
    resultBg = pilImgToCv2(img, cv2.COLOR_RGB2BGR)
    cv2.rectangle(resultBg, (x, y), (x2, y2), (0, 0, 255), 2)
    # showImg(resultBg) # 可以通过它来看处理后的图片效果
    print(distance)
    return distance, resultBg
sliceimgpath = './slice.png'
imgpath = './缺口背景图片.png'
getDistance(Image.open(imgpath), Image.open(sliceimgpath))

我们来介绍第二种方法,也是本案例所使用的方法,由于不同电脑的分辨率不一样,导致会有一点点误差,大家要自己在代码中修改合适的数值,我这里改的是-6。

def is_pixel_equal(image1, image2, x, y):
    """
    判断两个像素是否相同
    :param image1: 有缺口图片1
    :param image2: 无缺口图片2
    :param x: 位置x
    :param y: 位置y
    :return: 判断同一位置像素是否相同
    """
    pixel1 = image1.load()[x, y]
    pixel2 = image2.load()[x, y]
    threshold = 60
    if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
            pixel1[2] - pixel2[2]) < threshold:
        return True
    else:
        return False


def get_gap(image1, image2):
    """
    获取缺口偏移量
    :param image1: 不带缺口图片
    :param image2: 带缺口图片
    :return:返回缺口位置
    """
    image1 = Image.open(image1)
    image2 = Image.open(image2)
    left = 60
    print('验证码图片宽度和高度:', image1.size)
    for i in range(left, image1.size[0]):
        for j in range(image1.size[1]):
            judge_value = is_pixel_equal(image1, image2, i, j)
            if judge_value is False:
                left = i-6
                return left

在这里,left = i - 6,我这里测试的是减6,你可能不用调整。

我这里运行之后,计算的结果是55,在后面w的逆向会用到。我们这里传入的是一个完整的图片和一个有缺口的图片做对比,而cv2的思路是把滑块也要拿下来和带缺口的图片做对比,因为每个缺口的朝向都不一样,我个人还是倾向于第二种,如果你喜欢第一种,可以自行修改相关代码。

滑块轨迹的代码

我看了很多大佬写的代码,我这里也贴一份大佬写的滑块轨迹代码,目前可用,是没有问题的。

import random
def __ease_out_expo(sep):
    '''
        轨迹相关操作
    '''
    if sep == 1:
        return 1
    else:
        return 1 - pow(2, -10 * sep)

def get_slide_track(distance):
    """
    根据滑动距离生成滑动轨迹
    :param distance: 需要滑动的距离
    :return: 滑动轨迹<type 'list'>: [[x,y,t], ...]
        x: 已滑动的横向距离
        y: 已滑动的纵向距离, 除起点外, 均为0
        t: 滑动过程消耗的时间, 单位: 毫秒
    """

    if not isinstance(distance, int) or distance < 0:
        raise ValueError(f"distance类型必须是大于等于0的整数: distance: {distance}, type: {type(distance)}")
    # 初始化轨迹列表
    slide_track = [
        [random.randint(-50, -10), random.randint(-50, -10), 0],
        [0, 0, 0],
    ]
    # 共记录count次滑块位置信息
    count = 40 + int(distance / 2)
    # 初始化滑动时间
    t = random.randint(50, 100)
    # 记录上一次滑动的距离
    _x = 0
    _y = 0
    for i in range(count):
        # 已滑动的横向距离
        x = round(__ease_out_expo(i / count) * distance)
        # y = round(__ease_out_expo(i / count) * 14)
        # 滑动过程消耗的时间
        t += random.randint(10, 50)
        if x == _x:
            continue
        slide_track.append([x, _y, t])
        _x = x
    slide_track.append(slide_track[-1])
    return slide_track

这个轨迹虽然说有点小瑕疵,但是,能过平台的检测就行,你们在运行的时候会发现它的y值都是0,而网页上实际生成的不是这样的,y值是有波动的。这里的代码,我们只要传入距离的参数就可以了。就是我们上面识别计算出来的距离。在这里,我们还可以拿到passtime,这里的值也特别重要,后面也会说的。

总结

我们今天主要说了关于滑块距离的计算,还有滑块距离的计算,我们下一篇,重点来逆向那个w的值,我在这里澄清之前说前两个w的值可以置空,但是,我这里试了一下,是不可以置空的,我看了大部分教学视频都说可以置空,是不对的,至少,我把前两个w的值补全之后,就不会报错。

geetest_1701956570696({"success": 0, "message": "forbidden"})

即使我们第三个w的值是对的,也是报forbidden,我一开始还以为我w的值扣错了,还怀疑过滑块轨迹有问题,这个前前后后花了我一周的时间,我希望大家少踩坑,我们在扣w的值的时候,有个随机数,前后也要一致,也是个坑。

下节预告:

接下来,我的思路是重点讲w的生成,因为也有不少博主发了,思路都差不多,可能就是函数名发生改变,加密的内容有一些稍微的变化,我会把三个w逆向都会分析过程都会发出来。由于版权问题,我不会把完整的js代码发出来,你跟着我思路扣,是没有问题的。我这里先给大家看看我成功的图片吧。

我还去测试了某平台手机发送验证码的滑块,这个网站只要最后一个w就可以,等大家学完这个官网的逆向,其他js基本上简单修改就可以使用了。


严正声明:本文仅供交流学习,勿用于非法用途


猜你喜欢

转载自blog.csdn.net/BROKEN__Y/article/details/134863809