注:此脚本非原创,只是在原作者代码基础上做了一点点调整。原创链接:https://www.cnblogs.com/whu-zeng/p/4855480.html
网上许多生成中文验证码的脚本都不能用,要么python解释器版本过旧,要么各种不明bug。两个小时终于找到了一个合适的。下面分享一下:
# -*- coding: utf-8 -*-
import codecs
import random
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
import math, string
from django.utils.six import unichr
class RandomChar():
@staticmethod
def Unicode():
val = random.randint(0x4E00, 0x9FBF)
return unichr(val)
@staticmethod
def GB2312():
head = random.randint(0xB0, 0xCF)
body = random.randint(0xA, 0xF)
tail = random.randint(0, 0xF)
val = (head << 8) | (body << 4) | tail
str = "%x" % val
# return str.decode('hex').decode('gb2312')
# return str.encode('gb2312').decode('gb2312')
return codecs.decode(str, 'hex_codec').decode('gb2312')
class ImageChar():
def __init__(self, fontColor=(0, 0, 0),
size=(150, 60),
# fontPath='C:/Windows/Fonts/wqy.ttc',
fontPath='C:/Windows/Fonts/simsun.ttc',
bgColor=(255, 255, 255),
fontSize=25):
self.size = size
self.fontPath = fontPath
self.bgColor = bgColor
self.fontSize = fontSize
self.fontColor = fontColor
self.font = ImageFont.truetype(self.fontPath, self.fontSize)
self.image = Image.new('RGB', size, bgColor)
self.char_list = []
def rotate(self):
self.image.rotate(random.randint(0, 30), expand=0)
def drawText(self, pos, txt, fill):
draw = ImageDraw.Draw(self.image)
# print(pos)
# print(txt)
# print(self.font)
# print(fill)
draw.text(pos, txt, font=self.font, fill=fill)
del draw
def randRGB(self):
return (random.randint(0, 255),
random.randint(0, 255),
random.randint(0, 255))
def randPoint(self):
(width, height) = self.size
return (random.randint(0, width), random.randint(0, height))
def randLine(self, num):
draw = ImageDraw.Draw(self.image)
for i in range(0, num):
draw.line([self.randPoint(), self.randPoint()], self.randRGB())
del draw
def randChinese(self, num):
gap = 5
start = 0
char_list = []
while True:
try:
for i in range(0, num):
char_list.append(RandomChar().GB2312())
x = start + self.fontSize * i + random.randint(0, gap) + gap * i
self.drawText((x, random.randint(-5, 5)), char_list[-1], self.randRGB())
self.rotate()
self.randLine(18)
self.char_list = char_list
break
except:
continue
def output(self):
output_buffer = BytesIO()
self.image.save(output_buffer, format='JPEG')
byte_data = output_buffer.getvalue()
return byte_data
def generate_code():
ic = ImageChar(fontColor=(100, 211, 90))
ic.randChinese(4)
byte_data = ic.output()
chars = ''.join(ic.char_list)
return (byte_data, chars)
if __name__ == '__main__':
generate_code()
调用generate_code函数即可获得图片验证码的二进制流和对应的汉字内容。
但是!
我的脚本有个问题:
下面这段代码的try语句很奇怪吧?因为在我运行脚本的过程中发现,某些特定范围的汉字生成时会出bug。也没时间去找原因,因此为了应急,才用了try语句(偶尔失败一次,那就重新生成呗)。日后闲下来了,我会再来研究研究的。
def randChinese(self, num):
gap = 5
start = 0
char_list = []
while True:
try:
for i in range(0, num):
char_list.append(RandomChar().GB2312())
x = start + self.fontSize * i + random.randint(0, gap) + gap * i
self.drawText((x, random.randint(-5, 5)), char_list[-1], self.randRGB())
self.rotate()
self.randLine(18)
self.char_list = char_list
break
except:
continue
再次注:此脚本非原创,只是在原作者代码基础上做了一点点调整。原创链接:https://www.cnblogs.com/whu-zeng/p/4855480.html