我给自己写了一个本地二维码生成器:离线生成、批量导出、样式可控

举报
yd_294377644 发表于 2026/11/04 20:41:39 2026/11/04
【摘要】 工作中经常要把链接、文本和编号做成二维码,在线工具虽然方便,却常有广告、登录要求和内容上传风险。于是我用 Python 写了一个完全离线的二维码生成器,支持实时预览、容错级别、颜色设置和批量导出。这篇博客记录编码生成、图片输出、可扫描性校验以及界面取舍中的实践经验。

目录

  1. 缘起:生成一个二维码为什么还要上传内容
  2. 需求拆解:能生成不代表真的能用
  3. 技术选型:Python 加两个依赖就够了
  4. 核心实现一:从文本到二维码矩阵
  5. 核心实现二:批量生成与文件导出
  6. UI 定制:所有设置都应该即时可见
  7. 三个影响扫码成功率的坑
  8. 结尾:工具离线之后,内容才真正属于自己

1. 缘起:生成一个二维码为什么还要上传内容

二维码是我工作中经常用到、却很少认真思考的东西。临时分享一个网址、制作设备编号、给文件下载地址配一张图,通常都会随手打开某个在线生成器。

用久之后,我开始在意几个问题:

  • 有些网站会把输入内容发送到服务器后再生成图片;
  • 页面上广告很多,下载按钮和推广按钮混在一起;
  • 导出高清图片或透明背景时要求登录;
  • 批量生成几十个编号,需要一条一条复制粘贴;
  • 网站下线或规则变化后,以前的操作流程就失效了。

二维码的生成算法本来就可以在本地完成。我的内容既不需要云端保存,也不需要短链接跳转,那么把它交给第三方就没有必要。

于是我决定写一个离线工具:输入内容后立刻预览,确认无误就保存为 PNG;需要批量生成时读取 CSV,一次输出全部图片。

2. 需求拆解:能生成不代表真的能用

我没有把目标写成“生成二维码”,而是拆成了更容易验收的项目:

诉求(人话) 拆解后(可验收)
输入后马上看到结果 内容或参数变化后自动刷新预览
手机能够稳定识别 保留静区,限制低对比度颜色组合
图片能直接使用 支持 PNG、固定尺寸和透明背景
不同场景可调整 提供四种纠错级别和边距设置
大量编号一次完成 从 CSV 读取内容,按指定列批量生成
内容不外传 生成过程不发起任何网络请求

第一版不做“动态二维码”。所谓动态二维码通常依赖一个在线跳转地址,后续才能修改目标内容,这与完全离线的目标相冲突。我只生成静态二维码,图中编码的就是用户输入的原始内容。

心得:先弄清二维码里真正保存的是什么,才能判断工具是否真的离线。

3. 技术选型:Python 加两个依赖就够了

程序使用 Python 编写,界面依然选择标准库里的 tkinter,二维码生成和图片处理交给成熟库:

能力 方案
二维码编码 qrcode
图片处理 Pillow
桌面界面 tkinter
批量数据读取 csv
配置保存 JSON

我没有自己实现二维码编码算法。它包含版本选择、数据分段、掩码和纠错码等细节,自行实现不仅工作量大,也容易生成“看起来像二维码、部分设备却扫不出来”的结果。

这个工具真正需要定制的是输入流程、参数约束、批量命名和导出体验,而不是重新发明编码算法。

心得:成熟标准优先使用经过验证的库,把精力放在自己真正要解决的交互问题上。

4. 核心实现一:从文本到二维码矩阵

生成一个基础二维码并不复杂。内容统一使用 UTF-8 编码,库会根据数据长度自动选择合适的二维码版本。

import qrcode
from qrcode.constants import ERROR_CORRECT_M

def make_qr(text, box_size=10, border=4):
    qr = qrcode.QRCode(
        version=None,
        error_correction=ERROR_CORRECT_M,
        box_size=box_size,
        border=border,
    )
    qr.add_data(text)
    qr.make(fit=True)

    return qr.make_image(
        fill_color="#111111",
        back_color="#ffffff",
    )

version=None 配合 fit=True,可以让库按照内容量自动决定矩阵大小。用户不需要理解二维码有多少个版本,只要在内容过长时收到明确提示即可。

预览不会在每次按键后立即生成。我加了约 200 毫秒的防抖:用户连续输入时取消上一次刷新任务,短暂停顿后才重新编码。这样粘贴长文本或快速修改内容时,界面不会反复计算和闪烁。

预览区旁边还会显示三项信息:字符数、生成后的模块数量,以及当前纠错级别。它们比一个笼统的“生成成功”更有帮助,尤其是在二维码越来越密时,用户能及时缩短内容或增大导出尺寸。

5. 核心实现二:批量生成与文件导出

批量模式读取 CSV 中指定的一列,一行生成一张图片。文件名来自另一列,但必须先清理系统不允许的字符。

import re

INVALID_CHARS = re.compile(r'[\\/:*?"<>|]')

def safe_filename(value, fallback):
    name = INVALID_CHARS.sub("_", value).strip().rstrip(".")
    return name or fallback

批量导出前先建立完整计划,而不是边读取边保存:

def build_export_plan(rows, name_key, data_key, output_dir):
    plan = []

    for index, row in enumerate(rows, start=1):
        data = row[data_key].strip()
        filename = safe_filename(row[name_key], f"qr_{index:04d}")
        plan.append((data, output_dir / f"{filename}.png"))

    return plan

建立计划后,程序会检查空内容、重复文件名和已存在目标。只有所有项目都通过校验,才开始生成。这能避免处理到一半才发现两个编号生成了同名文件。

图片导出时不直接把小预览图放大,而是用相同内容重新按目标尺寸渲染。二维码的边缘需要保持清晰,使用普通插值缩放可能让黑白模块出现灰色过渡,反而降低识别率。

批量完成后,程序会输出一份 CSV 报告,记录原始行号、编码内容、目标文件和生成结果。失败项不会被悄悄跳过。

心得:批量功能最重要的不是速度,而是执行前可预见、执行后可核对。

6. UI 定制:所有设置都应该即时可见

界面左侧是内容输入和参数,右侧是二维码预览。常用操作始终在一个窗口完成:

  • 文本框支持直接粘贴多行内容;
  • 纠错级别使用简单下拉框,并显示适用说明;
  • 前景色和背景色旁边实时显示对比度提示;
  • 尺寸和边距变化会立即更新预览;
  • “保存单张”和“批量生成”分成两个清晰入口。

我没有提供任意拖动定位点、渐变填充或复杂图案。二维码首先是机器读取的数据载体,其次才是一张视觉图片。装饰越自由,越容易破坏定位图形和模块边界。

保存按钮旁边会显示预计导出尺寸,例如 1200 × 1200 PNG。透明背景被单独标注风险,因为很多扫码场景最终会把透明区域叠到不可控的底色上。

界面底部还有一个“测试记录”区域。用户可以用手机扫码后手动标记通过,程序会记住本次使用的尺寸、颜色和纠错级别,便于之后重复使用经过验证的模板。

7. 三个影响扫码成功率的坑

坑一:边距太小。 二维码四周的空白区域叫静区,识别器需要它区分二维码与周围内容。为了让图片看起来更满而把边距裁掉,可能导致二维码在复杂背景上无法识别。工具默认保留 4 个模块宽度,并对过小设置给出警告。

坑二:颜色有差异不等于对比度足够。 深蓝配黑色、浅灰配白色肉眼能看出不同,摄像头在弱光和失焦情况下却可能分不清。我的工具会计算相对亮度,前景与背景对比不足时禁止批量导出,并建议使用深色前景和浅色背景。

坑三:中文内容能生成,不代表所有扫码器解释一致。 二维码保存的是字节,不同应用对纯文本编码和特殊协议的处理可能不同。包含中文、换行或特殊字符时,必须用实际目标设备测试;如果业务允许,编码一个规范的 HTTPS 地址通常兼容性更好。

另外,在中心加入 Logo 不能只依赖高纠错级别。Logo 尺寸、位置和周围留白都会影响结果。第一版干脆不提供 Logo 功能,避免给用户“选了高级纠错就一定安全”的错觉。

8. 结尾:工具离线之后,内容才真正属于自己

完成这个二维码生成器后,我最喜欢的不是多了几种颜色选项,而是生成过程变得可解释:输入什么,二维码里就保存什么;文件在哪里生成,完全由自己决定;没有短链接,也没有隐藏的跳转服务。

一个可靠的本地二维码工具应该做到:

  1. 生成过程不依赖网络;
  2. 默认参数优先保证可扫描性;
  3. 批量执行前检查全部目标;
  4. 明确区分静态二维码与在线跳转服务;
  5. 鼓励在真实设备和真实印刷尺寸下测试。

二维码并不神秘,它只是把一段数据编码成黑白模块。真正容易出问题的,是为了好看不断压缩边距、降低对比度,或者把关键内容交给无法控制的在线服务。

如果你也经常制作二维码,可以先做一个最小版本:输入文本、生成黑白二维码、保存 PNG。等实际遇到批量编号或固定模板需求时,再逐步加入 CSV 和样式设置。

工具越简单,数据流向越清楚;内容留在本地,使用时也会更踏实。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。