当前位置: 首页 > article >正文

Python 学习之生成图形验证码

一、 如何生成图形验证码?

新建一个captcha 的python 文件包,在__init__.py 文件中写入生成图形验证码的代码,将字体文件也放入这个文件包中 。

import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import string



class Captcha(object):
    # 生成几位的验证码
    number = 4
    # 验证码图片的宽度和高度
    size = (110, 38)
    # 验证码字体的大小
    fontsize = 25
    # 加入干扰线的条数
    line_number = 2
    # 构建一个验证码源文本
    source = list(string.ascii_letters)
    source.extend(map(lambda x: str(x), range(10)))

    # 用户绘制干扰线
    @classmethod
    def _gene_line(cls, draw, width, height):
        begin = (random.randint(0, width), random.randint(0, height))
        end = (random.randint(0, width), random.randint(0, height))
        draw.line([begin, end], fill=cls._gene_random_color(), width=2)

    # 用于绘制干扰点
    @classmethod
    # cls, draw, point_chance, width, height
    def _gene_points(cls, draw, width, height, rate):
        # chance = min(100, max(0, int(point_chance)))  #大小限制在0-100
        # for w in range(width):
        #     for h in range(height):
        #         tmp = random.randint(0, 100)
        #         if tmp > chance:
        #             draw.point((w, h), fill=cls._gene_random_color())
        # 因为width为图形验证码的宽,height为图形验证码的高,整个图都是由点组成的
        # 点的x坐标范围:[0, 图形的宽度], y的坐标范围:[0, 图形的高度], 这样就能遍历图像的每一个像素点
        # rate 用来控制点生成的概率,大约100个点有rate个点被选中
        # point方法用来画点,参数1:点的坐标, 参数2:点的颜色
        for x in range(width):
            for y in range(height):
                if random.randint(1, 100) <= rate:
                    draw.point((x, y), fill=cls._gene_random_color())

    # 随机生成颜色
    @classmethod
    def _gene_random_color(cls, start=0, end=255):
        random.seed()
        return (random.randint(start, end), random.randint(start, end), random.randint(start, end))

    # 随机选择一个字体
    @classmethod
    def _gene_random_font(cls):
        fonts = [
            "AlimamaShuHeiTi-Bold.ttf",
            "AlimamaDaoLiTi.ttf",
            "AlimamaDongFangDaKai-Regular.ttf",
        ]
        font = random.choice(fonts)
        return f"utils/captcha/{font}"

    #     随机生成一个字符串(包括英文和数字)
    @classmethod
    def gene_text(cls, number):
        return ''.join(random.sample(cls.source, number))

    #     生成验证码
    @classmethod
    def gene_graph_captcha(cls):
        # 验证码图片的宽和高
        width, height = cls.size
        # 创建图片
        image = Image.new('RGBA', (width, height), cls._gene_random_color(0, 100))
        # 验证码字体
        font = ImageFont.truetype(cls._gene_random_font(), cls.fontsize)
        # 创建画笔
        draw = ImageDraw.Draw(image)
        # 生成字符串
        text = cls.gene_text(cls.number)
        # font.getsize(text)获取字体的尺寸
        # pillow 版本10 会报这个错误, AttributeError: 'FreeTypeFont' object has no attribute 'getsize'
        # 降低版本为9.5,但是安装一直报Read timed out,所以直接取消掉
        # font_width, font_height = font.getsize(text)
        # 填充字符串
        draw.text((30, 5), text, font=font,
                  fill=cls._gene_random_color(150, 255))
        # 绘制干扰线
        for x in range(0, cls.line_number):
            cls._gene_line(draw, width, height)
        # 绘制噪点
        cls._gene_points(draw, width, height, 20)
        with open('utils/captcha/captcha.png', 'wb') as fp:
            image.save(fp)
        return text, image


# if __name__ == '__main__':
    # Captcha.gene_graph_captcha()

二、 后端如何将图形验证码传给前端?

from utils.captcha import Captcha
from io import BytesIO
from flask import Blueprint, make_response
bp = Blueprint('common', __name__, url_prefix='/common')
@bp.route('/graph_captcha/')
def graph_captcha():
    # 获取验证码
    text, image = Captcha.gene_graph_captcha()
    # BytesIO 二进制流数据
    out = BytesIO()
    # 将image 指定保存在out 二进制流里面
    image.save(out, 'PNG')
    # 由于添加了图片数据进去,指针会指向文件流最后,所以需要将文件流指针指到0,跟操作文件类似
    out.seek(0)
    resp = make_response(out.read())
    resp.content_type = "image/png"
    cache.set(text.lower(), text.lower())
    return resp

三、 前端如何使用后端传递过来的图形验证码?

<div class="mb-3 input-group">
            <input class="form-control" type="text" name="graph_code" placeholder="图形验证码">
            <span id="graph_captcha_box" class="input-group-text graph_captcha_box">
                <img id="graph_captcha" src="{{ url_for('common.graph_captcha') }}" alt="">
            </span>
</div>
window.onload = function () {
    let graph_captcha_box = document.getElementById('graph_captcha_box')
    let graph_captcha = document.getElementById('graph_captcha')
  

    graph_captcha_box.addEventListener('click', function () {
        let timeStamps = new Date().getTime();
        graph_captcha.src = `/common/graph_captcha/?timeStamps=${timeStamps}`
    })
}


http://www.kler.cn/news/325620.html

相关文章:

  • 谷神后端$vs.proc.invoke.stock.loadMap
  • golang语法基础
  • 【大数据应用开发】2023年全国职业院校技能大赛赛题第01套
  • 基于php的助农生鲜销售系统
  • vmware 操作系统安装
  • 常见框架漏洞复现
  • IT运维挑战与对策:构建高效一体化运维管理体系
  • Chapter 2 - 1. Understanding Congestion in Fibre Channel Fabrics
  • Redis: RDB与AOF的选择和容灾备份以及Redis数据持久化的优化方案
  • X86架构(九)——保护模式的进入
  • Hive数仓操作(三)
  • 使用Vue.extend( ) 模仿 elementui 创建一个类似 message 消息提示框
  • AI大模型之旅-最强开源文生图工具Stable Diffusion WebUI 教程
  • Safari 浏览器中的 <audio> 标签的控件无效 - 解决方法
  • linux信号 | 学习信号三步走 | 全解析信号的产生方式
  • 数据结构双链表和循环链表
  • 高级主题:接口性能测试与压力测试
  • 0基础跟德姆(dom)一起学AI 数据处理和统计分析08-日期类型处理,Matplotlib介绍
  • 事务的四大特性(ACID)
  • 直接用Bash发送HTTP请求 —— 筑梦之路
  • 【代码随想录Day27】贪心算法Part01
  • C#基于SkiaSharp实现印章管理(10)
  • 【Linux的内存管理】
  • zy81_C#中在窗体中实现坐标变换
  • 基于SSM的“银发在线教育云平台”的设计与实现(源码+数据库+文档)
  • Race Karts Pack 全管线 卡丁车赛车模型素材
  • CSS 中的@media print 是干什么用的?
  • Spark_UDF处理缺失值或空值
  • node实现大文件切片上传的方法
  • R整理数据技巧