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 相关文章推荐
在Python的Tornado框架中实现简单的在线代理的教程
May 02 Python
合并百度影音的离线数据( with python 2.3)
Aug 04 Python
Django Highcharts制作图表
Aug 27 Python
使用Python3 编写简单信用卡管理程序
Dec 21 Python
利用python将图片转换成excel文档格式
Dec 30 Python
python3 requests中使用ip代理池随机生成ip的实例
May 07 Python
Django跨域请求问题的解决方法示例
Jun 16 Python
详解如何用python实现一个简单下载器的服务端和客户端
Oct 28 Python
如何基于python实现画不同品种的樱花树
Jan 03 Python
opencv python 图片读取与显示图片窗口未响应问题的解决
Apr 24 Python
用python按照图像灰度值统计并筛选图片的操作(PIL,shutil,os)
Jun 04 Python
Django Form设置文本框为readonly操作
Jul 03 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 iconv() : Detected an illegal character in input string
2010/12/05 PHP
详解Grunt插件之LiveReload实现页面自动刷新(两种方案)
2015/07/31 PHP
PHP实现的简单操作SQLite数据库类与用法示例
2017/06/19 PHP
用js实现下载远程文件并保存在本地的脚本
2008/05/06 Javascript
使用EXT实现无刷新动态调用股票信息
2008/11/01 Javascript
原生js实现改变随意改变div属性style的名称和值的结果
2013/09/26 Javascript
javascipt匹配单行和多行注释的正则表达式
2013/11/20 Javascript
jquery 页面滚动到底部自动加载插件集合
2014/01/31 Javascript
浅谈Jquery核心函数
2015/06/18 Javascript
详解AngularJS的通信机制
2015/06/18 Javascript
js阻止浏览器默认行为的简单实例
2016/05/15 Javascript
阿里云ecs服务器中安装部署node.js的步骤
2016/10/08 Javascript
基于vue2.0+vuex的日期选择组件功能实现
2017/03/13 Javascript
微信小程序实战之顶部导航栏(选项卡)(1)
2020/06/19 Javascript
js获取一组日期中最近连续的天数
2017/05/25 Javascript
Vue Transition实现类原生组件跳转过渡动画的示例
2017/08/19 Javascript
详解vue-router 初始化时做了什么
2018/06/11 Javascript
js遍历详解(forEach, map, for, for...in, for...of)
2019/08/28 Javascript
js实现简单选项卡制作
2020/08/05 Javascript
Python实现对PPT文件进行截图操作的方法
2015/04/28 Python
Python获取航线信息并且制作成图的讲解
2019/01/03 Python
Python3 使用pillow库生成随机验证码
2019/08/26 Python
如何提高python 中for循环的效率
2020/04/15 Python
Pycharm插件(Grep Console)自定义规则输出颜色日志的方法
2020/05/27 Python
HTML+CSS3 模仿Windows7 桌面效果
2010/06/17 HTML / CSS
深入理解HTML5定时器requestAnimationFrame的使用
2018/12/12 HTML / CSS
全球最大的户外用品零售商之一:The House
2018/06/12 全球购物
大学毕业生工作的自我评价
2013/10/01 职场文书
财务人员担保书
2014/05/13 职场文书
优秀共青团员事迹材料
2014/12/25 职场文书
2015年安全生产月活动总结
2015/03/26 职场文书
《1942》观后感
2015/06/08 职场文书
导游词之澳门玫瑰圣母堂
2019/12/03 职场文书
MySQL8.0.24版本Release Note的一些改进点
2021/04/22 MySQL
pytorch 带batch的tensor类型图像显示操作
2021/05/20 Python
Java线程的6种状态与生命周期
2022/05/11 Java/Android