本文采用python进行类研招网验证码生成
研招网的验证码分为三种
1、字母数字类识别
2、汉字类识别
3、算数表达式计算识别
背景图片
验证码的背景就是一个100*200的白色背景,然后随机加黑点,然后再随机加一条曲直线
def create_back_ground(height=100,width=200,random_piont_num=1000):
# create back ground image
image = Image.new('RGB', (width, height), (255, 255, 255))
draw = ImageDraw.Draw(image)
# add random point to back ground
for i in range(random_piont_num):
x=random.randint(0,width)
y=random.randint(0,height)
draw.point((x, y), fill=(0,0,0))
# add line to back ground
draw.line(((random.randint(0, width),random.randint(0,height)),(random.randint(0, width),random.randint(0,height))),fill=(0,0,0),width=random.randint(3,7))
return image
1、字母数字类识别
def get_char_image(image,x_gap=15,y_gap=8):
# create en_char image
draw = ImageDraw.Draw(image)
# get random en char
char_list=get_rdm_char()
# get start point
x,y=get_rdm_start_point(image)
# select font and size
font=ImageFont.truetype('C:\\Windows\\Fonts\\Arial.ttf', 36)
# draw en_char to image
for index,char in enumerate(char_list):
x=x+random.randint(x_gap,x_gap+10)
draw.text((x,y+random.randint(0,y_gap)),char,fill=(0,0,0),font=font)
return image
def get_rdm_char(num=4):
char_list=[]
for i in range(0,random.randint(num-1,num+1)):
ran=random.randint(0,2)
if ran==0:
char_list.append(chr(random.randint(65,90)))
elif ran==1:
char_list.append(chr(random.randint(97, 122)))
else:
char_list.append(chr(random.randint(48,57)))
return char_list
2、汉字类识别
def get_cn_char_image(image,x_gap=30,y_gap=8):
# get chinese char image
draw = ImageDraw.Draw(image)
char_list = get_rdm_cn_char()
x, y = get_rdm_start_point(image)
font = ImageFont.truetype('C:\\Windows\\Fonts\\simsun.ttc', 36)
for index, char in enumerate(char_list):
x = x + random.randint(x_gap, x_gap + 10)
draw.text((x, y + random.randint(0, y_gap)),char,fill=(0, 0, 0), font=font)
return image
def get_rdm_cn_char(num=3):
char_list = []
for i in range(0, random.randint(num - 1, num + 1)):
char_list.append(RandomChinese().GBK2312())
print(char_list)
return char_list
class RandomChinese():
# https://blog.csdn.net/ak739105231/article/details/83959865
# use unicode generate random chinese word
@staticmethod
def Unicode():
val = random.randint(0x4e00, 0x9fbf)
return chr(val)
# use GBK2312 generate random chinese word
@staticmethod
def GBK2312():
head = random.randint(0xb0, 0xf7)
body = random.randint(0xa1, 0xfe)
val = f'{head:x}{body:x}'
str = bytes.fromhex(val).decode('gb2312')
return str
3、算数表达式计算识别
def get_num_image(image,x_gap=12,y_gap=8):
# get num expression image
draw = ImageDraw.Draw(image)
char_list=get_rdm_num()
x, y = get_rdm_start_point(image)
font = ImageFont.truetype('C:\\Windows\\Fonts\\Arial.ttf', 36)
for index,char in enumerate(char_list):
x=x+random.randint(x_gap,x_gap+10)
draw.text((x,y+random.randint(0,y_gap)),char,fill=(0,0,0),font=font)
print('res:'+str(ExpressionSolve.solve_expression(char_list)))
return image
def get_rdm_num(num=4):
op_list=['+','-','*']
char_list=[]
for i in range(0,random.randint(num-1,num+1)):
char_list.append(chr(random.randint(48,57)))
char_list.append(op_list[random.randint(0,2)])
char_list.pop()
return char_list
然后这个算式表达涉及到一个进行计算的代码
def jia(x ,y):
return x+ y
def jian(x, y):
return x - y
def cheng(x, y):
return x * y
def chu(x, y):
return x / y
def get_priority_x_y(op_x,op_y):
# x_priority>y_priority return True
if op_x=='+' or op_x=='-':
if op_y=='*' or op_y=='/':
return False
elif op_y=='+' or op_y=='-':
return True
elif op_x=='*' or op_x=='/':
return True
else:
return None
def solve_expression(expression):
print(expression)
num_stack=[]
op_stack=[]
operator = {'+': jia, '-': jian, '*': cheng, '/': chu}
index=0
while(index<len(expression)):
#for char in expression:
char=expression[index]
'''
print('--------')
print(num_stack)
print(op_stack)
print(char)
print('--------')
'''
if char>='0' and char<='9':
num_stack.append(int(char))
elif char=='(':
op_stack.append(char)
elif char==')':
b=num_stack.pop()
a=num_stack.pop()
op=op_stack.pop()
res=operator.get(op)(a,b)
num_stack.pop()
num_stack.append(res)
continue
else:
if len(op_stack)==0:
op_stack.append(char)
else:
last_op=op_stack[-1]
if get_priority_x_y(last_op,char):
last_op=op_stack.pop()
b = num_stack.pop()
a = num_stack.pop()
res = operator.get(last_op)(a, b)
num_stack.append(res)
continue
else:
op_stack.append(char)
index=index+1
while(len(op_stack)!=0):
b = num_stack.pop()
a = num_stack.pop()
op = op_stack.pop()
res = operator.get(op)(a, b)
num_stack.append(res)
return num_stack.pop()
最后的结果如下:
由于GBK2313也含有一些不常用字,所以生成的汉字验证码不太好
这里没有对字体、字体大小、旋转、加粗这些进行处理,加上去也挺简单的