在开发中许多地方要用到验证码,验证码的一般限制用户进行表单提交的时候进行爆破,这篇文章记录Python如何生成验证码。
验证码的生成主要注意到这几点
- 验证码的宽高
- 验证码字体
- 验证码内容
- 干扰线
- 噪点
满足这几点就可以生成一张验证码,下面代码是我之前学习Flask,copy别人的代码,之前都在用这串代码实现验证码功能,这里记录下,方便以后copy。
1 | # -*- coding: UTF-8 -*- |
2 | import random |
3 | import string |
4 | # Image:一个画布 |
5 | # ImageDraw:一个画笔 |
6 | # ImageFont:画笔的字体 |
7 | from PIL import Image, ImageDraw, ImageFont, ImageFilter |
8 | |
9 | |
10 | # pip install pillow |
11 | |
12 | # Captcha验证码 |
13 | |
14 | class Captcha(object): |
15 | # 生成几位数的验证码 |
16 | number = 4 |
17 | # 验证码图片的宽度和高度 |
18 | size = (100, 30) |
19 | # 验证码字体大小 |
20 | fontsize = 25 |
21 | # 加入干扰线的条数 |
22 | line_number = 2 |
23 | |
24 | # 构建一个验证码源文本 |
25 | SOURCE = list() |
26 | for index in range(0, 10): |
27 | SOURCE.append(str(index)) |
28 | |
29 | # 用来绘制干扰线 |
30 |
|
31 | def __gene_line(cls, draw, width, height): |
32 | begin = (random.randint(0, width), random.randint(0, height)) |
33 | end = (random.randint(0, width), random.randint(0, height)) |
34 | draw.line([begin, end], fill=cls.__gene_random_color(), width=2) |
35 | |
36 | # 用来绘制干扰点 |
37 |
|
38 | def __gene_points(cls, draw, point_chance, width, height): |
39 | chance = min(100, max(0, int(point_chance))) # 大小限制在[0, 100] |
40 | for w in range(width): |
41 | for h in range(height): |
42 | tmp = random.randint(0, 100) |
43 | if tmp > 100 - chance: |
44 | draw.point((w, h), fill=cls.__gene_random_color()) |
45 | |
46 | # 生成随机的颜色 |
47 |
|
48 | def __gene_random_color(cls, start=0, end=255): |
49 | random.seed() |
50 | return (random.randint(start, end), random.randint(start, end), random.randint(start, end)) |
51 | |
52 | # 随机选择一个字体 |
53 |
|
54 | def __gene_random_font(cls): |
55 | fonts = [ |
56 | 'verdana.ttf' |
57 | ] |
58 | font = random.choice(fonts) |
59 | return 'utils/captcha/' + font |
60 | |
61 | # 用来随机生成一个字符串(包括英文和数字) |
62 |
|
63 | def gene_text(cls, number): |
64 | # number是生成验证码的位数 |
65 | return ''.join(random.sample(cls.SOURCE, number)) |
66 | |
67 | # 生成验证码 |
68 |
|
69 | def gene_graph_captcha(cls): |
70 | # 验证码图片的宽和高 |
71 | width, height = cls.size |
72 | # 创建图片 |
73 | # R:Red(红色)0-255 |
74 | # G:G(绿色)0-255 |
75 | # B:B(蓝色)0-255 |
76 | # A:Alpha(透明度) |
77 | image = Image.new('RGBA', (width, height), cls.__gene_random_color(0, 100)) |
78 | # 验证码的字体 |
79 | font = ImageFont.truetype(cls.__gene_random_font(), cls.fontsize) |
80 | # 创建画笔 |
81 | draw = ImageDraw.Draw(image) |
82 | # 生成字符串 |
83 | text = cls.gene_text(cls.number) |
84 | # 获取字体的尺寸 |
85 | font_width, font_height = font.getsize(text) |
86 | # 填充字符串 |
87 | draw.text(((width - font_width) / 2, (height - font_height) / 2), text, font=font, |
88 | fill=cls.__gene_random_color(150, 255)) |
89 | # 绘制干扰线 |
90 | for x in range(0, cls.line_number): |
91 | cls.__gene_line(draw, width, height) |
92 | # 绘制噪点 |
93 | cls.__gene_points(draw, 10, width, height) |
94 | # image.filter(ImageFilter.EDGE_ENHANCE_MORE) |
95 | return (text, image) |