批量二维码生成看起来只是”重复一百次单码生成”,但实际场景里命名混乱、内容重复、贴错码、扫不出来等问题层出不穷。这些坑都在生成之前——编号规则、内容设计、防伪标识、印刷工艺没规划好,事后纠正成本巨大。
命名规则:避免乱序的核心
最常见的坑:
错误:1.png, 2.png, ..., 100.png
排序:1, 10, 100, 11, 12, ..., 2, 20, 21, ..., 9
打印顺序与编号顺序不一致 → 全乱
正确:
✓ 001.png, 002.png, ..., 100.png(前补零)
✓ seat-A01.png, seat-A02.png, ..., seat-Z10.png(含可读编号)
✓ device-2026-001.png(年份 + 序号)
位数选择:
- < 100 个 → 3 位补零(001-099)
- < 1000 个 → 4 位补零(0001-0999)
- < 10000 个 → 5 位
含可读信息(推荐):
seat-A01-row1-col1.png ← A 区 1 排 1 列
seat-A02-row1-col2.png
...
device-2026-Q1-001-machineA.png
↑序号 ↑设备名
优势:
- 文件名一眼看出对应位置 / 设备
- 贴标时不需要查清单
- 后期排查问题快
避免特殊字符:
- ✗ 空格 / 中文 / 中文标点 → 跨平台兼容性差
- ✗
$ & % # ?→ URL 编码 / Shell 转义麻烦 - ✓ 字母 + 数字 +
-+_
内容设计:避免重复 / 可预测
三类典型内容
| 类型 | 示例 | 唯一性方案 |
|---|---|---|
| URL(邀请链接) | https://x.com/?t=xxx | URL 参数加唯一 token |
| 纯文本(设备 ID) | DEV-2026-001 | 业务规则编号 |
| 复杂数据(vCard 名片) | 多字段 | 字段组合(姓名 + 公司 + 电话) |
唯一性的常见错误
❌ 自增数字邀请码(id=1, id=2, id=3)
→ 黑客直接试 id=1-1000 抢码
❌ 时间戳作 ID(时间戳=1700000000123)
→ 并发场景可能撞码
❌ 短码(4-6 位字母数字)
→ 容量小,更容易撞 + 被穷举
❌ 用户敏感信息作 ID(身份证 / 手机号)
→ 严重隐私泄露
推荐的唯一性方案
import uuid
# UUID v4(128 位随机)
token = str(uuid.uuid4())
# 'a3f7c2e8-9b4d-4f1c-8e3a-7d9f2b5c6e8a'
# Base62 短链 token(更短但仍随机)
import secrets, string
chars = string.ascii_letters + string.digits
token = ''.join(secrets.choice(chars) for _ in range(16))
# 'aB3xY7nQ2vP9mK4w'
# 业务编号(部门 + 年份 + 自增)
biz_id = f"DEV-2026-{i:04d}"
# 'DEV-2026-0001'
容错等级:选 H 还是 L
二维码有 4 个容错等级:
| 等级 | 容错率 | 适用场景 | 编码效率 |
|---|---|---|---|
| L | 7% | 屏幕展示、清洁环境 | 最高 |
| M | 15% | 普通办公 | 中 |
| Q | 25% | 户外、印刷品 | 低 |
| H | 30% | 工业、加 logo、易污损 | 最低 |
选择策略:
- 屏幕扫码(手机展示)→ L 或 M(容量优先)
- 标签贴纸(室内)→ M 或 Q
- 户外 / 工业贴标 → H(防污损 / 折痕)
- 二维码中加 logo → H(logo 占据约 30% 区域,需要 H 才能正常识别)
陷阱:选 L 等级 + 印在户外 + 风吹日晒 → 几个月就扫不出来。
二维码下印可读编号
┌─────────────────┐
│ ▓ ▓▓▓▓ ▓▓▓ ▓ ▓ │
│ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓│
│ ▓ ▓▓▓ ▓▓▓ ▓ ▓▓▓│
│ ▓▓▓ ▓ ▓ ▓▓▓ ▓ ▓│
│ ▓ ▓ ▓▓▓ ▓▓▓ ▓▓ │
└─────────────────┘
DEV-2026-001 ← 可读编号印在下方
3F 东会议室 ← 简短说明
为什么必须印:
- 二维码扫不出来时(破损、相机失灵)→ 用户能手动查
- 视觉识别——一眼看出对应位置
- 防贴错——肉眼对照
- 防伪——印错位的伪码与真码对不上
字号 / 间距:
- 字号 ≥ 二维码宽度的 1/8
- 与码间距 5mm 以上(避免扫描误识别)
- 黑色粗体(高对比)
印刷材质与耐久度
环境/用途 推荐材质 耐久度
────────────────────────────────────────────────
室内活动(一周) 铜版纸 + 不干胶 ⭐
室内长期(年) PP 合成纸 + 哑膜 ⭐⭐⭐
户外短期(3 个月) PVC + UV 印刷 ⭐⭐⭐
户外长期(年+) PVC + UV + 哑膜 ⭐⭐⭐⭐
工业 / 户外永久 金属铝标 + 蚀刻 ⭐⭐⭐⭐⭐
高温 / 化学环境 陶瓷标牌 ⭐⭐⭐⭐⭐
典型材质成本(参考):
- 铜版纸:¥0.05/ 张
- PP 合成纸:¥0.20/ 张
- PVC + UV:¥0.50/ 张
- 金属铝标蚀刻:¥5-20/ 张
陷阱:
- 厨房 / 浴室 → 普通纸 1 个月就掉
- 户外阳光直射 → 普通油墨褪色
- 极端温度(< -20°C / > 60°C)→ 胶水失效
测试:批量生成后必做的校验
# Python 验证示例
import qrcode
from pyzbar.pyzbar import decode
from PIL import Image
contents = [...] # 你的内容列表
# 生成
for i, content in enumerate(contents, start=1):
qr = qrcode.QRCode(error_correction=qrcode.constants.ERROR_CORRECT_H)
qr.add_data(content)
qr.make(fit=True)
img = qr.make_image(fill='black', back_color='white')
img.save(f"qr-{i:04d}.png")
# 验证(解码回来对比)
for i, content in enumerate(contents, start=1):
img = Image.open(f"qr-{i:04d}.png")
decoded = decode(img)
if not decoded:
print(f"FAIL: qr-{i:04d}.png 无法解码")
elif decoded[0].data.decode() != content:
print(f"FAIL: qr-{i:04d}.png 内容不一致")
人工抽样:
- 每 100 个抽 5-10 个用手机扫
- 不同手机(iOS / Android)+ 不同距离(10cm / 30cm / 50cm)
- 印刷品先打 1 张样本,确认能扫再批量
一次性二维码(邀请码 / 验票)
单纯二维码做不到”扫一次失效”——必须服务端配合:
1. 生成时给每个码一个唯一 token
→ 数据库存 token + 状态(unused / used / expired)
2. 二维码内容 = URL + token
https://example.com/checkin?t=abc123
3. 用户扫码 → 浏览器打开 URL
→ 服务端查 token 状态
→ unused → 提供服务,标记为 used
→ used / expired → 返回"已使用 / 已过期"
4. 用户截图传播也无效——token 是一次性的
安全要点:
- token 至少 16 位随机字符(不可预测)
- 数据库 unique 约束防并发使用
- 设置过期时间(7 天 / 24 小时)
- 记录使用日志(IP / 时间 / UA)便于追溯
纯静态方案:
- 只能”信任客户端” —— 用 cookie 标记”已用”
- 换设备 / 清缓存即可绕过
- 不适合高价值场景
个人 / 小团队的简易批量方案
| 数量 | 推荐方案 |
|---|---|
| < 10 | 单个生成 + 在线工具 |
| 10-100 | 在线批量工具(CSV 上传) |
| 100-1000 | 在线工具 / Python 脚本 |
| 1000+ | Python / Node 脚本 + 定期生成 |
| 需要 logo / 颜色 | QR Code Monkey、专业 PDF 工具 |
Python 5 行搞定:
import qrcode
contents = ["url1", "url2", "url3"]
for i, c in enumerate(contents, 1):
qrcode.make(c).save(f"qr-{i:03d}.png")
Excel + 邮件合并(无编程):
- Excel 准备列表
- Word 邮件合并 + QR 字段
- 批量打印
实务清单
✅ 必做:
- 文件名前补零 + 含可读信息
- 内容唯一性用 UUID / 随机 token(不要自增)
- 容错等级按场景选(H 是户外默认)
- 二维码下印可读编号
- 抽样测试不同设备 / 距离
- 印刷前先打样
❌ 避免:
- 命名只用数字不补零
- 邀请码用自增数字
- 静态码做”一次性令牌”
- 户外用普通纸标签
- 容错等级 L + 户外环境
- 不印可读编号(扫不出无法兜底)
批量生成的核心不是”生成”——是前置规划:编号规则、内容唯一性、防伪标识、印刷材质,决定了贴出去后是用得久还是一团乱麻。