【1】生成图片验证码
- 依赖于pillow模块
pip install pillow
- 使用pillow模块在导入时使用
import PIL
,而不是pillow
【1.1】Pillow图像生成模块
| from PIL import Image, ImageDraw, ImageFont |
| |
| |
| |
| |
| img_obj = Image.new(mode='',size=(width,height),color='颜色') |
| ''' |
| mode: 图像模式,常见的包括 'L'(灰度图像)、'RGB'(真彩色图像)和 'RGBA'(带透明通道的图像)等。 |
| size: 图像尺寸,以元组 (width, height) 的形式指定,表示图像的宽度和高度。 |
| color: 图像的颜色,通常使用 RGB 或 RGBA 表示颜色,例如 (255, 0, 0) 表示红色,(0, 255, 0, 128) 表示半透明的绿色。 |
| ''' |
| |
| img_obj.open(filename, mode='r') |
| img_obj.save(fp, format=None, **params) |
| img_obj.resize(size, resample=3) |
| img_obj.rotate(angle, resample=0, expand=0, center=None, translate=None, fillcolor=None) |
| img_obj.crop(box=None) |
| img_obj.filter(filter) |
| |
| draw_obj = ImageDraw.Draw(im='') |
| draw_obj = ImageDraw.Draw(im=img_obj) |
| |
| |
| draw_obj.text(xy, text, fill=None, font=None, anchor=None, spacing=0, align="left") |
| draw_obj.draw_obj.line(xy, fill=None, width=0, joint=None) |
| draw_obj.pieslice(xy, start, end, fill=None, outline=None, width=0) |
| draw_obj.polygon(xy, fill=None, outline=None, width=0) |
| |
| font_obj = ImageFont.truetype(font, size, index=0, encoding='') |
| font_obj = ImageFont.load_default() |
| |
| |
| getsize(text): 返回给定文本的大小。 |
| getmask(text, mode='', fill=0, direction=None, features=None): 返回给定文本的掩码。 |
| getmetrics(): 返回字体的度量信息,如字符宽度、高度等。 |
| getname(): 返回字体的名称。 |
| get_variation_names(): 返回变体字体的名称。 |
| get_variation_axes(): 返回变体字体的轴。 |
【1.2】io内存管理器模块
- 使用io内存管理器创建数据流,生成速度快,且不会产生硬盘消耗
| from io import BytesIO, StringIO |
| |
| |
| |
| io_obj = BytesIO() |
| |
| io_obj.read(size:int) |
| io_obj.readline(size:int) |
| io_obj.readlines(hint=-1) |
| io_obj.write(s) |
| io_obj.getvalue() |
| io_obj.seek(offset, whence=0) |
| io_obj.tell() |
| io_obj.truncate(size=None) |
| io_obj.flush() |
【1.3】依赖Pillow模块和BytesIO对象实现生成图片验证码
| from PIL import Image, ImageDraw, ImageFont, ImageFilter |
| import random |
| from io import BytesIO |
| |
| |
| def rgb_number(): |
| |
| return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) |
| |
| |
| |
| def create_verify_code(img_type="RGB", img_size: tuple = (115, 34), img_rgb_number: tuple = None): |
| if not img_rgb_number: |
| |
| img_rgb_number = rgb_number() |
| |
| img_obj = Image.new(mode=img_type, size=img_size, color=img_rgb_number) |
| |
| img_obj.filter(ImageFilter.UnsharpMask(radius=2, percent=150, threshold=3)) |
| |
| img_draw = ImageDraw.Draw(img_obj) |
| |
| img_font = ImageFont.truetype('static/font/汉仪晴空体简.ttf', 30) |
| |
| |
| code = '' |
| |
| for i in range(4): |
| string_list = [ |
| str(random.randint(0, 9)), |
| chr(random.randint(65, 90)), |
| chr(random.randint(97, 122)) |
| ] |
| temp = random.choice(string_list) |
| |
| |
| img_draw.text((i * 25 + 10, 0), temp, fill=rgb_number(), font=img_font) |
| |
| code += temp |
| |
| |
| |
| |
| io_obj = BytesIO() |
| |
| img_obj.save(io_obj, "png") |
| |
| img_data = io_obj.getvalue() |
| |
| |
| return code, img_data |
【1.3.1】使用方法
- 将图片验证码渲染至
img标签的src属性中
- img标签的src属性,有三种方式可以渲染图片
- 通过指定链接渲染图片
http://
- 通过本地路径渲染图片
/static/
- 通过二进制数据渲染图片
【1.3.1.1】后端
| |
| |
| |
| from lib.GenerateVerifyCode import create_verify_code |
| |
| def verify_code(request): |
| captcha, img_data = create_verify_code() |
| |
| request.session['captcha'] = captcha |
| |
| return HttpResponse(img_data) |
| |
| '''设置了session后,其他地方可以通过request.session.get('captcha')获取到验证码数据''' |
【1.3.1.2】路由
- 我们使用通过二进制数据渲染图片验证码
- 可以通过反向解析执行视图函数
| path('verify_code/', views.verify_code, name='verify_code') |
【1.3.1.3】前端
| <img src="{% url 'user:verify_code' %}" |
| onclick="this.src='{% url 'verify_code' %}'+'?t='+ new Date().getTime();"> |
onclick
:是为了在点击时切换图片,当每一次点击时,向后端发送一次请求
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了