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圖片素材以及後續的代碼。編寫不易,希望大家手留餘香,點點贊或者是關注。

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