Python每日一练(6)-验证码

1. 随机数字短信验证码

随着手机支付和网络支付的广泛应用,交易安全越来越成为重中之重。大部分网站在用户修改个人密码或支付交易时采用验证码来进行用户验证。请编写一个程序,随机生成1条6位数字验证码,然后让用户输入刚生成的验证码,最后对用户输入的验证码进行验证。如果用户输入非数字,提示必须输入为数字,请重新输入!。如果用户输入位数不是6位,提示输入必须为六位数字,请重新输入!。如果用户输入错误,提示输入错误,请重新输入!。输入正确,则提示输入正确,您可以去修改用户信息了!。运行效果如图所示。
在这里插入图片描述
示例代码如下:

import random

verification_code = "".join(list(map(str, random.sample(range(0, 10), 6))))
print(f"接收到的验证码为: {verification_code}")
while True:
    code_str = input("请输入验证码: ").strip()
    if not code_str.isdigit():
        print("必须输入为数字,请重新输入!")
    elif len(code_str) != 6:
        print("输入必须为六位数字,请重新输入!")
    elif code_str == verification_code:
        print("输入正确,您可以去修改用户信息了!")
        break
    else:
        print("输入错误,请重新输入!")

对代码中的某些语法进行说明,如图所示:
在这里插入图片描述
上述随机生成验证码的代码还可以使用下面这种,如图所示:
在这里插入图片描述

2. 限时输入的数字短信验证码

为了提升网站的安全性,一些电商网站对短信验证进行了输入时间的限制,用户必须在60秒内输入正确的验证码,并确认通过。否则验证码将失效,用户需要重新获取。这样可以防止不法分子利用各种手段破解验证码,导致用户账户密码或资金的损失。请编写一个程序,可以随机获取数字验证码,要求用户在60秒内进行验证。如果超过60秒,提示验证码已过期,请重新获取!。如果用户输入正确,提示验证码验证正确,将退出!。如果用户输入错误,提示验证码不正确,请重新输入!。运行效果如图所示。
在这里插入图片描述
示例代码如下:

from tkinter import *
from tkinter.messagebox import *
import random
import time


def get_verification_code():
    verification_code = ""  # 在之前的案例中我们使用一句话生产验证码 这里改用for循环
    count = 60  # 用来计时
    for i in range(6):
        verification_code += str(random.randint(0, 9))
    show["text"] = verification_code
    show.update()  # 刷新显示

    while count > 1:
        try:
            topic["text"] = "验证码过期还有:" + str(count)
            topic.update()
            time.sleep(1)
            count -= 1
        except:
            break
    else:
        topic['text'] = '验证码失效'
        topic.update()
        showwarning(title="带时间限制的验证码", 
                    message='验证码过期,请重新获取!')  # 弹出框
        show['text'] = '验证码失效'
        show.update()


def confirm_code():
    # get()方法获取变量内容
    if not m_str_var.get().strip().isdigit():
        showwarning(title='带时间限制的验证码',
                    message='必须输入为数字,请重新输入!')
    elif len(m_str_var.get().strip()) != 6:
        showwarning(title='带时间限制的验证码',
                    message='输入必须为六位数字,请重新输入!')
    elif str(show['text']).strip() == m_str_var.get().strip():
        showwarning(title='带时间限制的验证码', message='验证码验证正确,将退出!')
        root.destroy()  # 退出窗口
    else:
        showwarning(title='带时间限制的验证码', message='验证码不正确,请重新输入!')


root = Tk()  # 生成root窗口
root.wm_attributes("-topmost", 1)  # 置顶
root.title("带时间限制的验证码")  # 给生成的窗口设置标题名
screenWidth = root.winfo_screenwidth()  # 屏幕宽度
screenHeight = root.winfo_screenheight()  # 屏幕高度
width = 250  # 窗口宽
height = 120  # 窗口高
x = (screenWidth - width) / 2  # 窗口左上角x轴位置
y = (screenHeight - height) / 2  # 窗口左上角y轴位置
# 指定主框体的大小 并且让主框体在屏幕中间显示
root.geometry("%dx%d+%d+%d" % (width, height, x, y))
root.resizable(width=False, height=False)  # 决定框体大小是否能够调整
# 定义完了之后,还不会在窗口中显示,必须加上pack()才行
# 窗口中各个元素的显示顺序是按执行pack()的顺序
topic = Label(root, text="带时间限制的验证码")
topic.pack()
show = Label(root, text=0)  # 这个Label等会用来显示验证码
show.pack()
m_str_var = StringVar()  # 字符串变量 默认是""
instr = Entry(root, textvariable=m_str_var)
instr.pack()
# 按钮 Button第一个参数: 父对象 text: 功能按钮名称 width=宽(字符宽) height=高(字符高)
# command:单价功能按钮时,执行此函数或者是方法
get_code = Button(root, text="获取验证码", command=get_verification_code,
                  width=15, height=1)
get_code.pack(side="left")
confirm = Button(root, text="确认", command=confirm_code, width=15, height=1)
confirm.pack(side="right")
root.mainloop()  # 进入消息循环(必需组件)

窗体居中图示说明:
在这里插入图片描述

3. 限制输入次数的数字短信验证码

为了防止恶意破解短信验证码,有些网站对验证码输入次数进行了限制,如输入错误不能超过6次,否则将退出并冻结账户。请编写一个程序,可以随机获取数字验证码,输入错误不能超过6次。如果验证码输入错误则提示验证码输入不正确,请重新入!,并提示剩余几次输入机会。如果输错6次则提示输入错误超过6次,账户将冻结并退出!。运行效果如图所示。
在这里插入图片描述
示例代码如下:

from tkinter import *
from tkinter.messagebox import *
import random
import time


def get_verification_code():
    verification_code = ""  # 在之前的案例中我们使用一句话生产验证码 这里改用for循环
    count = 60  # 用来计时
    for i in range(6):
        verification_code += str(random.randint(0, 9))
    show["text"] = verification_code
    show.update()  # 刷新显示

    while count > 1:
        try:
            topic["text"] = "验证码过期还有:" + str(count)
            topic.update()
            time.sleep(1)
            count -= 1
        except:
            break
    else:
        topic['text'] = '验证码失效'
        topic.update()
        showwarning(title="带时间限制的验证码",
                    message='验证码过期,请重新获取!')  # 弹出框
        show['text'] = '验证码失效'
        show.update()


def confirm_code():
    global error_count  # 声明error_count为全局变量
    if str(show['text']).strip() == m_str_var.get().strip():
        showwarning(title='带时间限制的验证码', message='验证码验证正确,将退出!')
        root.destroy()  # 退出窗口
    else:
        if error_count == 6:
            showwarning(title='带时间限制的验证码', message="输入错误超过6次,账户将冻结并退出!")
            root.destroy()
        else:
            msg = '验证码输入不正确,请重新入!还剩余' + str(6 - error_count) + "次机会!"
            showwarning(title='带时间限制的验证码', message=msg)
        error_count += 1


root = Tk()  # 生成root窗口
root.wm_attributes("-topmost", 1)  # 置顶
root.title("带时间限制的验证码")  # 给生成的窗口设置标题名
screenWidth = root.winfo_screenwidth()  # 屏幕宽度
screenHeight = root.winfo_screenheight()  # 屏幕高度
width = 250  # 窗口宽
height = 120  # 窗口高
x = (screenWidth - width) / 2  # 窗口左上角x轴位置
y = (screenHeight - height) / 2  # 窗口左上角y轴位置
error_count = 0  # 统计输入错误的次数
# 指定主框体的大小 并且让主框体在屏幕中间显示
root.geometry("%dx%d+%d+%d" % (width, height, x, y))
root.resizable(width=False, height=False)  # 决定框体大小是否能够调整
# 定义完了之后,还不会在窗口中显示,必须加上pack()才行
# 窗口中各个元素的显示顺序是按执行pack()的顺序
topic = Label(root, text="带时间限制的验证码")
topic.pack()
show = Label(root, text=0)  # 这个Label等会用来显示验证码
show.pack()
m_str_var = StringVar()  # 字符串变量 默认是""
instr = Entry(root, textvariable=m_str_var)
instr.pack()
# 按钮 Button第一个参数: 父对象 text: 功能按钮名称 width=宽(字符宽) height=高(字符高)
# command:单价功能按钮时,执行此函数或者是方法
get_code = Button(root, text="获取验证码", command=get_verification_code,
                  width=15, height=1)
get_code.pack(side="left")
confirm = Button(root, text="确认", command=confirm_code, width=15, height=1)
confirm.pack(side="right")
root.mainloop()  # 进入消息循环(必需组件)

4. 数学计算验证码

在2000年左右的时候,年仅21岁路易斯冯安(Luis von Ahn)巧妙地设计了一种网络验证方式,很好地解决了网络邮箱验证的问题。原理是计算机先产生一个随机的字符串,然后用程序把这个字符串的图像进行随机的扭曲变形,能辨认出变形字符串的就是用户,否则认为是黑客或恶意用户使用软件进行的机器识别。现在验证码被广泛应用于各种网络平台,验证方式也五花八门。编写一个个位数的加减法验证码,让用户计算算式的结果。输入结果正确,通过验证,提示验证成功,正在登录......。输入结果错误,提示验证错误,请重新输入 ,重新输出一组算式。如图所示。
在这里插入图片描述
示例代码如下:

import random

while True:
    num1 = random.randint(0, 9)
    num2 = random.randint(0, 9)
    symbol = random.choice("+-")
    expression = str(num1) + " " + symbol + " " + str(num2)
    print("算式的结果")
    print(expression + " = ?")
    expression_value = eval(expression)
    result = int(input("结果: "))
    if result == expression_value:
        print("验证成功,正在登录......")
        break
    else:
        print("验证错误,请重新输入......")

5. 限制输错次数的数学计算验证码

为了防止不法企业或人员利用软件技术破解验证码,一些网站限制用户输入验证码的次数,如输入错误次数超过8次,将冻结用户输入2个小时。为上面的数字计算验证码添加限制输错次数的功能。用户输入错误超过8次,提示用户验证超过8次,请2小时后再进行登录验证!,并退出程序。运行效果如图所示。
在这里插入图片描述
示例代码如下:

import random
import time
import sys

error_count = 0  # 错误次数
while error_count < 8:
    num1 = random.randint(0, 9)
    num2 = random.randint(0, 9)
    symbol = random.choice("+-")
    expression = str(num1) + " " + symbol + " " + str(num2)
    print("算式的结果")
    print(expression + " = ?")
    expression_value = eval(expression)
    result = int(input("结果: "))
    if result == expression_value:
        print("验证成功,正在登录......")
        break
    else:
        print("验证错误,请重新输入......")
        error_count += 1
else:
    print("验证超过8次,请2小时后再进行登录验证!")
    times = 7200  # 两小时是120分钟 7200秒
    seconds = 0
    while seconds < times:
        # 返回元组类型数据 元组第一个元素为: 商 元组第二个元素为: 余数
        minute, sec = divmod(times - seconds, 60)
        left_time = str(minute) + '分' + str(sec) + '秒'  # 剩余时间
        sys.stdout.write('\r')
        sys.stdout.write('剩余时间:{}'.format(left_time))
        sys.stdout.flush()
        time.sleep(1)
        seconds += 1

6. 动态验证码

随着大数据和人工智能技术的发展,普通验证码很容易被破解。如何提高验证码的破解难度,保护用户账户和资金的安全呢?使用动态验证码技术是一种比较好的方式,动态验证码如图所示。编写一个程序,实现动态验证码,其实动态验证码是一个GIF动画,用户将动画中的验证码输入到验证码输入框,如果验证正确,提示验证通过,将退出系统!,否则提示验证码不正确,请重新输入!。运行效果如下图所示。
在这里插入图片描述
示例代码如下:

from tkinter import *
from tkinter.messagebox import *
import random


def set_gif():
    global code_index
    global gif_path
    global frames
    code_index = random.randint(0, len(gif_list) - 1)
    gif_path = './cap/' + gif_list[code_index] + '.gif'
    frames = [PhotoImage(file=gif_path, format='gif -index %i' % i) for i in range(max_p)]
    print(frames)
    show_pic(0)


def confirm_code():
    global code_index
    if str(code_list[code_index]).lower() == m_str_var.get().strip().lower():
        showwarning(title='动态验证码', message='验证通过,将退出系统!')
        root.destroy()
    else:
        showwarning(title='动态验证码', message='验证码不正确,请重新输入!')
        set_gif()


def close():
    root.destroy()


def show_pic(k):
    global frames
    frame = frames[k]
    k += 1
    Label(root, image=frame, height=20).grid(column=2, row=1)
    root.after(800, show_pic, k % max_p)


if __name__ == '__main__':
    gif_list = ["验证码0", "验证码1", "验证码2", "验证码3", "验证码4", "验证码5", "验证码6", "验证码7",
                "验证码8", "验证码9", "验证码10", "验证码11", "验证码12"]
    code_list = ["36uad", "eun2p", "tgy19", "1tt8i", "1gria", "4gsah", "2q6gy", "2gnf7", "q4q1y",
                 "5qhi6", "1ferh", "wtyi2", "5ttyi"]
    code_index = 0  # 用来记录随机产生的索引
    gif_path = ""  # 用来记录是哪一张gif图片
    max_p = 6
    frames = []
    root = Tk()  # 创建根窗体
    root.title("动态验证码")
    screenWidth = root.winfo_screenwidth()
    screenHeight = root.winfo_screenheight()
    width = 400
    height = 110
    x = (screenWidth - width) / 2
    y = (screenHeight - height) / 2
    # 设置窗体大小 以及让窗体居中
    root.geometry("%dx%d+%d+%d" % (width, height, x, y))
    # 设置窗体不能拖拽改变窗体大小
    root.resizable(width=False, height=False)
    set_gif()

    # 设置图片
    image1 = PhotoImage(file="sport.png")
    # 在Lable()内使用"image=imageobj" 参数设置此图像对象
    # imageobj: 可以由PhotoImage创建
    add_member = Label(root, text="新增会员", image=image1).grid(row=0, column=0)
    # 提示
    tips = Label(root, text="请输入验证码:").grid(row=1, column=0)
    m_str_var = StringVar()  # 字符串变量 默认是""
    input_code = Entry(text="0", textvariable=m_str_var, width=10).grid(row=1, column=1)

    # relief: 建立控件的边框
    another_one = Button(root, text="换一张", relief=FLAT, command=set_gif, width=10)
    another_one.grid(row=1, column=3)

    # 确认按钮
    confirm_button = Button(root, text="确认", command=confirm_code, width=10)
    confirm_button.grid(row=2, column=2)

    # 退出按钮
    quit_button = Button(root, text="退出", command=close, width=10)
    quit_button.grid(row=2, column=3)
    root.mainloop()

7. 图形验证码

大家对12306网站的图形验证码是不是很有印象。下面编写一个仿12306网站的图形验证码程序,每次出现5个图片,按要求选出两个正确的图形。选择正确,提示验证通过,将进入系统,选择错误,提示验证失败,请重新验证,并重新输出新验证码。如果用户没有选择任何图片,单击确定按钮则提示请选择图形验证码再验证!。如果感觉这组验证码选择困难,可以单击换一组按钮,重新换一组验证码进行验证。
在这里插入图片描述
今天的案例笔者总结了一下,主要是对tkinter的一个掌握,如果tkinter熟悉,那么这个案例就完成得比较快,反之则慢。最后一个笔者实在是懒得修改代码了,直接将运行后的效果图放在上面。如果感兴趣的话,可以私聊笔者要gif图片素材以及后续的代码。编写不易,希望大家手留余香,点点赞或者是关注。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章