Python使用PIL库实现验证码图片的方法


Posted in Python onMarch 11, 2016

本文实例讲述了Python使用PIL库实现验证码图片的方法。分享给大家供大家参考,具体如下:

现在的网页中,为了防止机器人提交表单,图片验证码是很常见的应对手段之一。这里就不详细介绍了,相信大家都遇到过。

现在就给出用Python的PIL库实现验证码图片的代码。代码中有详细注释。

#!/usr/bin/env python
#coding=utf-8
import random
from PIL import Image, ImageDraw, ImageFont, ImageFilter
_letter_cases = "abcdefghjkmnpqrstuvwxy" # 小写字母,去除可能干扰的i,l,o,z
_upper_cases = _letter_cases.upper() # 大写字母
_numbers = ''.join(map(str, range(3, 10))) # 数字
init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
def create_validate_code(size=(120, 30),
             chars=init_chars,
             img_type="GIF",
             mode="RGB",
             bg_color=(255, 255, 255),
             fg_color=(0, 0, 255),
             font_size=18,
             font_type="ae_AlArabiya.ttf",
             length=4,
             draw_lines=True,
             n_line=(1, 2),
             draw_points=True,
             point_chance = 2):
  '''
  @todo: 生成验证码图片
  @param size: 图片的大小,格式(宽,高),默认为(120, 30)
  @param chars: 允许的字符集合,格式字符串
  @param img_type: 图片保存的格式,默认为GIF,可选的为GIF,JPEG,TIFF,PNG
  @param mode: 图片模式,默认为RGB
  @param bg_color: 背景颜色,默认为白色
  @param fg_color: 前景色,验证码字符颜色,默认为蓝色#0000FF
  @param font_size: 验证码字体大小
  @param font_type: 验证码字体,默认为 ae_AlArabiya.ttf
  @param length: 验证码字符个数
  @param draw_lines: 是否划干扰线
  @param n_lines: 干扰线的条数范围,格式元组,默认为(1, 2),只有draw_lines为True时有效
  @param draw_points: 是否画干扰点
  @param point_chance: 干扰点出现的概率,大小范围[0, 100]
  @return: [0]: PIL Image实例
  @return: [1]: 验证码图片中的字符串
  '''
  width, height = size # 宽, 高
  img = Image.new(mode, size, bg_color) # 创建图形
  draw = ImageDraw.Draw(img) # 创建画笔
  def get_chars():
    '''生成给定长度的字符串,返回列表格式'''
    return random.sample(chars, length)
  def create_lines():
    '''绘制干扰线'''
    line_num = random.randint(*n_line) # 干扰线条数
    for i in range(line_num):
      # 起始点
      begin = (random.randint(0, size[0]), random.randint(0, size[1]))
      #结束点
      end = (random.randint(0, size[0]), random.randint(0, size[1]))
      draw.line([begin, end], fill=(0, 0, 0))
  def create_points():
    '''绘制干扰点'''
    chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100]
    for w in xrange(width):
      for h in xrange(height):
        tmp = random.randint(0, 100)
        if tmp > 100 - chance:
          draw.point((w, h), fill=(0, 0, 0))
  def create_strs():
    '''绘制验证码字符'''
    c_chars = get_chars()
    strs = ' %s ' % ' '.join(c_chars) # 每个字符前后以空格隔开
    font = ImageFont.truetype(font_type, font_size)
    font_width, font_height = font.getsize(strs)
    draw.text(((width - font_width) / 3, (height - font_height) / 3),
          strs, font=font, fill=fg_color)
    return ''.join(c_chars)
  if draw_lines:
    create_lines()
  if draw_points:
    create_points()
  strs = create_strs()
  # 图形扭曲参数
  params = [1 - float(random.randint(1, 2)) / 100,
       0,
       0,
       0,
       1 - float(random.randint(1, 10)) / 100,
       float(random.randint(1, 2)) / 500,
       0.001,
       float(random.randint(1, 2)) / 500
       ]
  img = img.transform(size, Image.PERSPECTIVE, params) # 创建扭曲
  img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) # 滤镜,边界加强(阈值更大)
  return img, strs
if __name__ == "__main__":
  code_img = create_validate_code()
  code_img.save("validate.gif", "GIF")

最后结果返回一个元组,第一个返回值是Image类的实例,第二个参数是图片中的字符串(比较是否正确的作用)。

最后结果返回一个元组,第一个返回值是Image类的实例,第二个参数是图片中的字符串(比较是否正确的作用)。

需要提醒的是,如果在生成ImageFont.truetype实例的时候抛出IOError异常,有可能是运行代码的电脑没有包含指定的字体,需要下载安装。

生成的验证码图片效果:

Python使用PIL库实现验证码图片的方法

这时候,细心的同学可能要问,如果每次生成验证码,都要先保存生成的图片,再显示到页面。这么做让人太不能接受了。这个时候,我们需要使用python内置的StringIO模块,它有着类似file对象的行为,但是它操作的是内存文件。于是,我们可以这么写代码:

try:
  import cStringIO as StringIO
except ImportError:
  import StringIO
mstream = StringIO.StringIO()
img = create_validate_code()[0]
img.save(mstream, "GIF")

这样,我们需要输出的图片的时候只要使用“mstream.getvalue()”即可。比如在Django里,我们首先定义这样的url:

from django.conf.urls.defaults import *
urlpatterns = patterns('example.views',
  url(r'^validate/$', 'validate', name='validate'),
)

在views中,我们把正确的字符串保存在session中,这样当用户提交表单的时候,就可以和session中的正确字符串进行比较。

from django.shortcuts import HttpResponse
from validate import create_validate_code
def validate(request):
  mstream = StringIO.StringIO()
  validate_code = create_validate_code()
  img = validate_code[0]
  img.save(mstream, "GIF")
  request.session['validate'] = validate_code[1]
  return HttpResponse(mstream.getvalue(), "image/gif")

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Windows下Python使用Pandas模块操作Excel文件的教程
May 31 Python
在Python程序和Flask框架中使用SQLAlchemy的教程
Jun 06 Python
python绘制铅球的运行轨迹代码分享
Nov 14 Python
Python tornado队列示例-一个并发web爬虫代码分享
Jan 09 Python
如何使用Python的Requests包实现模拟登陆
Apr 27 Python
python命令 -u参数用法解析
Oct 24 Python
python ubplot使用方法解析
Jan 10 Python
Python原始套接字编程实例解析
Jan 29 Python
使用TensorFlow搭建一个全连接神经网络教程
Feb 06 Python
Python print不能立即打印的解决方式
Feb 19 Python
将pycharm配置为matlab或者spyder的用法说明
Jun 08 Python
python使用Windows的wmic命令监控文件运行状况,如有异常发送邮件报警
Jan 30 Python
Python2.x利用commands模块执行Linux shell命令
Mar 11 #Python
Python实现列表转换成字典数据结构的方法
Mar 11 #Python
python中enumerate函数遍历元素用法分析
Mar 11 #Python
python实现class对象转换成json/字典的方法
Mar 11 #Python
Windows下Python的Django框架环境部署及应用编写入门
Mar 10 #Python
深入学习python的yield和generator
Mar 10 #Python
Python中random模块生成随机数详解
Mar 10 #Python
You might like
php中将时间差转换为字符串提示的实现代码
2011/08/08 PHP
一个tab标签切换效果代码
2009/03/27 Javascript
javascript实现的弹出层背景置灰-模拟(easyui dialog)
2013/12/27 Javascript
Jquery中的$.each获取各种返回类型数据的使用方法
2015/05/03 Javascript
JavaScript+html5 canvas制作色彩斑斓的正方形效果
2016/01/27 Javascript
Jquery元素追加和删除的实现方法
2016/05/24 Javascript
关于JS中二维数组的声明方法
2016/09/24 Javascript
Angularjs之ngModel中的值验证绑定方法
2018/09/13 Javascript
Vue.js的模板语法详解
2020/02/16 Javascript
JS数组及对象遍历方法代码汇总
2020/06/16 Javascript
[03:07]2015国际邀请赛选手档案EHOME.rOtK 是什么让他落泪?
2015/07/31 DOTA
[47:36]Optic vs Newbee 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
CentOS 7下安装Python 3.5并与Python2.7兼容并存详解
2017/07/07 Python
Python 比较两个数组的元素的异同方法
2017/08/17 Python
详解python实现交叉验证法与留出法
2019/07/11 Python
Django中的cookie和session
2019/08/27 Python
线程安全及Python中的GIL原理分析
2019/10/29 Python
python bluetooth蓝牙信息获取蓝牙设备类型的方法
2019/11/29 Python
python 多进程队列数据处理详解
2019/12/23 Python
解决TensorFlow模型恢复报错的问题
2020/02/06 Python
Keras 实现加载预训练模型并冻结网络的层
2020/06/15 Python
Python包和模块的分发详细介绍
2020/06/19 Python
详解python的变量缓存机制
2021/01/24 Python
详解HTML5 Canvas绘制不规则图形时的非零环绕原则
2016/03/21 HTML / CSS
canvas裁剪clip()函数的具体使用
2018/03/01 HTML / CSS
金蝶的一道SQL笔试题
2012/12/18 面试题
《锄禾》教学反思
2014/04/08 职场文书
实习护士自荐信
2014/06/21 职场文书
工作证明格式及范本
2014/09/12 职场文书
电视新闻稿
2015/07/17 职场文书
餐馆开业致辞
2015/08/01 职场文书
实验心得体会范文
2016/01/25 职场文书
Prometheus 监控MySQL使用grafana展示
2021/08/30 MySQL
node快速搭建后台的实现步骤
2022/02/18 NodeJs
Pytorch中使用ImageFolder读取数据集时忽略特定文件
2022/03/23 Python
试用1103暨1103、1101同门大比武 [ DAIWEI ]
2022/04/05 无线电