-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVerification_code_generation.py
More file actions
175 lines (152 loc) · 6.25 KB
/
Copy pathVerification_code_generation.py
File metadata and controls
175 lines (152 loc) · 6.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# -*- coding: utf-8 -*-
# @Time : 19-1-11 上午9:49
# @Author : Felix Wang
import random
from io import BytesIO
# 首先要安装PIL库 pip3 install pillow
from PIL import Image, ImageDraw, ImageFont, ImageFilter
def mkdir(path):
# 引入模块
import os
# 去除首位空格
path = path.strip()
# 去除尾部 \ 符号
path = path.rstrip("\\")
# 判断路径是否存在
# 存在 True
# 不存在 False
isExists = os.path.exists(path)
# 判断结果
if not isExists:
# 如果不存在则创建目录
# 创建目录操作函数
os.makedirs(path)
print(path + ' 创建成功')
return True
else:
# 如果目录存在则不创建,并提示目录已存在
print(path + ' 目录已存在')
return False
class CheckCode:
def __init__(self, font_file, font_size=36, width=240, height=60, char_length=4, start_color_num=0,
end_color_num=255, is_simple=True, is_oncache=False):
"""
初始化
:param font_file: 字体文件
:param font_size: 字体大小,默认36
:param width: 验证码宽度
:param height: 验证码高度
:param char_length: 验证码文字个数
:param start_color_num: 颜色开始的颜色
:param end_color_num: 颜色结束
:param is_simple: 是否是简体中文,默认为True,如果为False则可能包含繁体中文
:param is_oncache: 是否存在缓存中,默认为False,表示以图片方式存储
"""
self.is_oncache = is_oncache
self.is_simple = is_simple
self.font_file = font_file
self.font_size = font_size
self.width = width
self.height = height
self.char_length = char_length
self.start_num = start_color_num
self.end_num = end_color_num
# 定义使用Image类实例化一个长为120px,宽为30px,基于RGB的(255,255,255)颜色的图片
self.image = Image.new('RGB', (self.width, self.height), (255, 255, 255))
# 创建Font对象:
self.font = ImageFont.truetype(self.font_file, self.font_size)
# 创建Draw对象:
self.draw = ImageDraw.Draw(self.image)
# 双下划綫的变量在类中不能直接访问起到保护的作用
self.__code_text = []
def get_random_code(self, time=1):
"""
:param is_simple: 是否包含中文繁体字,默认不包含,True表示不包含
:param time: 返回多少个
:return: 返回一个随机字符列表
"""
is_simple = self.is_simple
codes = []
for i in range(time):
num = chr(random.randint(0x30, 0x39)) # 随机生成数字
lowercase = chr(random.randint(0x61, 0x74)) # 随机生成小写字母
capcase = chr(random.randint(0x41, 0x5a)) # 随机生成大写字母
# Unicode编码的汉字,带繁体字 ,共2万多字
zh = chr(random.randint(0x4e00, 0x9fbf))
# gbk编码的简单汉字,无繁体字
head = random.randint(0xb0, 0xf7)
body = random.randint(0xa1, 0xf9) # 在head区号为55的那一块最后5个汉字是乱码,为了方便缩减下范围
val = f'{head:x}{body:x}'
ch = bytes.fromhex(val).decode('gb2312')
if is_simple:
# code = random.choice([ch, num, lowercase, capcase])
code = random.choice([ch, num, lowercase, capcase])
else:
code = random.choice([zh, num, lowercase, capcase])
codes.append(code)
return codes
# 随机颜色:
def rndColor(self, start, end, randomflag=True):
"""
:param start:
:param end:
:param randomflag: 是否返回随机参数,
:return:
"""
return (random.randint(start, end), random.randint(start, end),
random.randint(start, end))
def rotate(self):
self.image.rotate(random.randint(0, 90), expand=0)
# 随机点
def randPoint(self):
return (random.randint(0, self.width), random.randint(0, self.height))
# 随机线
def randLine(self, num):
draw = ImageDraw.Draw(self.image)
for i in range(0, num):
draw.line([self.randPoint(), self.randPoint()], self.rndColor(0, 255))
del draw
# 获取验证码
def get_codes(self):
return self.__code_text
def draw_pic(self):
# 填充每个像素:
# 单一背景
color = self.rndColor(170, 255) # 可以把背景调浅色
for x in range(self.width):
for y in range(self.height):
self.draw.point((x, y), fill=color)
# 输出文字:
codes = self.get_random_code(time=self.char_length)
self.__code_text = []
for ii in range(self.char_length):
code = self.get_random_code()[0]
self.__code_text.append(code)
self.draw.text([random.randint(int((self.width / 2 - self.font_size / 2) / self.char_length * 2 * ii),
int((self.width / 2 - self.font_size / 2) / self.char_length * 2 * (
ii + 1))), random.randint(0, self.height / 4)],
code, font=self.font, fill=self.rndColor(0, 120)) # 把字体调深色
# self.rotate()
# 画出随机线
self.randLine(10)
# 模糊:
# self.image = self.image.filter(ImageFilter.BLUR)
if self.is_oncache: # 保存在缓存
f = BytesIO()
self.image.save(f, 'jpeg')
return f.getvalue()
else:
# 保存
self.image.save('images/{}.jpg'.format(''.join(self.get_codes())), 'jpeg')
# 创建文件夹,用来存放验证码
mkdir('images')
# 这里的字体采用能识别中文的字体
font_file = '/home/felix/.local/share/fonts/SIMHEI.TTF'
# checkcode = CheckCode(font_file=font_file, is_simple=True, char_length=random.randint(3, 7))
# 生成多张验证码
for i in range(100):
checkcode = CheckCode(font_file=font_file, is_simple=True, char_length=random.randint(3, 7))
checkcode.draw_pic()
# 生成的验证码的内容
codes = checkcode.get_codes()
print(i, codes)