首先展示一下最后的效果图

appium输入验证码 python python登陆验证码_python


这就是我们一个验证码效果图

安装环境:
这一步主要使用的模块是 pillow,没有安装的话可以使用 pip install pillow 进行安装

PIL:Python Image Library,是 Python 处理图片的标准库,不过 PIL 仅支持到 Python2.7,之后有人在其基础上创建了兼容的版本,名字就叫做 pillow。

1.先来创建验证码图片

#产生验证码图片
from random import randint
from PIL import Image, ImageDraw, ImageFont
def get_random_color():
   # 随机颜色RGB
   return randint(120, 200), randint(120, 200), randint(120, 200)
def get_random_code():
   # 随机字符
   codes = [[chr(i) for i in range(48, 58)], [chr(i) for i in range(65, 91)], [chr(i) for i in range(97, 123)]]
   codes = codes[randint(0, 2)]
   return codes[randint(0, len(codes)-1)]
def generate_captcha(width=140, height=60, length=4):
   # 生成验证码
   img = Image.new("RGB", (width, height), (250, 250, 250))
   draw = ImageDraw.Draw(img)
    #font.ttf 为字体文件
   font = ImageFont.truetype(os.path.dirname(__file__)+ '/font.ttf', size=36) 
   # 验证码文本
   text = ""
   for i in range(length):
     c = get_random_code()
     text += c
     rand_len = randint(-5, 5)
     draw.text((width * 0.2 * (i+1) + rand_len, height * 0.2 + rand_len), c, font=font, fill=get_random_color())
   # 加入干扰线
   for i in range(3):
     x1 = randint(0, width)
     y1 = randint(0, height)
     x2 = randint(0, width)
     y2 = randint(0, height)
     draw.line((x1, y1, x2, y2), fill=get_random_color())
   # 加入干扰点
   for i in range(16):
      draw.point((randint(0, width), randint(0, height)), fill=get_random_color())
      basedir = os.path.abspath(os.path.dirname(__file__))+ '/code/'
      #生成一个MD5加密名字,以防被传到前端被爬取
      md_text = hashlib.md5('{}zanzanzanzanzanzan'.format(text).encode()).hexdigest()
      #保存图片
      img.save(basedir + md_text + ".jpg")
      #text为生成的验证码,md_text为生成的文件名称
   return  text,md_text

2.调用创建图片接口

sched模块实现了一个时间调度程序,该程序可以通过单线程执行来处理按照时间尺度进行调度的时间。
通过调用scheduler.enter(delay,priority,func,args)函数,可以将一个任务添加到任务队列里面,当指定的时间到了,就会执行任务(func函数)

import time, sched
import datetime
#调用验证码图片生成接口
@admin_views.route('/get_captcha')
def get_captcha():
	#调用生辰图片接口返回:验证码,以及文件名
    text,md_text = generate_captcha()
    #拼接生成的验证码图片名
    img= os.path.join('/code/',md_text+'.jpg')
    #这里我把我们刚获得的验证码存在了session里,作为全局,比较安全也比较试用
    session['code'] = text
    #这一步的意思是,我去进程的方式开一个任务不影响后续操作
    t1 = multiprocessing.Process(target=print_some_times)
    t1.start()
    # print_some_times()
    return img

#定时任务,定时来删除创建的图片
s = sched.scheduler(time.time, time.sleep)

def print_time():
	#产生图片的目录
    basedir = os.path.abspath(os.path.dirname(__file__))+ '/code/'
    #os.listdir 以列表形式展示当前文件夹下的图片
    list_ = os.listdir(basedir)
    #遍历当前文件夹下的文件
    for i in list_:
        join_export_path = basedir + i
        # 获取创建时间
        establish_time = time.strftime('%M ',time.localtime(os.path.getctime(join_export_path)))  
        # 获取当前时间
        current_time = time.strftime('%M ',time.localtime(time.time())) 
        # M代表分钟  创建时间-当前时间 不等于0 
        #相当于只存在60秒
        if int(current_time) - int(establish_time) !=0:
           #删除当前文件
            os.remove(join_export_path)
            #把session的值也清空,可以简单代替验证码的时效性
            session['code'] = '验证码过期'

def print_some_times():
    print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    s.enter(60,1,print_time)#任务的间隔时间,任务被调度到相同的时间执行,要执行的任务函数
    s.run()
    print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

3.前端界面

这里我使用的前端框架为layui,当然你可以使用自己喜欢框架
layui官网(感兴趣可以看一看):https://www.layui.com/

<html class="x-admin-sm">
<head><meta charset="UTF-8"></head>
<div class="login layui-anim layui-anim-up">
<body>
        <div class="message">管理员登录</div>
        <div id="darkbannerwrap"></div>

        <form  class="layui-form"  method="post">
            <input type="hidden" id="err" value="{{err}}">
            <input name="user_name" id="user_name" placeholder="用户名" type="text" lay-verify="required" class="layui-input" value="">
            <hr class="hr15">
            <input name="user_passwd"  id="user_passwd" lay-verify="required" placeholder="密码" type="password" class="layui-input" value="">
            <hr class="hr15">
           <table>
               <tr>
                   <td>
                       <input type="text"  name='your_in' id="your_in" title="请输入验证码" placeholder="验证码(不区分大小写)" class="layui-input"/>
                   </td>
                   <td>
                       <a href="javascript:void(0)" onclick="Change()"><img src="" id="captcha"></a><br>
                        <a href="javascript:void(0)" onclick="Change()">看不清楚,换一张</a><br>
                   </td>
               </tr>
           </table>


            <hr class="hr15">
            <input value="登录" lay-submit lay-filter="login" style="width:100%;" type="button" id="button">
            <hr class="hr20" >
        </form>

</div></div></div>
</body>
<script>
	 //验证码
             function Change() {
                     $.ajax({
                       url: '{{ url_for('admin_views.get_captcha') }}',
                       async: true,
                       type: "GET",
                       success: function (data) {
                         document.getElementById("captcha").src = data;
                       }
                     })
                   }
         //监听回车键提交from表单
		$('#your_in').on('keydown', function (event) {
            if (event.keyCode == 13) {
            layui.use('form', function(){
              var form = layui.form;
                  $.ajax({
                      url:'/api/user/login/',   //调用验证接口
                      method:'post',
                      data:{
                    'user_name':$( "input[name='user_name']").val(),
                    'user_passwd':$( "input[name='user_passwd']").val(),
                          'code':$( "input[name='your_in']").val(),
            },


                      //请求的页面响应成功,则进行处理:
                    success: function(res) {
                          var  data = JSON.parse(res);
                    if (data.code ==200) {

                      x = $.cookie('token');

                        layer.msg('登录成功', {
                            icon: 1,
                            time: 2000
                        },
                        function() {
                            if(document.referrer !='/'){
                                location.href = '/index/'
                        }
                        else{
                            location.href = '/index/';}
                            var fun ='go'
                            collect.fu(fun)

                            return false;

                        });

                    } else {

                        data = JSON.parse(res)
                        layer.msg( data.msg);
                        return false;
                    }
                },
                      //请求的页面响应失败,则进行处理:
                      error: function(data) {
                    layer.msg(JSON.stringify(data.field),
                    function() {
                        location.reload();
                    });
                    return false;
                },
                  })

            });dataType="json"

            }
        });

        window.onload = Change();

</script>
</html>

4.后端账号密码 验证

@api_views.route('/api/user/login/', methods=['POST'])
def user_login():
    code = request.form.get('code').upper()
    if session['code'] == '验证码过期':
        return api_result(code=-1, msg='验证码已过期,请从新输入')
    if code != session['code'].upper():
        return api_result(code=-1, msg='验证码错误')
    sql_dic = {
        'user_name': request.form.get("user_name"),
        'user_passwd': str_md5(request.form.get("user_passwd")),
    }
    现在我们已经获取到账号,密码,验证码
    接下来就要到自己的库里去判断该用户名密码是否正确

到这里为止,一个简单的登录验证码主页就做出来了,当然还有很多可以去完善的地方,欢迎各位码农,大佬指出