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读取图片EXIF信息类库介绍和使用实例
Jul 10 Python
python opencv检测目标颜色的实例讲解
Apr 02 Python
python学习基础之循环import及import过程
Apr 22 Python
Python装饰器用法实例总结
May 26 Python
python 以16进制打印输出的方法
Jul 09 Python
PyTorch的深度学习入门之PyTorch安装和配置
Jun 27 Python
对YOLOv3模型调用时候的python接口详解
Aug 26 Python
Django获取应用下的所有models的例子
Aug 30 Python
在pandas中遍历DataFrame行的实现方法
Oct 23 Python
pycharm中导入模块错误时提示Try to run this command from the system terminal
Mar 26 Python
python 统计list中各个元素出现的次数的几种方法
Feb 20 Python
Python预测分词的实现
Jun 18 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实现singleton()单例模式实例
2014/11/06 PHP
PHP中JSON的应用技巧
2015/10/10 PHP
详解json在php中的应用
2018/09/30 PHP
用javascript实现给出的盒子的序列是否可连为一矩型
2007/08/30 Javascript
很多人都是用下面的js刷新站IP和PV
2008/09/05 Javascript
jquery text()要注意啦
2009/10/30 Javascript
jQuery获取css z-index在各种浏览器中的返回值
2010/09/15 Javascript
简单实用jquery版三级联动select示例
2013/07/04 Javascript
jQuery Validate 验证,校验规则写在控件中的具体实例
2014/02/27 Javascript
javascript使用prototype完成单继承
2014/12/24 Javascript
jquery实现动态改变div宽度和高度
2015/05/08 Javascript
JavaScript DOM节点操作方法总结
2016/08/23 Javascript
BootStrap 模态框实现刷新网页并关闭功能
2017/01/04 Javascript
详解ES6之用let声明变量以及let loop机制
2017/07/15 Javascript
微信小程序实现点击按钮移动view标签的位置功能示例【附demo源码下载】
2017/12/06 Javascript
浅谈React前后端同构防止重复渲染
2018/01/05 Javascript
js自定义trim函数实现删除两端空格功能
2018/02/09 Javascript
ES7之Async/await的使用详解
2019/03/28 Javascript
详解小程序退出页面时清除定时器
2019/04/28 Javascript
[01:45]绝对公平!DOTA2队长征召模式详解
2014/04/25 DOTA
python下10个简单实例代码
2017/11/15 Python
Python3.5基础之函数的定义与使用实例详解【参数、作用域、递归、重载等】
2019/04/26 Python
利用anaconda保证64位和32位的python共存
2021/03/09 Python
python如何统计代码运行的时长
2019/07/24 Python
如何设置PyCharm中的Python代码模版(推荐)
2020/11/20 Python
尤妮佳moony海外旗舰店:日本殿堂级纸尿裤品牌
2018/02/23 全球购物
党的群众路线教育实践活动宣传方案
2014/02/23 职场文书
社区维稳工作方案
2014/06/06 职场文书
党的群众路线教育实践活动总结报告
2014/07/03 职场文书
社区清明节活动总结
2014/07/04 职场文书
教师节主持词开场白
2015/05/29 职场文书
婚宴父母致辞
2015/07/27 职场文书
幼儿园家长心得体会
2016/01/21 职场文书
高中信息技术教学反思
2016/02/16 职场文书
诗词赏析-(浣溪沙)
2019/08/13 职场文书
Python&Matlab实现灰狼优化算法的示例代码
2022/03/21 Python