无聊之作-类研招网验证码生成

本文采用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也含有一些不常用字,所以生成的汉字验证码不太好

这里没有对字体、字体大小、旋转、加粗这些进行处理,加上去也挺简单的

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值