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 相关文章推荐
精确查找PHP WEBSHELL木马的方法(1)
Apr 12 Python
Python实现的最近最少使用算法
Jul 10 Python
Python使用lxml模块和Requests模块抓取HTML页面的教程
May 16 Python
使用Python的Twisted框架编写非阻塞程序的代码示例
May 25 Python
Python中的os.path路径模块中的操作方法总结
Jul 07 Python
python 接口_从协议到抽象基类详解
Aug 24 Python
pytorch中tensor的合并与截取方法
Jul 26 Python
Python爬虫之正则表达式的使用教程详解
Oct 25 Python
对python中的乘法dot和对应分量相乘multiply详解
Nov 14 Python
Python autoescape标签用法解析
Jan 17 Python
DataFrame.groupby()所见的各种用法详解
Jun 14 Python
python下载的库包存放路径
Jul 27 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+ajax做仿百度搜索下拉自动提示框(有实例)
2012/08/21 PHP
使用php判断浏览器的类型和语言的函数代码
2013/02/28 PHP
功能强大的PHP发邮件类
2016/08/29 PHP
PHP htmlspecialchars()函数用法与实例讲解
2019/03/08 PHP
Javascript 写的简单进度条控件
2008/01/22 Javascript
弹出层之1:JQuery.Boxy (一) 使用介绍
2011/10/06 Javascript
javascript 3d 逐侦产品展示(核心精简)
2014/03/26 Javascript
js使用ajax读博客rss示例
2014/05/06 Javascript
深入分析js的冒泡事件
2014/12/05 Javascript
DIV随滚动条滚动而滚动的实现代码【推荐】
2016/04/12 Javascript
解决Angular.Js与Django标签冲突的方案
2016/12/20 Javascript
基于Cookie常用操作以及属性介绍
2017/09/07 Javascript
利用Console来Debug的10个高级技巧汇总
2018/03/26 Javascript
浅谈super-vuex使用体验
2018/06/25 Javascript
解决layui上传文件提示上传异常,实际文件已经上传成功的问题
2018/08/19 Javascript
详解微信小程序之一键复制到剪切板
2019/04/24 Javascript
JS实现滑动导航效果
2020/01/14 Javascript
Python列表list数组array用法实例解析
2014/10/28 Python
使用Python编写基于DHT协议的BT资源爬虫
2016/03/19 Python
python障碍式期权定价公式
2019/07/19 Python
Pytorch 定义MyDatasets实现多通道分别输入不同数据方式
2020/01/15 Python
Python使用Pyqt5实现简易浏览器(最新版本测试过)
2020/04/27 Python
python 图像判断,清晰度(明暗),彩色与黑白实例
2020/06/04 Python
水芝澳美国官网:H2O Plus
2016/10/15 全球购物
JustFab加拿大:女鞋、靴子、手袋和服装在线
2018/05/18 全球购物
俄罗斯卫浴采暖及维修用品超级市场:Dkrussia
2020/05/12 全球购物
TCP/IP模型的分界线
2012/12/01 面试题
舞蹈教育学专业推荐信
2013/11/27 职场文书
求职简历中的自我评价分享
2013/12/08 职场文书
企业内部培训方案
2014/02/04 职场文书
党的群众路线教育学习材料
2014/05/12 职场文书
环保倡议书500字
2014/05/15 职场文书
2015年大学教师工作总结
2015/05/20 职场文书
医院见习总结
2015/06/24 职场文书
升学宴学生致辞
2015/09/29 职场文书
分析MySQL优化 index merge 后引起的死锁
2022/04/19 MySQL