热线电话:13121318867

登录
首页精彩阅读Python使用PIL库实现验证码图片的方法
Python使用PIL库实现验证码图片的方法
2017-08-15
收藏

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

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

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

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

#!/usr/bin/env python
#coding=utf-8
importrandom
fromPILimportImage, 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))
defcreate_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)# 创建画笔
  defget_chars():
    '''生成给定长度的字符串,返回列表格式'''
    returnrandom.sample(chars, length)
  defcreate_lines():
    '''绘制干扰线'''
    line_num=random.randint(*n_line)# 干扰线条数
    foriinrange(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))
  defcreate_points():
    '''绘制干扰点'''
    chance=min(100,max(0,int(point_chance)))# 大小限制在[0, 100]
    forwinxrange(width):
      forhinxrange(height):
        tmp=random.randint(0,100)
        iftmp >100-chance:
          draw.point((w, h), fill=(0,0,0))
  defcreate_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)
  ifdraw_lines:
    create_lines()
  ifdraw_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)# 滤镜,边界加强(阈值更大)
  returnimg, strs
if__name__=="__main__":
  code_img=create_validate_code()
  code_img.save("validate.gif","GIF")

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

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

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

生成的验证码图片效果:

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

try:
  importcStringIO as StringIO
exceptImportError:
  importStringIO
mstream=StringIO.StringIO()
img=create_validate_code()[0]
img.save(mstream,"GIF")
这样,我们需要输出的图片的时候只要使用“mstream.getvalue()”即可。比如在Django里,我们首先定义这样的url:
fromdjango.conf.urls.defaultsimport*
urlpatterns=patterns('example.views',
  url(r'^validate/$','validate', name='validate'),
)
在views中,我们把正确的字符串保存在session中,这样当用户提交表单的时候,就可以和session中的正确字符串进行比较。
fromdjango.shortcutsimportHttpResponse
fromvalidateimportcreate_validate_code
defvalidate(request):
  mstream=StringIO.StringIO()
  validate_code=create_validate_code()
  img=validate_code[0]
  img.save(mstream,"GIF")
  request.session['validate']=validate_code[1]
  returnHttpResponse(mstream.getvalue(),"image/gif")
希望本文所述对大家Python程序设计有所帮助。


数据分析咨询请扫描二维码

最新资讯
更多
客服在线
立即咨询