网站备案 链接,公司电商网站建设费用怎么记账,有做兼职的网站吗,深圳找网站建设公司哪家好许多网站在注册时都要求输入验证码#xff0c;这样做为了防止被程序恶意注册和保证网站安全
1. Pillow
PIL(Python Imaging Library)是一个强大的python图像处理库#xff0c;只是支持到python2.7, Pillow虽说是PIL的一个分支#xff0c;但是pillow支持python3.x#xff… 许多网站在注册时都要求输入验证码这样做为了防止被程序恶意注册和保证网站安全
1. Pillow
PIL(Python Imaging Library)是一个强大的python图像处理库只是支持到python2.7, Pillow虽说是PIL的一个分支但是pillow支持python3.x已经发展成比PIL本身更具活力的图像处理库我们使用Pillow来生成验证码安装方式为
pip install Pillow2. 生成一张指定大小随机颜色的图片
2.1 随机颜色
颜色的处理使用(r,g,b)格式r, g, b 的范围是[0, 255] 使用random模块的randint方法生成3个随机数
def random_color():c1 random.randint(0, 255)c2 random.randint(0, 255)c3 random.randint(0, 255)return c1, c2, c32.2 生成一张指定大小的图片
def random_color():c1 random.randint(0, 255)c2 random.randint(0, 255)c3 random.randint(0, 255)return c1, c2, c3def generate_picture(width120, height35):image Image.new(RGB, (width, height), random_color())return imageif __name__ __main__:image generate_picture()image.save(test.png)现在还只是生成了一张颜色随机的图片接下来要在图片上面写上随机数字和字母
3. 在图片上写上随机数字和字母
3.1 生成随机数字和字母
def get_random_str():获取一个随机字符, 数字或小写字母:return:random_num str(random.randint(0, 9))random_low_alpha chr(random.randint(97, 122))random_char random.choice([random_num, random_low_alpha])return random_char使用random模块提供的随机函数生成指定长度的字符串
3.2 在image对象上画数字和字母
def draw_str(count, image, font_size):在图片上写随机字符:param count: 字符数量:param image: 图片对象:param font_size: 字体大小:return:draw ImageDraw.Draw(image)# 获取一个font字体对象参数是ttf的字体文件的目录以及字体的大小font_file os.path.join(Andale Mono.ttf)font ImageFont.truetype(font_file, sizefont_size)temp []for i in range(count):random_char random_str()draw.text((10i*30, -2), random_char, random_color(), fontfont)temp.append(random_char)valid_str .join(temp) # 验证码return valid_str, imageif __name__ __main__:image generate_picture()valid_str, image draw_str(4, image, 35)image.save(test.png)创建一个ImageDraw.Draw对象在image上画随机字符你可以设置字体 我使用了Andale Mono.ttf mac电脑上在/System/Library/Fonts 目录下找到字体其他系统也有各自的字体文件将字体文件复制到与脚本相同的目录下。
4. 制造噪点
为了防止验证码被轻易的破解还应该在图片上制造一些噪点随机画几条线随机画几个点
def noise(image, width120, height35, line_count3, point_count20)::param image: 图片对象:param width: 图片宽度:param height: 图片高度:param line_count: 线条数量:param point_count: 点的数量:return:draw ImageDraw.Draw(image)for i in range(line_count):x1 random.randint(0, width)x2 random.randint(0, width)y1 random.randint(0, height)y2 random.randint(0, height)draw.line((x1, y1, x2, y2), fillrandom_color())# 画点for i in range(point_count):draw.point([random.randint(0, width), random.randint(0, height)], fillrandom_color())x random.randint(0, width)y random.randint(0, height)draw.arc((x, y, x 4, y 4), 0, 90, fillrandom_color())return imageif __name__ __main__:image generate_picture()valid_str, image draw_str(4, image, 35)image noise(image)image.save(test.png)5. 生成base64编码的图片
实践中如果是生成网站注册使用的验证码图片一般来说不会将其保存到图片文件中因为这会生成大量的小图片完全没必要。我们可以将图片的内容保存到BytesIO对象中最终生成base64编码的图片这样向前端传回去的就是字符串格式为
data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAH...data:image/jpeg;base64 这一段是固定写法逗号剩余的部分是图片经过base64编码后的字符串
def valid_code():生成图片验证码,并对图片进行base64编码:return:image generate_picture()valid_str, image draw_str(4, image, 35)image noise(image)f BytesIO()image.save(f, png) # 保存到BytesIO对象中, 格式为pngdata f.getvalue()f.close()encode_data base64.b64encode(data)data str(encode_data, encodingutf-8)img_data data:image/jpeg;base64,{data}.format(datadata)return valid_str, img_dataif __name__ __main__:print(valid_code())6. 全部代码
为了向你阐述生成验证码图片的过程我将整个过程进行拆解因此代码也被拆解的凌乱你可以将这些代码整合,以便在实际应用中使用
import os
import random
import base64
from io import BytesIO
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFontdef random_color():c1 random.randint(0, 255)c2 random.randint(0, 255)c3 random.randint(0, 255)return c1, c2, c3def generate_picture(width120, height35):image Image.new(RGB, (width, height), random_color())return imagedef random_str():获取一个随机字符, 数字或小写字母:return:random_num str(random.randint(0, 9))random_low_alpha chr(random.randint(97, 122))random_char random.choice([random_num, random_low_alpha])return random_chardef draw_str(count, image, font_size):在图片上写随机字符:param count: 字符数量:param image: 图片对象:param font_size: 字体大小:return:draw ImageDraw.Draw(image)# 获取一个font字体对象参数是ttf的字体文件的目录以及字体的大小font_file os.path.join(Andale Mono.ttf)font ImageFont.truetype(font_file, sizefont_size)temp []for i in range(count):random_char random_str()draw.text((10i*30, -2), random_char, random_color(), fontfont)temp.append(random_char)valid_str .join(temp) # 验证码return valid_str, imagedef noise(image, width120, height35, line_count3, point_count20)::param image: 图片对象:param width: 图片宽度:param height: 图片高度:param line_count: 线条数量:param point_count: 点的数量:return:draw ImageDraw.Draw(image)for i in range(line_count):x1 random.randint(0, width)x2 random.randint(0, width)y1 random.randint(0, height)y2 random.randint(0, height)draw.line((x1, y1, x2, y2), fillrandom_color())# 画点for i in range(point_count):draw.point([random.randint(0, width), random.randint(0, height)], fillrandom_color())x random.randint(0, width)y random.randint(0, height)draw.arc((x, y, x 4, y 4), 0, 90, fillrandom_color())return imagedef valid_code():生成图片验证码,并对图片进行base64编码:return:image generate_picture()valid_str, image draw_str(4, image, 35)image noise(image)f BytesIO()image.save(f, png) # 保存到BytesIO对象中, 格式为pngdata f.getvalue()f.close()encode_data base64.b64encode(data)data str(encode_data, encodingutf-8)img_data data:image/jpeg;base64,{data}.format(datadata)return valid_str, img_dataif __name__ __main__:print(valid_code())