【Python】玩转二维码:生成、伪造和识别

前言及视频

界面:
在这里插入图片描述

二维码作为信息技术的一种,它的普及在给人们生活带来便利的同时,也给不法分子带来了可乘之机。
视频:

酷炫二维码

一、二维码的生成

1.1 导包和相关说明


'''
QRCode参数详细说明:
    version: 一个整数,范围为1到40,表示二维码的大小(最小值是1,是个12×12的矩阵),如果想让程序自动生成,将值设置为 None 并使用 fit=True 参数即可。
    error_correction: 二维码的纠错范围,可以选择4个常量:
        ··1. ERROR_CORRECT_L 7%以下的错误会被纠正
        ··2. ERROR_CORRECT_M (default) 15%以下的错误会被纠正
        ··3. ERROR_CORRECT_Q 25 %以下的错误会被纠正
        ··4. ERROR_CORRECT_H. 30%以下的错误会被纠正
    boxsize: 每个点(方块)中的像素个数
    border: 二维码距图像外围边框距离,默认为4,而且相关规定最小为4
正常生成二维码的步骤:
    创建QRCode对象
    add_data()添加数据
    make_image()创建二维码(返回im类型的图片对象)
    自动打开图片,im.show()

打包方法:
(env_study) E:\python_study\env_study\酷炫二维码>pyinstaller -F -w -i logo.ico 酷炫二维码.py
'''

import os
import sys
import random
import time
import qrcode
from PIL import Image, ImageTk, ImageDraw, ImageFont
from tkinter import ttk
from ttkthemes import ThemedTk
import tkinter as tk
from tkinter import filedialog
from pyzbar import pyzbar

1.2 设置当前目录

# 获取当前文件所在目录的完美版
def get_current_path():
    paths = sys.path
    current_file = os.path.basename(__file__)
    for path in paths:
        try:
            if current_file in os.listdir(path):
                current_path = path
                break
        except (FileExistsError,FileNotFoundError) as e:
            print(e)
    return(current_path)
current_path = get_current_path()
# 改变当前目录为当前文件所在目录的两种方式
os.chdir(current_path)  # 方式一:调用上面的完美函数,可处理所有特殊情况
# os.chdir(sys.path[0]) # 方式二:调用系统函数,简单精炼

1.3 设置保存目录

在这里插入图片描述

# 设置保存目录
def save_path():
    s_path = filedialog.askdirectory()
    path_str.set(s_path)

1.4 设置图标文件

在这里插入图片描述

# 设置图标文件
def get_logo():
    s_filename = filedialog.askopenfilename()
    logo_str.set(s_filename)

1.5 清空输入项

在这里插入图片描述


# 清空输入项
def clear():
    qr_str.set('')
    logo_str.set('')
    name_str.set('')

1.6 初始化二维码

在这里插入图片描述

# 初始化二维码
def qr_init_info():
    # 初始化二维码链接,这是为了快速测试程序
    qr_list = [
        {'百度官网': ['https://www.baidu.com', 'ico/baidu_logo.png']},
        {'hao123': ['https://www.hao123.com', 'ico/hao123_logo.png']},
        {'网易163': ['https://www.163.com', 'ico/网易_logo.png']},
        {'搜狐': ['https://www.sohu.com', 'ico/搜狐_logo.png']},
        {'腾讯': ['https://www.qq.com', 'ico/腾讯_logo.png']},
        {'阿里': ['https://www.1688.com', 'ico/阿里_logo.png']},
        {'淘宝': ['https://www.taobao.com', 'ico/淘宝_logo.png']},
    ]
    # 二维码保存目录
    save_dir = et_path.get()
    if not save_dir:
        save_dir = os.getcwd()
    # 二维码保存文件名
    save_name = et_name.get()
    save_name += time.strftime(r'%Y-%m-%d %H_%M_%S', time.localtime(time.time())) + '.png'
    # 二维码链接/文字
    words = et_qr.get()
    qr_name = et_name.get()
    qr_logo = et_logo.get()
    if not words:
        rd_spl = random.sample(qr_list,1)[0]
        qr_name = list(rd_spl.keys())[0]
        words = list(rd_spl.values())[0][0]
        qr_logo = list(rd_spl.values())[0][1]
    # 二维码Logo 
    if not qr_logo:
        qr_logo = 'ico/logo.ico'
    # 设置二维码链接和名称
    qr_str.set(words)
    name_str.set(qr_name)
    logo_str.set(qr_logo)
    return(words, qr_logo, qr_name, save_name, save_dir)

1.7 生成二维码图片主程序

# 生成二维码图片主程序
def generate_qr():
    # 调用函数初始化二维码信息
    words, qr_logo, qr_name, save_name, save_dir = qr_init_info()

    # 实例化qrcode对象
    qr = qrcode.QRCode(version=1, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=10, border=4)
    # 传入数据
    qr.add_data(words)
    # 制作二维码
    qr.make(fit=True)
    # 生成图片,如果不传参数会生成黑白二维码
    qr_image = qr.make_image(fill_color='#000', back_color='#FFF')
    
    # 调用函数添加logo
    qr_image = add_logo(qr_logo, qr_image)

    # 调用函数仿造微信或支付宝
    dict_copy = {
        'wechat':['ico/wechat780x1170.png', (145, 252), 790],
        'alipay':['ico/alipay780x1170.png', (145, 400), 926],
        }
    for item in list(dict_copy.keys()):
        if var_copy.get() == item:
            copy_png, copy_qr_loc, copy_name_locy = dict_copy[item]
            qr_image = copy_wechat_alipay(qr_image, qr_name, copy_png, copy_qr_loc, copy_name_locy)

    # 保存二维码图片
    qr_image.save(r'result/' + save_name)

    # 显示二维码
    img_file_path = save_dir + '/result/' + save_name
    qr_show(img_file_path)

1.8 显示二维码

在这里插入图片描述

# 显示二维码
def qr_show(img_file_path):
    img_open = Image.open(img_file_path)
    global img_png                                  # 声明全局变量,否则函数执行完,变量被回收,图片框就空了
    img_png = ImageTk.PhotoImage(img_open)
    lb_image.config(image=img_png)

1.9 添加中心logo图标

在这里插入图片描述


# 添加中心logo图标
def add_logo(qr_logo, qr_image):
    # 添加logo,打开logo照片
    icon = Image.open(qr_logo)
    icon_w, icon_h = icon.size
    # 生成一个比logo稍大点的白色背景图片
    wh_image_icon = Image.new('RGB', (int(icon_w*1.2), int(icon_h*1.2)), (255,255,255))
    # 把原来的logo图片居中贴到白背景上
    wh_image_icon.paste(icon, (int((int(icon_w*1.2)-icon_w)/2), int((int(icon_h*1.2)-icon_h)/2)), mask=None)
    # 获取新的带白边的logo的宽度和高度
    icon_w, icon_h = wh_image_icon.size
    # 获取二维码图片的宽高
    img_w, img_h = qr_image.size
    # 参数设置logo的大小,logo占二维码1/factor
    factor = 5
    size_w = int(img_w / factor)
    size_h = int(img_h / factor)
    if icon_w > size_w:
        icon_w = size_w
    if icon_h > size_h:
        icon_h = size_h
    # 根据二维码图片的尺寸重新设置logo的尺寸
    wh_image_icon = wh_image_icon.resize((icon_w, icon_h), Image.ANTIALIAS)
    # 得到画图的x,y坐标,居中显示
    w = int((img_w - icon_w) / 2)
    h = int((img_h - icon_h) / 2)
    # 将带白边的logo居中贴到二维码中间,会遮挡部分二维码,但是纠错功能会自动补全
    qr_image.paste(wh_image_icon, (w, h), mask=None)
    # 重设二维码尺寸为 490*490
    qr_image = qr_image.resize((490, 490), Image.ANTIALIAS)
    return(qr_image)

二、二维码的伪造(代码不公开)

在这里插入图片描述
在这里插入图片描述

# 仿造微信支付宝
def copy_wechat_alipay(qr_image, qr_name, copy_png, copy_qr_loc, copy_name_locy):
    # 为防止被人利用,此处代码暂不公开
    pass

三、二维码的识别

在这里插入图片描述

# 识别解析二维码
def qr_identify():
    words = ''
    # 打开需要识别的二维码文件
    s_filename = filedialog.askopenfilename()
    # 判断文件是否存在
    if not os.path.exists(s_filename):
        raise FileExistsError(s_filename)
    # 显示二维码
    qr_show(s_filename)
    # 解析二维码
    words = pyzbar.decode(Image.open(s_filename), symbols=[pyzbar.ZBarSymbol.QRCODE])
    # 转换格式,提取有用数据
    words = list(words[0])[0].decode('utf-8')
    # 设置识别结果到第一行
    qr_str.set(words)
    name_str.set('')
    logo_str.set('')

四、Tkinter可视化UI界面

# 创建窗口控件及布局
def create_window():
	# 此处省略部分控件代码
    # 按钮放到表格布局中
    """
    grid管理器是Tkinter里面最灵活的几何管理布局器。如果你不确定什么情况下从三种布局管理中选择,你至少要保证自己会使用grid。
        使用grid进行布局管理非常容易。只需要创建控件,然后使用grid方法去告诉布局管理器在合适的行和列去显示它们。
        你不用事先指定每个网格的大小,布局管理器会自动根据里面的控件进行调节。
        注意:无法在一个主窗口中混合使用pack和grid
        默认的控件会在网格中居中显示。sticky选项指定对齐方式,可以选择的值有:N/S/E/W,分别代表上北/下南/左西/右东。
        columnspan选项可以指定控件跨越多列显示
        rowspan选项可以指定控件跨越多行显示
    window.update() 可以手动刷新界面
    """

    lb_title.grid(row=1, column=0, columnspan=4, pady=30)

    lb_qr.grid(row=3, column=0, padx=10, pady=5)
    et_qr.grid(row=3, column=1, padx=10, pady=5, columnspan=3, sticky='w')

    btn_logo.grid(row=6, column=0, padx=10, pady=5)
    et_logo.grid(row=6, column=1, padx=10, pady=5, columnspan=3, sticky='w')

    lb_name.grid(row=5, column=0, padx=10, pady=5)
    et_name.grid(row=5, column=1, padx=10, pady=5, columnspan=3, sticky='w')

    btn_save_path.grid(row=9, column=0, padx=10, pady=5)
    et_path.grid(row=9, column=1, padx=10, pady=5, columnspan=3, sticky='w')

    lb_copy.grid(row=10, column=0, padx=10, pady=5)
    radio_original.grid(row=10, column=1, padx=10, pady=5, sticky='e')
    radio_wechat.grid(row=10, column=2, padx=10, pady=5)
    radio_alipay.grid(row=10, column=3, padx=10, pady=5, sticky='w')

    btn_generate.grid(row=11, column=0, padx=10, pady=5)

    btn_clear.grid(row=12, column=0, padx=10, pady=5)

    lb_image.grid(row=11, column=1, rowspan=3, columnspan=3, padx=10, pady=5)

    btn_identify.grid(row=14, column=0, padx=10, pady=5)


create_window()
# 窗口死循环
window.mainloop()

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岳涛@心馨电脑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值