过某开源滑动验证码

过某开源滑动验证码

今天早上我有一点空闲时间,想着回顾一下前几天在某查询网站遇到的滑动验证码,以免时间久了忘记了。那个网站可能使用的是较早版本的开源滑块验证码系统tianai-captcha,但我不确定是否正确。
在这里插入图片描述

整体思路:

获取背景大图和模板小图,用ddddocr识别缺口位置,模拟人滑动,从通过了验证的载荷来看,主要是模拟形成这个trackList

在这里插入图片描述

基本步骤:

1、获取背景图与模板小图,这个容易,试着滑动一下,从图中接口可以得到backgroundImagetemplateImage

在这里插入图片描述

将获取的图片base64解码保存到本地,保存图片时要注意“固定尺寸”与“渲染大小”之间的关系。

# 将base64编码的图转换为图片

def decode_base64_to_image(base64_string, output_filename, target_size=None):
    # 分割base64字符串,去掉前缀(如果有的话)
    base64_data = base64_string.split(',')[1] if ',' in base64_string else base64_string

    # 解码base64字符串
    image_data = base64.b64decode(base64_data)

    # 使用BytesIO将字节数据转为图像
    image = Image.open(BytesIO(image_data))

    # 如果指定了尺寸,调整图像大小
    if target_size:
        image = image.resize(target_size, Image.LANCZOS)

    # 保存图像到本地文件
    image.save(output_filename)
    
    
def get_image_id():
    url = "http://xxx.xxx.xxx/x_xxxx/gen"
    params = {
        "type": "SLIDER"
    }
    data = '^^{^}^'.encode('unicode_escape')
    response = session.post(url, headers=headers, cookies=cookies, params=params, data=data, verify=False)

    json_data = json.loads(response.text)
    backgroundImage = json_data['captcha']['backgroundImage'].split(',')[1]
    templateImage = json_data['captcha']['templateImage'].split(',')[1]

    # # 保存图片到本地文件
    decode_base64_to_image(backgroundImage, "backgroundImage.jpg", (300, 180)) #注意这里的尺寸是原图的 1/2
    decode_base64_to_image(templateImage, "templateImage.png", (55, 180))

    return json_data['id']
2、用ddddocr识别缺口位置
# 识别偏移量
def get_slider_offset_ddddocr(target, background):
    det = ddddocr.DdddOcr(det=False, ocr=False, show_ad=False)
    with open(target, 'rb') as f:
        target_bytes = f.read()
    with open(background, 'rb') as f:
        background_bytes = f.read()
    res = det.slide_match(target_bytes, background_bytes)
    return res
3、得到缺口位置后,模拟滑动(此乃核心部分),程序中随机数区间可以自行调整,以便获得更高的通过率。
def generate_trajectory(x):
    trajectory = []
    current_x = 0
    current_y = 0
    current_time = random.randint(824, 3065)
    # start with 'down' event
    trajectory.append({"x": current_x, "y": current_y, "type": "down", "t": current_time})
    # add 'move' events
    while current_x < x:
        current_time += random.randint(10, 30)

        move_x = random.randint(1, int(max(1, (x - current_x) / 20)))  # adjust move speed based on distance left
        move_y = random.randint(-2, 2)  # random minor variance in y
        current_x += move_x
        current_y = move_y
        # ensure current_x does not exceed target x
        if current_x > x:
            current_x = x
        trajectory.append({"x": current_x, "y": current_y, "type": "move", "t": current_time})

    # end with 'up' event
    current_time += random.randint(100, 1000)  # randomly determine time taken to lift finger
    trajectory.append({"x": current_x, "y": current_y, "type": "up", "t": current_time})

    return trajectory
4、组装数据提交,我就按照载荷数据的形式组装的,没有去校验各个参数能否更简单。

在这里插入图片描述

def generate_data(trajectory, id):
    import datetime
    # 当前时间为滑动开始时间
    start_time = datetime.datetime.now()

    # 将轨迹时间转换为合适的时间戳,并取毫秒部分
    updated_trajectory = []
    for event in trajectory:
        # 计算事件时间
        event_time = start_time + datetime.timedelta(milliseconds=event['t'])
        # 获取毫秒部分的最后三位数字,转为三位字符串
        milli_str = ('000' + str(event_time.microsecond // 1000))[-3:]
        updated_event = {
            "x": event['x'],
            "y": event['y'],
            "type": event['type'],
            "t": milli_str  # 只保留时间的最后三位
        }
        updated_trajectory.append(updated_event)

    # 设置滑动结束时间
    end_time = start_time + datetime.timedelta(milliseconds=trajectory[-1]['t'])

    # 将时间格式化
    start_sliding_time = start_time.isoformat() + "Z"
    end_sliding_time = end_time.isoformat() + "Z"

    # 提交的数据对象
    from datetime import datetime

    data = {
        "id": id,
        "data": {
            "bgImageWidth": 300,
            "bgImageHeight": 180,
            "startSlidingTime": datetime.fromisoformat(start_sliding_time.replace('Z', '+00:00')).strftime(
                '%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z',
            "endSlidingTime": datetime.fromisoformat(end_sliding_time.replace('Z', '+00:00')).strftime(
                '%Y-%m-%dT%H:%M:%S.%f')[:-3] + 'Z',
            "trackList": updated_trajectory
        }
    }
    return json.dumps(data, separators=(',', ':'))
5、如果通过校验返回如下状态,可以检测中的某一个Key,如果没有通过,重新获取。
{"code":200,"data":{"id":"get_image_id函数所获取的id"},"msg":"OK","success":true}

整个程序通过率90%吧。在生成轨迹时,当时我滑动了大约近二十组数据,将它提供给gpt-4o,让它进行了分析。 以下轨迹分析的程序,你可以根据它分析的结果,来确定generate_trajectory()中随机数。以下是分析程序。

'''
@File    : 轨迹
@Author  : Bobo
@Blog    : https://blog.csdn.net/chinagaobo
@Note    : This code is for learning and communication purposes only
'''
import json

guiji1 = [] #校验通过后的轨迹列表
guiji2= []
guiji3 = []
guiji4= []
...

def analyze_trajectories(trajectories):
    for i, trajectory in enumerate(trajectories):
        print(f"Analysis of track {i + 1}:")
        for j in range(1, len(trajectory)):
            dx = trajectory[j]['x'] - trajectory[j - 1]['x']
            dy = trajectory[j]['y'] - trajectory[j - 1]['y']
            dt = trajectory[j]['t'] - trajectory[j - 1]['t']
            print(f"Step {j} -> dx: {dx}, dy: {dy}, dt: {dt}")
        print()




# 将四组轨迹放入列表
trajectories = [guiji1, guiji2, guiji3, guiji4]

# 分析轨迹
analyze_trajectories(trajectories)

整篇文章给出了解决此种滑动验证的思路及代码,如果您有好的思路,还请不吝赐教。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值