Note: this script is not original, just a little adjustment based on the original author's code. Original links: https://www.cnblogs.com/whu-zeng/p/4855480.html
Many scripts that generate Chinese verification code on the Internet can not be used, or the python interpreter version is too old, or all kinds of unknown bug. After two hours, we finally found a suitable one. Let's share the following:
# -*- 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()
By calling the generate_code function, we can get the binary stream of the picture verification code and the corresponding Chinese character content.
But!
My script has a problem:
Is the try statement in the following code strange? Because in the process of my script running, I found that some specific Chinese characters will generate bug when they are generated. There is no time to find out the reason, so in order to meet the emergency, the try statement is used (if it fails once in a while, it will be regenerated). When I am free, I will study it again.
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
Note again: this script is not original, just a little adjustment based on the original author's code. Original links: https://www.cnblogs.com/whu-zeng/p/4855480.html