使用python做验证码图片

来源:互联网 发布:自我认知 知乎 编辑:程序博客网 时间:2024/06/05 23:47
在网络应用中,验证码常常作为一个必备的手段,用来避免机器人恶意注册,保证坐在浏览器前的是一个人。

下面是一个实战项目的结果。

  1. #coding: utf-8
  2. import Image,ImageDraw,ImageFont,os,string,random,ImageFilter
  3. def initChars():
  4.     """
  5.     允许的字符集合,初始集合为数字、大小写字母
  6.     usage:  initChars()      
  7.     param:  None
  8.     return: list
  9.             返回允许的字符集和
  10.     for:    picChecker类初始字符集合
  11.     todo:   Nothing
  12.     """
  13.     nums = [str(i) for i in range(10)]
  14.     letterCase = [
  15.                       'a''b''c''d''e''f''g''h''i''j''k'
  16.                       'l''m''n''o''p''q''r''s''t''u''v'
  17.                       'w''x''y''z'
  18.                      ]
  19.     upperCase = [
  20.                      'A''B''C''D''E''F''G''H''I''J''K'
  21.                      'L''M''N''O''P''Q''R''S''T''U''V'
  22.                      'W''X''Y''Z'
  23.                     ]
  24.     return(nums+letterCase+upperCase)
  25. class picChecker(): 
  26.     """
  27.         图片验证代码:
  28.         1)    用户注册需填写图片验证码,以阻止机器人注册
  29.         2)    图片验证码字符数为 4 位(大小写字母与数字,不区分大小写)。
  30.               用户如果没有填写验证码或没有填写正确的验证码,
  31.               页面友好性提示用户填写(同时程序方面也做相应限制)
  32.         
  33.         usage:  pc = picChecker().createChecker()
  34.         param:  很多,如下
  35.                 chars           允许的字符集合,
  36.                                 类型  list
  37.                                 默认值 initChars()
  38.                                 例子  ['1','2','3']
  39.                 length          字符串长度
  40.                                 类型  integer
  41.                                 默认值 4
  42.                 size            图片大小
  43.                                 类型  tutle
  44.                                 默认值 (120,30)
  45.                                 例子  (120,30)
  46.                 fontsize        字体大小
  47.                                 类型  integer
  48.                                 默认值 25
  49.                 begin           字符其实位置,即左上角位置
  50.                                 类型  tutle
  51.                                 默认值 (5,-2)
  52.                 outputType      输出类型
  53.                                 类型  string
  54.                                 默认值 GIF
  55.                                 可选值 GIF JPEG TIFF PNG
  56.                 mode            图片模式
  57.                                 类型  string
  58.                                 可选值 RGB L (还有其他模式,但只推荐这2种)
  59.                                 默认值 RGB
  60.                 backgroundColor 背景色
  61.                 foregroundColor 前景色
  62.                                 当mode=RGB时,backgroundColor,foregroundColor为tutle类型
  63.                                               取值为(integer,integer,integer)
  64.                                               表示RGB颜色值
  65.                                 当mode=L时,backgroundColor,foregroundColor为数字,表示黑白模式
  66.                                             取值为0-255
  67.                                             表示灰度
  68.                 fonttype        字体路径
  69.                                 类型  string
  70.                                 默认值 "simsum.ttc"
  71.                 jamNum          干扰线条数
  72.                                 类型  (int1,int1)
  73.                                 int1    干扰线条数下限,包含
  74.                                 int2    干扰线条数上线,包含
  75.                 pointBorder     散点噪音
  76.                                 构造方法:对每个像素点使用随机函数确定是否在该像素上画散点噪音
  77.                                 类型  (int1,int2)
  78.                                         int1越大  散点越多
  79.                                         int2越大  散点越少
  80.                 
  81.                 
  82.         return: [picCheckerStr,pic]
  83.                 picCheckerStr:  表示返回图片中对应的字符串,可用于session验证以及其他用途
  84.                 pic          :  返回的图片,类型为Image
  85.         for   :
  86.         todo  : Nothing
  87.                 
  88.     """
  89.     
  90.     #默认字体路径
  91.     #DEFAULT_FONT_PATH = os.path.join(os.path.dirname(__file__),'simsun.ttc').replace('//','/')
  92.     
  93.     def __init__(self,chars = initChars(),size = (120,30),fontsize = 25,
  94.                  begin = (5,-2),outputType = 'GIF',mode = 'RGB' ,
  95.                  backgroundColor = (255,255,255), foregroundColor = (0,0,255),
  96.                  fonttype = "simsun.ttc",length = 4,jamNum = (1,2),
  97.                  pointBorder = (40,39)):
  98.         """
  99.         初始化配置
  100.         """         
  101.         
  102.         #验证码配置
  103.         #允许的字符串
  104.         self.chars = chars
  105.         #图片大小
  106.         self.size = size
  107.         #字符起始插入点
  108.         self.begin = begin
  109.         #字符串长度
  110.         self.length = length
  111.         #输出类型
  112.         self.outputType = outputType
  113.         #字符大小
  114.         self.fontsize = fontsize
  115.         #图片模式
  116.         self.mode = mode
  117.         #背景色
  118.         self.backgroundColor = backgroundColor
  119.         #前景色
  120.         self.foregroundColor = foregroundColor
  121.         #干扰线条数
  122.         self.jamNum = jamNum
  123.         #散点噪音界限
  124.         self.pointBorder = pointBorder
  125.         #字体库路径
  126.         self.fonttype = fonttype
  127.         #设置字体,大小默认为18
  128.         self.font = ImageFont.truetype(self.fonttype, self.fontsize)        
  129.     def getPicString(self):
  130.         """
  131.         usage:  getPicString()
  132.         return: string
  133.         for :   生成给定长度的随机字符串
  134.         todo:   Nothing
  135.         """
  136.         #初始化字符串长度
  137.         length = self.length
  138.         #初始化字符集合
  139.         chars = self.chars
  140.         
  141.         #获得字符集合
  142.         selectedChars = random.sample(chars,length)
  143.         charsToStr = string.join(selectedChars,'')
  144.         return(charsToStr)
  145.         
  146.     def createChecker(self):
  147.         """
  148.         usage:  createChecker()
  149.         return: [str,pic]
  150.                 str:对应的字符串
  151.                 pic:对应的图片
  152.         for:
  153.         todo:
  154.         """
  155.         
  156.         #获得验证码字符串
  157.         randStr = self.getPicString() 
  158.         #将字符串加入空格
  159.         randStr1 = string.join([i+" " for i in randStr],"")
  160.         #创建图形
  161.         im = Image.new(self.mode,self.size,self.backgroundColor) 
  162.         #创建画笔
  163.         draw = ImageDraw.Draw(im)       
  164.         #输出随机文本
  165.         draw.text(self.begin, randStr1, font=self.font,fill=self.foregroundColor)
  166.         #im = self.drawText(draw,randStr,im)            
  167.         #干扰线
  168.         self.createJam(draw)
  169.         #散点噪音
  170.         self.createPoints(draw)             
  171.         #图形扭曲       
  172.         para = [1-float(random.randint(1,2))/100,
  173.                 0,
  174.                 0,              
  175.                 0,
  176.                 1-float(random.randint(1,10))/100,
  177.                 float(random.randint(1,2))/500,
  178.                 0.001,
  179.                 float(random.randint(1,2))/500
  180.                 ]
  181.         #print randStr,para
  182.         im = im.transform(im.size, Image.PERSPECTIVE,para)
  183.         #图像滤镜
  184.         im=im.filter(ImageFilter.EDGE_ENHANCE_MORE)
  185.         im.save("checker.jpg",self.outputType) 
  186.         return([randStr,im])
  187.     
  188.     def createJam(self,draw):
  189.         """
  190.         usage:  创建干扰线
  191.         para:   draw    表示画笔
  192.         return: None
  193.         for:
  194.         todo:
  195.         """
  196.         #干扰线条数
  197.         lineNum = random.randint(self.jamNum[0],self.jamNum[1])
  198.         
  199.         for i in range(lineNum):
  200.             begin = (random.randint(0,self.size[0]),random.randint(0,self.size[1]))
  201.             end = (random.randint(0,self.size[0]),random.randint(0,self.size[1]))
  202.             draw.line([begin,end],fill = (0,0,0))
  203.     
  204.     def createPoints(self,draw):
  205.         """
  206.         usage:  创建散点噪音
  207.         para:   draw    表示画笔
  208.         return: None
  209.         for:
  210.         todo:
  211.         """
  212.         #散点噪音
  213.         for x in range(self.size[0]):
  214.             for y in range(self.size[1]):
  215.                 flag = random.randint(0,self.pointBorder[0])
  216.                 if flag > self.pointBorder[1]:
  217.                     draw.point((x,y),fill = (0,0,0))
  218.                 del flag
  219.         
  220. if __name__ == '__main__':
  221.     c=picChecker()
  222.     t=c.createChecker()
  223.     print(t)
  224.     
  225.         
  226.