吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1788|回复: 28
收起左侧

[Python 原创] 模拟网页滑块验证

  [复制链接]
lookfeiji 发表于 2023-11-16 23:50
本帖最后由 lookfeiji 于 2023-11-17 10:32 编辑

来啦,来啦,反正闲着也是闲着,那就折腾呗!
不是发了生成验证码图片么,有版友问滑块怎么实现呢?
于是我找GPT问了一下,加上自己也有点思路,刚刚好一结合。嗯,效果不错
源码需怕python环境,以及需安装了PIL这个库
楼主的表达能力真心不怎么样,只能大概介绍一下思路了,
基本实现方式是打开一张图片,随机取图片的一个点,以这个点为中心向上下左右各50个像素裁剪出一个100*100的正方形小图片,作为滑块的活动图片,
(其实在这个阶段想的很多,感觉还有蛮大的可操作空间,例如作为滑块的大图那个白色的地方还可以加点干扰点,或者白色背景改为随机颜色)不能给自己留坑,我还没学会javascript逆向呢,所以不写了。

如图

如图

剪裁出来的张这样

剪裁出来的张这样


图片备好其他就简单了,借助与tkinter模块的bind函数监控拖动滑块,让小滑块的x与大滑块裁剪时随机的那个终点重回就好了
(其实这里也想随机的,不一定只能左右移啊,也可以上下移动的,或者斜线移动,就跟抽签一样抽中x就x移动,抽中y就上下移动,不写了,不想动了)
基本就这些了吧,以下是源码
[Python] 纯文本查看 复制代码
import random
import tkinter
import os
from PIL import Image, ImageTk
from tkinter import messagebox


def slider(image):
    """
    从图片上截下一个小滑块,
    并同时保存小滑块与扣掉小滑块的图片
    """
    global img_x, img_y
    # 先从图片上随机定位出一个点,作为滑块的中心点
    img_x = random.randint(image_width//2-60, image_width-60)  # 先从图片右半部分随机获取出一个x点,不要定位到图片外界去
    img_y = random.randint(60, image_height-60)  # 剪裁像素为100*100的小图所以边框位置留60个像素,避免越界切到图外去了
    # 以定位出来的点剪裁出一个大小为100*100的小滑块图片
    x1, y1, x2, y2 = img_x-50, img_y-50, img_x+50, img_y+50  # 左上角和右下角坐标

    # 裁剪小图
    small_image = image.crop((x1, y1, x2, y2))  # 根据坐标剪裁小图片

    # 保存小图
    small_image.save(small_image_path)
    small_image.close()

    # 裁剪大图
    cropped_image = image.copy()
    try:
        cropped_image.paste((255, 255, 255), (x1, y1, x2, y2))  # 将裁剪区域涂白,有些环境这里报错,加个异常处理
    except:
        cropped_image.paste(300, (x1, y1, x2, y2))
    # 保存大图
    cropped_image.save(big_image_path)
    cropped_image.close()


def on_click(event):
    global is_mouse_dragged
    """
    鼠标按下触发事件
    """
    # 处理鼠标左键按下并移动的操作
    is_mouse_dragged = True
    # 获取鼠标单击的坐标
    x = event.x
    #  避免移动图像超出大图边界
    if x < 50:
        x = 60
    elif x > image_width-50:
        x = image_width-60
    # 更新图像位置
    canvas.coords(image_item, x-50, img_y-50)  # 图片像素为100*100的减50将鼠标点居于图片中心


def func(event):
    global is_mouse_dragged
    """
    鼠标松开触发事件,
    鼠标松开检查是否对齐滑块
    """
    # 只有当鼠标按下并拖动过滑块才能完全触发判定
    if not is_mouse_dragged:
        return
    else:
        is_mouse_dragged = False
    if (img_x-5) <= event.x <= (img_x+5):  # 大图x方向与小图滑块对齐容错左右各5个像素
        messagebox.showinfo("信息", "操作成功!")
    else:
        messagebox.showerror("错误", f"不是这个位置\n")


def update_coordinates(event):
    x = event.x
    y = event.y
    label.config(text=f"X 坐标:{x}, Y 坐标:{y}")


if __name__ == '__main__':
    img_x, img_y = 0, 0   # 记录剪裁滑块中心点在原图的位置
    is_mouse_dragged = False  # 检测按下鼠标移动后才会触发松开按键的事件
    image_path = r"C:\Users\Administrator\Desktop\111\image.png"  # 指定一个图片路径
    path_dir = os.path.split(image_path)[0]
    big_image_path = os.path.join(path_dir, 'path_to_cropped_image.png')  # 大图像路径
    small_image_path = os.path.join(path_dir, 'path_to_small_image.png')  # 小图像路径

    root = tkinter.Tk(className='滑块验证模拟')
    image = Image.open(image_path)
    photo = ImageTk.PhotoImage(image)  # 将image转为tkinter可以显示的对象图片

    width = root.winfo_screenwidth()  # 获取屏幕宽度
    height = root.winfo_screenheight()  # 获取屏幕高度
    image_width = image.width  # 获取图片宽
    image_height = image.height  # 获取图片高

    win_width = (width-image_width)//2
    win_height = (height-image_height)//2

    root.geometry(f'{image_width}x{image_height}+{win_width}+{win_height}')  # 以图片大小创建窗口大小,并让窗口居中屏幕
    slider(image)  # 切出大小图

    label = tkinter.Label(root, text="鼠标坐标")
    label.pack()
    # 创建Canvas控件并显示大图
    canvas = tkinter.Canvas(root, width=image_width, height=image_height)
    canvas.pack()
    big_image = tkinter.PhotoImage(file=big_image_path)
    canvas.create_image(0, 0, anchor="nw", image=big_image)

    # 显示小图
    small_image = tkinter.PhotoImage(file=small_image_path)
    image_item = canvas.create_image(10, img_y-50, anchor="nw", image=small_image)  # 500, 100小图坐标的起始位置

    # 绑定鼠标单击事件
    root.bind("<Motion>", update_coordinates)
    canvas.bind("<B1-Motion>", on_click)  # 鼠标按下拖动滑块
    canvas.bind("<ButtonRelease-1>", func)  # 鼠标松开检测是否重合

    root.mainloop()

接着再配置图片,其实只要把代码的79行中的C:\Users\Administrator\Desktop\1111\image.png改为任意png后缀的图片路径都能玩的,其他图片理论上也支持的,自行测试吧!

这个是配置图片,这一张就够了,源码里带剪裁了

这个是配置图片,这一张就够了,源码里带剪裁了

免费评分

参与人数 8吾爱币 +12 热心值 +6 收起 理由
object86 + 1 用心讨论,共获提升!
vichen + 1 + 1 我很赞同!
shiqiangge + 1 我很赞同!
趁火打劫 + 1 我很赞同!
cjcmxc + 1 + 1 我很赞同!
Aithurs + 1 我很赞同!
为之奈何? + 1 + 1 我很赞同!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| lookfeiji 发表于 2023-11-18 13:15
zhangsan2022 发表于 2023-11-17 08:55
验证码识别,楼主,还有那种将图片从斜着滑动到:正着的验证码怎么弄,求思路。 比如:图片是一张倒着的塔 ...

好了,这个比那个要难搞点,因为是小图切割透明化可能没处理好,可能会有一个警告,但是不影响运行
[Python] 纯文本查看 复制代码
import random
import tkinter
import os
import math
from PIL import Image, ImageTk, ImageDraw
from tkinter import messagebox


def crop_circle(image):
    global center_x, center_y
    """
    从图片上截下一个小滑块,
    并同时保存小滑块与扣掉小滑块的图片
    """
    # 定义裁剪区域(圆形)
    center_x = 600  # x圆心的坐标点
    center_y = 150  # y圆心的坐标点
    radius = 50  # 圆半径大小

    x1 = center_x - radius
    x2 = center_x + radius
    y1 = center_y - radius
    y2 = center_y + radius

    # 创建一个透明图像作为遮罩
    mask = Image.new("L", image.size, 0)
    draw = ImageDraw.Draw(mask)
    draw.ellipse((x1, y1, x2, y2), fill=255)

    # 将遮罩应用于裁剪操作
    cropped_small_image = image.copy()
    cropped_small_image.putalpha(mask)
    cropped_small_image = cropped_small_image.crop((x1, y1, x2, y2))

    # 创建一个遮罩的反向版本
    inverted_mask = Image.eval(mask, lambda px: 255 - px)

    # 从大图中去除圆形区域
    cropped_big_image = image.copy()
    cropped_big_image.putalpha(inverted_mask)

    # 保存裁剪后的小图
    cropped_small_image.convert("RGBA").save(small_image_path, format="PNG")

    # 保存裁剪后的大图
    cropped_big_image.convert("RGBA").save(big_image_path, format="PNG")

    # 关闭图像
    image.close()
    cropped_small_image.close()
    cropped_big_image.close()


def on_click(event):
    global angle
    x1, y1 = center_x-50, center_y-50
    x2, y2 = event.x, event.y
    dx = x2 - x1
    dy = y2 - y1
    # 计算鼠标移动点与x基准线的角度,若以Y为基准角度将dy与dx参数互换math.atan2(dx, dy),计算出来的是弧度
    # 再用degrees将弧度转为角度
    angle1 = math.degrees(math.atan2(dy, dx))
    angle = int((angle1 + 360) % 360)  # 将角度值限制在0至359度之间

    rotated_image = small_img.rotate(angle, center=(small_img.width // 2, small_img.height // 2))

    rotated_image_tk = ImageTk.PhotoImage(rotated_image)
    canvas.itemconfig(image_item, image=rotated_image_tk)
    canvas.image = rotated_image_tk  # 更新图像引用


def func(event):
    """
    鼠标松开触发事件,
    鼠标松开检查图片角度是否是0度
    左右各允许3度的误差
    """
    if angle <= 3 or angle >= 357:
        messagebox.showinfo("信息", "操作成功!")
    else:
        messagebox.showerror("错误", f"不是这个位置\n")


def update_coordinates(event):
    x = event.x
    y = event.y
    label.config(text=f"X 坐标:{x}, Y 坐标:{y} , 当前角度: {int(angle)}")


if __name__ == '__main__':
    center_x, center_y = 0, 0  # 记录剪裁滑块中心点在原图的位置
    angle = 0

    image_path = r"C:\Users\Administrator\Desktop\111\image.png"  # 指定一个图片路径
    path_dir = os.path.split(image_path)[0]
    big_image_path = os.path.join(path_dir, 'path_to_cropped_image.png')  # 大图像路径
    small_image_path = os.path.join(path_dir, 'path_to_small_image.png')  # 小图像路径

    root = tkinter.Tk(className='滑块验证模拟')
    image = Image.open(image_path)
    photo = ImageTk.PhotoImage(image)  # 将image转为tkinter可以显示的对象图片

    width = root.winfo_screenwidth()  # 获取屏幕宽度
    height = root.winfo_screenheight()  # 获取屏幕高度
    image_width = image.width  # 获取图片宽
    image_height = image.height  # 获取图片高

    win_width = (width - image_width) // 2
    win_height = (height - image_height) // 2

    root.geometry(f'{image_width}x{image_height}+{win_width}+{win_height}')  # 以图片大小创建窗口大小,并让窗口居中屏幕
    crop_circle(image)  # 切出大小图

    label = tkinter.Label(root, text="鼠标坐标")
    label.pack()
    # 创建Canvas控件并显示大图
    canvas = tkinter.Canvas(root, width=image_width, height=image_height)
    canvas.pack()
    big_image = tkinter.PhotoImage(file=big_image_path)
    canvas.create_image(0, 0, anchor="nw", image=big_image)

    # 显示小图
    random_angle = random.randint(10, 350)  # 随机一个角度,用于避免图片一加载就直接通过了
    small_img = Image.open(small_image_path)
    # 对图片进行随机旋转,center是旋转点坐标
    rotated_image = small_img.rotate(random_angle, center=(small_img.width // 2, small_img.height // 2))
    small_image = ImageTk.PhotoImage(rotated_image)
    image_item = canvas.create_image(center_x-50, center_y-50, anchor="nw", image=small_image)

    # 绑定鼠标单击事件
    root.bind("<Motion>", update_coordinates)
    canvas.bind("<B1-Motion>", on_click)  # 鼠标按下拖动滑块
    canvas.bind("<ButtonRelease-1>", func)  # 鼠标松开检测是否重合

    root.mainloop()

配置图片还是那种大图,将代码94行中的C:\Users\Administrator\Desktop\111\image.png改为你的图片路径就好了
1700284363301.jpg

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
zhangsan2022 + 1 + 1 谢谢@Thanks!

查看全部评分

戰龍在野 发表于 2023-11-17 00:08
ying1024 发表于 2023-11-17 00:14
developers 发表于 2023-11-17 00:52
学到了,谢谢大佬
wushaolaiye 发表于 2023-11-17 07:09
学习一下,之前研究过一段时间没搞明白
FruitBaby 发表于 2023-11-17 07:45
验证码识别,提供了通用的思路
chentt 发表于 2023-11-17 08:12
谢谢分享,反过来也可以用来做验证码识别
yaphoo 发表于 2023-11-17 08:22
高手在论坛
DR2023 发表于 2023-11-17 08:32
学习到了,高手
yu520 发表于 2023-11-17 08:44
刚好在做验证码识别,借鉴一下,感谢分顶
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-4 16:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表