Django网络应用开发的5项基础核心技术包括模型(Model)的设计,URL 的设计与配置,View(视图)的编写,Template(模板)的设计和Form(表单)的使用。
有些网站的注册和登录会用到图形验证码,但随着爬虫技术的进步,图形验证码从简单的字母和数字,到比较高要求的滑块和点击选择文字。
本次项目会用到 PIL 图像处理标准库来生成图形验证码。
pip install Pillow
from PIL import Image
# 打开一个jpg图像文件,注意路径要改成你自己的:
im = Image.open('/Users/app/data/test.jpg')
# 获得图像尺寸:
w, h = im.size
# 缩放到50%:
im.thumbnail((w//2, h//2))
# 把缩放后的图像用jpeg格式保存:
im.save('/Users/app/data/thumbnail.jpg', 'jpeg')
① 生成图形验证码
import random
import string
import time
import os
from PIL import Image, ImageDraw, ImageFont
Image 是一个画板(context) ImageDraw 是一个画笔 ImageFont 画笔的字体。
需要定义图形验证码中的字体,生成几位数的验证码,图形和字体的大小,图形的背景颜色和字体的颜色。
class Captcha(object):
# 字体的位置
font_path = os.path.join(os.path.dirname(__file__), "Verdana.ttf")
# font_path = 'utils/captcha/verdana.ttf'
# 生成几位数的验证码
number = 4
# 生成验证码图片的宽度和高度
size = (100, 40)
#背景颜色默认为白色 RGB(Red,Green,Blue)
bgcolor = (0, 0, 0)
#随机字体颜色
random.seed(int(time.time()))
fontcolor = (random.randint(200, 255), random.randint(100, 255), random.randint(100, 255))
#验证码字体大小
fontsize = 20
#随机干扰线颜色
linecolor = (random.randint(0, 250), random.randint(0, 255), random.randint(0, 250))
#是否要加入干扰线
draw_line = True
#是否要绘制干扰点
draw_point = True
#加入干扰线的条数
line_number = 3
#用来随机生成一个字符串(包括英文和数字)
SOURCE = list(string.ascii_letters)
for index in range(0, 10):
SOURCE.append(str(index))
定义成类方法,然后是私有的,对象在外面不能直接调用。
@classmethod
def gene_text(cls):
return ''.join(random.sample(cls.SOURCE, cls.number))
绘制干扰线
@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.linecolor)
@classmethod
def __gene_point(cls, draw, point_chance, width, height):
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 > 100 - chance:
draw.point((w, h), fill=(0, 0, 0))
@classmethod
def gene_code(cls):
width, height = cls.size # 获取宽和高
image = Image.new('RGBA', (width, height), cls.bgcolor) # 创建图片 RGB A是透明度
font = ImageFont.truetype(cls.font_path, cls.fontsize)
draw = ImageDraw.Draw(image) # 创建画笔
text = cls.gene_text() # 生成字符串
font_width, font_height = font.getsize(text) # 获取文字的宽和高
# 填充字符串 画布的大小 - 文字的大小 / 2 字符串居中
draw.text(((width - font_width) / 2, (height - font_height) / 2), text, font=font, fill=cls.fontcolor)
# 如果需要干扰线
if cls.draw_line:
# 遍历 line_number ,就是画线的条数
for x in range(0, cls.line_number):
cls.__gene_line(draw, width, height)
# 如果需要绘制噪点
if cls.draw_point:
cls.__gene_point(draw, 10, width, height)
return (text,image)
② 读取图形验证码
在 django.http 模块中定义了 HttpResponse 对象的API。
from django.http import HttpResponse
调用图形验证码生成类
from io import BytesIO
from utils.captcha.hycaptcha import Captcha
def img_captcha(request):
text, image = Captcha.gene_code()
# 字节流 image 不是一个HttpRsponse 可以识别的对象
# 要将image 变成一个数据流才能放到HttpRsponse中
# BytesIO() 相当于一个管道,可以用来储存 字节流
out = BytesIO()
image.save(out, 'png')
# 将文件指针设置到0
out.seek(0)
# content_type 数据类型
response = HttpResponse(content_type='image/png')
# 从文件指针开始读
response.write(out.read())
# 返回文件指针在哪个位置 得到文件大小
response['Content-length'] = out.tell()
# 将图形验证码保留在 session
request.session['img_captcha'] = text
return response
urlpatterns = [
path("img_captcha/", views.img_captcha, name='img_captcha'),
]