如何制作验证码

推导步骤1:在img标签的src属性里放上验证码的请求路径

补充1.img的src属性:
    1.图片路径
    2.url
    3.图片的二进制数据
补充2:字体样式
    我们计算机上之所以可以输出各种各样的字体样式,其内部其实对应的是一个个以.ttf结尾的文件

由于img的src属性里可以放图片的二进制数据,因此我们可以在src里放上图片的请求路径,返回的是一个图片的二进制数据

<img src="/get_code/" alt width="350" height="35">

&#x8BE5;&#x89C6;&#x56FE;&#x51FD;&#x6570;&#x8FD4;&#x56DE;&#x7684;&#x662F;&#x56FE;&#x7247;&#x7684;&#x4E8C;&#x8FDB;&#x5236;&#x6570;&#x636E;&#xFF0C;&#x56FE;&#x7247;&#x662F;&#x672C;&#x5730;&#x5DF2;&#x6709;&#x7684;&#x56FE;&#x7247;&#x8DEF;&#x5F84;
def get_code(request):
    with open ('static/img/default.png','rb') as f:
        data = f.read()
    return HttpResponse(data)

字体样式网站

推导步骤2:利用pillow模块动态产生图片

"""
&#x56FE;&#x7247;&#x76F8;&#x5173;&#x7684;&#x6A21;&#x5757;&#xFF1A;
        pip3 install pillow
&#x5BFC;&#x5165;&#xFF1A;from PIL import Image,ImageDraw,ImageFont
Image&#xFF1A;&#x751F;&#x6210;&#x56FE;&#x7247;
ImageDraw&#xFF1A;&#x80FD;&#x591F;&#x5728;&#x56FE;&#x7247;&#x4E0A;&#x4E71;&#x6D82;&#x4E71;&#x753B;
ImageFont&#xFF1A;&#x63A7;&#x5236;&#x5B57;&#x4F53;&#x6837;&#x5F0F;
"""
from PIL import Image,ImageDraw,ImageFont
import random

def get_random():
    return random.randint(0,255),random.randint(0,255),random.randint(0,255),

def get_code(request):
    1.&#x5148;&#x4EA7;&#x751F;&#x4E00;&#x4E2A;&#x56FE;&#x7247;&#xFF0C;new&#x65B9;&#x6CD5;&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x53C2;&#x6570;&#x662F;&#x56FA;&#x5B9A;&#x6A21;&#x5F0F;RGB&#x683C;&#x5F0F;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x662F;&#x56FE;&#x7247;&#x5927;&#x5C0F;(&#x5BBD;&#xFF0C;&#x9AD8;)&#xFF0C;&#x7B2C;&#x4E09;&#x4E2A;&#x662F;&#x56FE;&#x7247;&#x989C;&#x8272;(&#x53EF;&#x4EE5;&#x653E;rgb&#x6A21;&#x5F0F;&#x7684;&#x989C;&#x8272;)
    # image_obj = Image.new('RGB',(350,35),'green') # &#x56FA;&#x5B9A;&#x989C;&#x8272;
    # image_obj = Image.new('RGB',(350,35),(23,43,53)) # &#x53D8;&#x5F62;1
    image_obj = Image.new('RGB', (350, 35), get_random()) # &#x53D8;&#x5F62;2
    2.&#x5C06;&#x4EA7;&#x751F;&#x7684;&#x56FE;&#x7247;&#x5B58;&#x8D77;&#x6765;&#xFF0C;&#x6253;&#x5F00;&#x4E00;&#x4E2A;&#x6587;&#x4EF6;&#xFF0C;&#x8BE5;&#x56FE;&#x7247;&#x6709;&#x4E00;&#x4E2A;save&#x65B9;&#x6CD5;&#x53EF;&#x4EE5;&#x5B58;&#x50A8;&#x56FE;&#x7247;&#xFF0C;&#x7B2C;&#x4E00;&#x4E2A;&#x53C2;&#x6570;&#x662F;&#x6587;&#x4EF6;&#x53E5;&#x67C4;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x662F;&#x5B58;&#x50A8;&#x56FE;&#x7247;&#x683C;&#x5F0F;
    with open('xxx.png','wb') as f:
        image_obj.save(f,'png')

    3.&#x518D;&#x5C06;&#x56FE;&#x7247;&#x4EE5;&#x4E8C;&#x8FDB;&#x5236;&#x5F62;&#x5F0F;&#x8BFB;&#x51FA;&#x6765;&#xFF0C;&#x8FD4;&#x56DE;&#x7ED9;img&#x6807;&#x7B7E;&#x7684;src&#x5C5E;&#x6027;
    with open('xxx.png','rb') as f:
        data = f.read()
    return HttpResponse(data)

上述方法:会进行频繁的文件存储IO操作,效率比较低下,步骤4利用内存管理器模块优化!

推导步骤4:利用内存管理器模块优化

"""
&#x5BFC;&#x5165;&#x5185;&#x5B58;&#x7BA1;&#x7406;&#x5668;&#x6A21;&#x5757;&#xFF1A;from io import BytesIO,StringIO
BytesIO&#xFF1A;&#x529F;&#x80FD;&#x4E34;&#x65F6;&#x5E2E;&#x60A8;&#x5B58;&#x50A8;&#x6570;&#x636E;&#xFF0C;&#x8FD4;&#x56DE;&#x7684;&#x6570;&#x636E;&#x662F;&#x4E8C;&#x8FDB;&#x5236;
StringIO&#xFF1A;&#x529F;&#x80FD;&#x4E34;&#x65F6;&#x5E2E;&#x60A8;&#x5B58;&#x50A8;&#x6570;&#x636E;&#xFF0C;&#x8FD4;&#x56DE;&#x7684;&#x6570;&#x636E;&#x662F;&#x5B57;&#x7B26;&#x4E32;
"""
def get_code(request):

    # 1.&#x540C;&#x6837;&#x5148;&#x751F;&#x6210;&#x4E00;&#x4E2A;&#x56FE;&#x7247;&#x5BF9;&#x8C61;
    image_obj = Image.new('RGB', (350, 35), get_random())
    # 2.&#x8FD9;&#x91CC;&#x518D;&#x751F;&#x6210;&#x4E00;&#x4E2A;&#x5185;&#x5B58;&#x7BA1;&#x7406;&#x5668;&#x5BF9;&#x8C61;&#xFF0C;&#x5C31;&#x53EF;&#x4EE5;&#x770B;&#x6210;&#x662F;f&#x6587;&#x4EF6;&#x53E5;&#x67C4;
    io_obj = BytesIO()
    # 3.&#x5C06;&#x56FE;&#x7247;&#x4FDD;&#x5B58;&#x5230;&#x6587;&#x4EF6;&#x7BA1;&#x7406;&#x5668;&#x5BF9;&#x8C61;&#x91CC;
    image_obj.save(io_obj,'png')
    # 4.&#x628A;&#x56FE;&#x7247;&#x4ECE;&#x6587;&#x4EF6;&#x7BA1;&#x7406;&#x5668;&#x5BF9;&#x8C61;&#x91CC;&#x53D6;&#x51FA;&#x6765;&#xFF0C;&#x7528;getvalue()&#x65B9;&#x6CD5;
    return HttpResponse(io_obj.getvalue())

最终步骤:写图片验证码

def get_code(request):
    # 1.&#x540C;&#x6837;&#x5148;&#x751F;&#x6210;&#x4E00;&#x4E2A;&#x56FE;&#x7247;&#x5BF9;&#x8C61;
    image_obj = Image.new('RGB', (350, 35), get_random())
    # 2.&#x5728;&#x56FE;&#x7247;&#x4E0A;&#x751F;&#x6210;&#x4E00;&#x4E2A;&#x753B;&#x7B14;&#x5BF9;&#x8C61;
    img_draw = ImageDraw.Draw(image_obj)
    # 3.&#x8BBE;&#x7F6E;&#x5B57;&#x4F53;&#x6837;&#x5F0F;&#xFF0C;truetype()&#x7B2C;&#x4E00;&#x4E2A;&#x53C2;&#x6570;&#x662F;&#x5B57;&#x4F53;&#x6837;&#x5F0F;&#x8DEF;&#x5F84;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x662F;&#x5B57;&#x4F53;&#x5927;&#x5C0F;
    img_font = ImageFont.truetype('static/font/222.ttf',30)

    # 4.&#x968F;&#x673A;&#x751F;&#x6210;&#x9A8C;&#x8BC1;&#x7801;&#xFF0C;&#x4E94;&#x4F4D;&#xFF0C;&#x5927;&#x5C0F;&#x5199;&#x5B57;&#x6BCD;&#x3001;&#x6570;&#x5B57;
    code = ''
    for i in range(5):
        random_upper = chr(random.randint(65,90)) # 65-90&#x7684;&#x6570;&#x5B57;&#x4F7F;&#x7528;chr()&#x51FD;&#x6570;&#x5BF9;&#x5E94;&#x8F6C;&#x6210;&#x5927;&#x5199;&#x5B57;&#x6BCD;
        random_lower = chr(random.randint(97,122)) # 97-122&#x7684;&#x6570;&#x5B57;&#x4F7F;&#x7528;chr()&#x51FD;&#x6570;&#x5BF9;&#x5E94;&#x8F6C;&#x6210;&#x5C0F;&#x5199;&#x5B57;&#x6BCD;
        random_int = str(random.randint(0,9))

        # &#x4ECE;&#x4E0A;&#x9762;&#x4E09;&#x79CD;&#x968F;&#x673A;&#x9009;&#x62E9;&#x4E00;&#x79CD;
        tmp = random.choice([random_int,random_lower,random_upper])
        # &#x5C06;&#x4EA7;&#x751F;&#x7684;&#x968F;&#x673A;&#x5B57;&#x7B26;&#x4E32;&#x5199;&#x5230;&#x56FE;&#x7247;&#x4E0A;
"""
        text()&#x65B9;&#x6CD5;&#x7684;&#x7B2C;&#x4E00;&#x4E2A;&#x53C2;&#x6570;&#xFF0C;&#x5B57;&#x7B26;&#x4E32;&#x5728;&#x56FE;&#x7247;&#x4E0A;&#x7684;&#x5750;&#x6807;&#xFF0C;&#x7B2C;&#x4E8C;&#x4E2A;&#x662F;&#x5B57;&#x7B26;&#x4E32;&#xFF0C;
        &#x7B2C;&#x4E09;&#x4E2A;&#x5B57;&#x7B26;&#x4E32;&#x7684;&#x989C;&#x8272;&#xFF0C;&#x7B2C;&#x56DB;&#x4E2A;&#x5B57;&#x4F53;&#x6837;&#x5F0F;&#x548C;&#x5927;&#x5C0F;
"""
        img_draw.text((i*60,0),tmp,get_random(),img_font)
        code += tmp
    print(code)
    # 5.&#x5C06;&#x751F;&#x6210;&#x7684;&#x968F;&#x673A;&#x9A8C;&#x8BC1;&#x7801;&#x4FDD;&#x5B58;&#x8D77;&#x6765;&#xFF0C;&#x56E0;&#x4E3A;&#x5728;&#x767B;&#x5F55;&#x7684;&#x89C6;&#x56FE;&#x51FD;&#x6570;&#x9700;&#x8981;&#x7528;&#x5230;&#xFF0C;&#x8FDB;&#x884C;&#x6BD4;&#x5BF9;
    request.session['code'] = code
    # 6.&#x518D;&#x751F;&#x6210;&#x4E00;&#x4E2A;&#x5185;&#x5B58;&#x7BA1;&#x7406;&#x5668;&#x5BF9;&#x8C61;&#xFF0C;&#x5C31;&#x53EF;&#x4EE5;&#x770B;&#x6210;&#x662F;f&#x6587;&#x4EF6;&#x53E5;&#x67C4;
    io_obj = BytesIO()
    # 7.&#x5C06;&#x56FE;&#x7247;&#x4FDD;&#x5B58;&#x5230;&#x6587;&#x4EF6;&#x7BA1;&#x7406;&#x5668;&#x5BF9;&#x8C61;&#x91CC;
    image_obj.save(io_obj,'png')
    # 8.&#x628A;&#x56FE;&#x7247;&#x4ECE;&#x6587;&#x4EF6;&#x7BA1;&#x7406;&#x5668;&#x5BF9;&#x8C61;&#x91CC;&#x53D6;&#x51FA;&#x6765;&#xFF0C;&#x7528;getvalue()&#x65B9;&#x6CD5;
    return HttpResponse(io_obj.getvalue())

补充

如何让用户一点验证码图片就刷新验证码

<img src="/get_code/" alt width="350" height="35" id="img">

<script>
    $('#img').click(function (){
        let OldUrl = $(this).attr('src')
        $(this).attr('src',OldUrl += '?')
    })
</script>

Original: https://www.cnblogs.com/suncolor/p/16703867.html
Author: 等日落
Title: 如何制作验证码

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/612856/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • linux常用命令(持续更新中…)

    查看所有开机启动服务:systemctl list-unit-files # 按Enter翻页 查看所有开机启动服务:systemctl list-unit-files | gre…

    数据库 2023年6月14日
    080
  • list对象中的数据如何去重呢?

    下文笔者讲述list对象的去重方法分享,list的实现类是我们存储数据的容器, 当里面存储的对象存在重复值时,我们该如何对其进行去重操作呢? 下文笔者将一一道来,首先我们需了解对象…

    数据库 2023年6月11日
    094
  • 关于.net6项目发布到docker(nginx)踩到的一些坑

    开发环境:桌面云系统(无法使用docker desktop),win10系统 后端开发工具:vs2022 数据库:mysql 缓存:redis 队列和事件处理:rabbitmq 前…

    数据库 2023年6月9日
    082
  • 0. 数据库设计规范化

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    数据库 2023年6月16日
    0106
  • day02-MySQL基础知识

    MySQL基本知识 1.数据库 1.1.创建数据库 语法: CREATE DATABASE [IF NOT EXISTS] db_name [create_specificatio…

    数据库 2023年6月11日
    096
  • MySQL主从同步

    1. 主从同步的定义 主从同步使得数据可以从一个数据库服务器复制到其他服务器上,在复制数据时,一个服务器充当主服务器(master),其余的服务器充当从服务器(slave)。因为复…

    数据库 2023年6月14日
    071
  • Hadoop_mapreduce统计文本单词

    Hadoop MapReduce是一个软件框架,基于该框架能够容易地编写应用程序,这些应用程序能够运行在由上千个商用机器组成的大集群上,并以一种可靠的,具有容错能力的方式并行地处理…

    数据库 2023年6月11日
    086
  • 网络爬虫_Scrapy框架入门

    什么是Scrapy? (百度百科) Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛…

    数据库 2023年6月11日
    097
  • spark报错:WARN util.Utils: Service ‘SparkUI’ could not bind on port 4040. Attempting port 4041.4042等错误

    spark报错:warn util.utils::service ‘sparkUI’ can not bind on part 4040.Attemptin…

    数据库 2023年6月14日
    076
  • 1_Layui

    官网:https://www.layui.com/ 在官网首页, 可以很方便的下载Layui Layui是一款经典模块化前端UI框架, 我们只需要定义简单的HTML,CSS,JS即…

    数据库 2023年6月11日
    093
  • Java Script 循环,数组,对象,判断,阶乘,查找-综合运用合集

    输出100个hello world. for (var i = 1; i console.log("hello world");} 创建一个包含1~100的数组…

    数据库 2023年6月11日
    091
  • Oracle 有排序的分页SQL写法

    第一种: 第二种: 第一种比第二种效率会高,这是因为:CBO 优化模式下,Oracle可以将外层的查询条件推到内层查询中,以提高内层查询的执行效率。对于第一个查询语句,第二层的查询…

    数据库 2023年6月16日
    089
  • MySQL8.0 DDL原子性特性

    1. DDL原子性概述 8.0之前并没有统一的数据字典dd,server层和引擎层各有一套元数据,sever层的元数据包括(.frm,.opt,.par,.trg等),用于存储表定…

    数据库 2023年6月9日
    061
  • canal

    canal 简介 canal 主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费。 canal 工作原理: canal 模拟 MySQL slave 的交互协议…

    数据库 2023年5月24日
    097
  • [VSCode] Todo Tree VSCode插件 待办事项树

    Todo Tree 一款待办事项插件 我们写程序的时候,难免会遇到一些情况需要标记或者搁置,在写代码的时候会用一些特殊的注释来表示不同的内容,使我们可以快速的定位我们注释的位置。 …

    数据库 2023年6月9日
    088
  • java四种访问修饰符及各自的权限

    1.public,即共有的,是访问权限限制最宽的修饰符。被public修饰的类、属性、及方法不仅可以跨类访问,而且可以跨包访问。 2. protected,即保护访问权限,是介于p…

    数据库 2023年6月11日
    097
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球