Streamlit是一个优秀的Python库,让数据科学家和开发者能够快速创建交互式Web应用。今天,我将展示如何使用Streamlit和qrcode库构建一个简单而实用的批量二维码生成器。

技术栈

  • Python
  • Streamlit
  • qrcode库
  • BytesIO
  • zipfile

项目功能

  • 生成单个或批量二维码
  • 自定义每个二维码的内容
  • 将生成的二维码打包下载为ZIP文件
  • 美观的用户界面

实现步骤

1. 安装必要的库

pip install streamlit qrcode pillow

2. 创建二维码生成函数

首先,我们需要一个函数来生成二维码图像:

import qrcode
from io import BytesIO def generate_qr_code(data):
"""生成二维码并返回二进制流对象。"""
qr = qrcode.QRCode(
version=1, # 控制二维码大小(1到40,数字越大尺寸越大)
error_correction=qrcode.constants.ERROR_CORRECT_H, # 容错级别
box_size=10, # 每个方块的像素大小
border=4, # 边框宽度,单位为方块
)
qr.add_data(data)
qr.make(fit=True) # 生成图片
img = qr.make_image(fill_color="black", back_color="white") # 将图片保存到字节流中
buffer = BytesIO()
img.save(buffer, format="PNG")
buffer.seek(0)
return buffer

这个函数接收文本数据,生成二维码,并将其作为字节流返回,而不是保存到磁盘上。

3. 创建ZIP打包函数

为了方便用户下载多个二维码,我们实现了一个ZIP打包功能:

import zipfile

def create_zip(qr_data_list):
"""将多个二维码图片打包成一个 ZIP 文件并返回二进制流对象。"""
zip_buffer = BytesIO()
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
for idx, (data, qr_buffer) in enumerate(qr_data_list):
zip_file.writestr(f"qr_code_{idx + 1}.png", qr_buffer.getvalue())
zip_buffer.seek(0)
return zip_buffer

4. 构建Streamlit界面

import streamlit as st

# 页面配置
st.set_page_config(page_title="二维码批量生成工具", page_icon="", layout="centered") # 页面标题
st.markdown('<div class="title"> 在线二维码生成器</div>', unsafe_allow_html=True)
st.markdown('<div class="subtitle">选择数量并输入内容生成二维码</div>', unsafe_allow_html=True) # 用户输入:选择数量
num_qr_codes = st.number_input("选择要生成的二维码数量:", min_value=1, max_value=20, step=1, value=1) # 动态生成输入框
inputs = []
for i in range(num_qr_codes):
user_input = st.text_input(f"输入内容 {i + 1}:", placeholder=f"输入第 {i + 1} 个二维码的内容")
inputs.append(user_input)

5. 处理生成和显示逻辑

# 生成二维码
if st.button("生成二维码"):
qr_data_list = []
for i, input_data in enumerate(inputs):
if input_data.strip():
qr_data_list.append((input_data, generate_qr_code(input_data)))
else:
st.warning(f"第 {i + 1} 个输入框为空,跳过生成!") if qr_data_list:
# 显示二维码,每行显示 3 个
num_per_row = 3
rows = (len(qr_data_list) + num_per_row - 1) // num_per_row
for row_idx in range(rows):
cols = st.columns(num_per_row)
for col_idx, (data, qr_buffer) in enumerate(
qr_data_list[row_idx * num_per_row : (row_idx + 1) * num_per_row]
):
with cols[col_idx]:
st.image(qr_buffer, caption=f"二维码 {row_idx * num_per_row + col_idx + 1}", width=200) # 提供 ZIP 下载按钮
zip_file = create_zip(qr_data_list)
st.download_button(
label="下载所有二维码(ZIP 文件)",
data=zip_file,
file_name="qrcodes.zip",
mime="application/zip",
help="点击下载生成的所有二维码图片",
)
else:
st.warning("请至少填写一个输入框的内容!")

6. 添加自定义CSS样式

为了美化应用界面,添加以下CSS样式:

st.markdown(
"""
<style>
.title {
text-align: center;
font-size: 3rem;
color: #4CAF50;
font-weight: bold;
margin-bottom: 20px;
}
.subtitle {
text-align: center;
font-size: 1.2rem;
color: #888;
margin-bottom: 40px;
}
/* 更多样式... */
</style>
""",
unsafe_allow_html=True,
)

7. 完整代码如下

import streamlit as st
import qrcode
from io import BytesIO
import zipfile def generate_qr_code(data):
"""生成二维码并返回二进制流对象。"""
qr = qrcode.QRCode(
version=1, # 控制二维码大小(1到40,数字越大尺寸越大)
error_correction=qrcode.constants.ERROR_CORRECT_H, # 容错级别
box_size=10, # 每个方块的像素大小
border=4, # 边框宽度,单位为方块
)
qr.add_data(data)
qr.make(fit=True) # 生成图片
img = qr.make_image(fill_color="black", back_color="white") # 将图片保存到字节流中
buffer = BytesIO()
img.save(buffer, format="PNG")
buffer.seek(0)
return buffer def create_zip(qr_data_list):
"""将多个二维码图片打包成一个 ZIP 文件并返回二进制流对象。"""
zip_buffer = BytesIO()
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
for idx, (data, qr_buffer) in enumerate(qr_data_list):
zip_file.writestr(f"qr_code_{idx + 1}.png", qr_buffer.getvalue())
zip_buffer.seek(0)
return zip_buffer # Streamlit 页面设置
st.set_page_config(page_title="二维码批量生成工具", page_icon="", layout="centered") # 自定义样式
st.markdown(
"""
<style>
.title {
text-align: center;
font-size: 3rem;
color: #4CAF50;
font-weight: bold;
margin-bottom: 20px;
}
.subtitle {
text-align: center;
font-size: 1.2rem;
color: #888;
margin-bottom: 40px;
}
.input-box {
margin: 20px auto;
padding: 20px;
border-radius: 10px;
background-color: #f9f9f9;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
max-width: 600px;
}
.qr-image {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 20px;
margin-top: 30px;
}
.qr-container {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 20px;
}
.download-btn {
margin-bottom: 10px;
padding: 10px 20px;
font-size: 1rem;
font-weight: bold;
color: white;
background: linear-gradient(90deg, #4CAF50, #2E8B57);
border: none;
border-radius: 5px;
cursor: pointer;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
.download-btn:hover {
background: linear-gradient(90deg, #2E8B57, #4CAF50);
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.2);
}
.char-limit-warning {
color: red;
font-size: 0.9rem;
margin-top: 5px;
text-align: right;
}
</style>
""",
unsafe_allow_html=True,
) # 页面标题
st.markdown('<div class="title"> 在线二维码生成器</div>', unsafe_allow_html=True)
st.markdown('<div class="subtitle">选择数量并输入内容生成二维码</div>', unsafe_allow_html=True) # 用户输入:选择数量
num_qr_codes = st.number_input("选择要生成的二维码数量:", min_value=1, max_value=20, step=1, value=1) # 动态生成输入框
inputs = []
for i in range(num_qr_codes):
user_input = st.text_input(f"输入内容 {i + 1}:", placeholder=f"输入第 {i + 1} 个二维码的内容")
inputs.append(user_input) # 生成二维码
if st.button("生成二维码"):
qr_data_list = []
for i, input_data in enumerate(inputs):
if input_data.strip():
qr_data_list.append((input_data, generate_qr_code(input_data)))
else:
st.warning(f"第 {i + 1} 个输入框为空,跳过生成!") if qr_data_list:
# 显示二维码,每行显示 3 个
num_per_row = 3
rows = (len(qr_data_list) + num_per_row - 1) // num_per_row # 计算需要的行数
for row_idx in range(rows):
cols = st.columns(num_per_row) # 每行创建 3 个列
for col_idx, (data, qr_buffer) in enumerate(
qr_data_list[row_idx * num_per_row : (row_idx + 1) * num_per_row]
):
with cols[col_idx]:
st.image(qr_buffer, caption=f"二维码 {row_idx * num_per_row + col_idx + 1}", width=200) # 打包成 ZIP 文件
zip_file = create_zip(qr_data_list) # 提供 ZIP 下载按钮
st.download_button(
label="下载所有二维码(ZIP 文件)",
data=zip_file,
file_name="qrcodes.zip",
mime="application/zip",
help="点击下载生成的所有二维码图片",
)
else:
st.warning("请至少填写一个输入框的内容!")

项目亮点

  1. 动态输入框:根据用户选择的数量动态生成输入框
  2. 响应式布局:使用列布局实现美观的多行多列显示
  3. 批量下载:支持将所有生成的二维码打包下载
  4. 错误处理:提供空输入验证和警告信息
  5. 美观UI:使用自定义CSS美化界面

运行应用

将上述代码保存为batch_barcode.py,然后运行:

streamlit run batch_barcode.py

访问浏览器中显示的本地URL(通常是 http://localhost:8501)即可使用应用。

扩展思路

  • 添加更多二维码自定义选项(颜色、大小、纠错级别)
  • 支持批量导入数据(CSV文件上传)
  • 添加条形码生成功能
  • 实现二维码内容预览功能
  • 支持生成带Logo的二维码

结论

通过Streamlit,我们能够快速构建一个功能齐全的二维码生成Web应用,无需编写HTML、CSS或JavaScript代码。这种开发方式非常适合原型设计和内部工具开发,大大提高了开发效率。

希望这个项目能为你提供参考,帮助你构建自己的Streamlit应用!

使用Streamlit构建批量二维码生成器的更多相关文章

  1. [python] Python二维码生成器qrcode库入门

    Python二维码生成器qrcode库入门 qrcode是二维码生成的Python开源库,官方地址为python-qrcode.所有代码见:Python-Study-Notes. 文章目录 Pytho ...

  2. C#版二维码生成器附皮肤下载

    原文 C#版二维码生成器附皮肤下载 前言 本文所使用的二维码生成代码是谷歌开源的条形码图像处理库完成的,c#版的代码可去https://code.google.com/p/zxing/download ...

  3. vue的二维码生成器

    vue项目开发的时候经常会遇到需要将一个网址链接转化为二维码的需求,方便用户扫描观看,以下就是我在寻找vue二维码生成器的时候踩过的坑. 不能用的二维码生成器    qrcode    node-qr ...

  4. jquery二维码生成插件_二维码生成器

    jquery二维码生成插件_二维码生成器 下载地址:jquery生成二维码.rar

  5. 标星7000+,这个 Python 艺术二维码生成器厉害了!

    微信二维码,相信大家也并不陌生,为了生成美观的二维码,许多用户都会利用一些二维码生成工具. 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手 ...

  6. QR二维码生成器源码(中间可插入小图片)

    二维码终于火了,现在大街小巷大小商品广告上的二维码标签都随处可见,而且大都不是简单的纯二维码,而是中间有个性图标的二维码. 我之前做了一个使用google开源项目zxing实现二维码.一维码编码解码的 ...

  7. C++ 里 构建动态二维数组

    //****动态二维数组 /* int m=3; int **data; int n=2; data=new int*[m]; for(int j=0;j<m;j++) { data[j]=ne ...

  8. C#版二维码生成器

    前言 本文所使用的二维码生成代码是谷歌开源的条形码图像处理库完成的,c#版的代码可去 这里   --  下载压缩包. 截止目前为止最新版本为2.2,提供以下编码格式的支持: UPC-A and UPC ...

  9. python二维码生成器

    周小董简书主页二维码.png   周小董博客主页二维码.png 现在,我们生活中到处可以看到二维码.它有啥好处呢?它具有信息容量大.可靠性高.可表示汉字及图象多种文字信息.保密防伪性强等优点. 我们生 ...

  10. laravel 二维码生成器包 QrCode 的使用

    在laravel中使用 QrCode 生成二维码 https://laravelacademy.org/post/2605.html 我在本机的windows下composer require 没有成 ...

随机推荐

  1. day2-变量与数据类型

    变量 概念:程序的基本组成单位 定义: 指定变量类型 根据值自行判断变量类型(类型推导) 省略var,定义赋值 var i int var i = 10 i, j := 20, 10 数据基本类型 基 ...

  2. 解决bootstrapvalidator配合select2插件不能正常校验的问题

    我在使用bootstrapvalidator对select2插件进行校验时,出现了不能校验的问题,于是求助度娘,发现大多的解决方法是这样的: 1.添加一个隐藏域,将bootstrapvalidator ...

  3. python 二级 基本数据类型

    1.思维导图 需要特殊记忆知识点 -1.01E-3值为 0.00101 基本运算一共9个: 取整 a//b 取余数 a%b x的y次幂 :x**y 数值运算函数 format 格式的控制 常用的操作 ...

  4. 魔方求解器程序(层先法,java版本)

    实现了一个三阶魔方的层先法求解程序:https://github.com/davelet/java-puzzle-resolver 欢迎试用. 用法 1. 随机试用 不关注起始状态的话可以用程序的随机 ...

  5. 查看、安装python指定版本的包、安装卸载第三方模块

    python安装/卸载第三方包 (1)安装第三方包: 安装指令pip install xxx (xxx,需安装的包名) 安装特定版本的package:通过使用==, >=, <=, > ...

  6. linux ln命令详解

    介绍 ln是linux的一个重要命令,它的功能是为某一个文件在另外一个位置建立一个同步的链接.当我们需要在不同的目录,用到相同的文件时,我们不需要在每一个需要的目录下都放一个必须相同的文件,我们只要在 ...

  7. go 遍历修改切片数据

    package main import "fmt" type good struct { id int64 sum int64 } func main() { good1 := g ...

  8. 用状态模式开发一个基于WPF的截图功能

    状态模式 状态模式是设计模式中的一种行为设计模式,对很多人来说,这个模式平时可能用不到.但是如果你做游戏开发的话,我相信你应该对这个模式有一个很深刻的理解.状态模式在游戏中开发中还是比较常见的.状态模 ...

  9. Anaconda指定目录安装终极指南+避坑大全

    最近被Python环境搞疯了吧?一个项目跑起来另一个就报错?用Conda环境隔离大法就对了!但默认安装竟吃掉根分区8G的硬盘?今天手把手教你迁移安装目录+实战部署AI项目. 今天测试AIREPORT, ...

  10. 事件监听、焦点--java进阶day03

    1.事件 按钮是组件,点击后就会重新游戏 对于这种点击了组件之后,有逻辑触发的操作,就是事件 2.事件中的专有名词 绑定监听也就是绑定监视,是真正组织代码逻辑的地方 要有绑定监听就需要监听器,今天学习 ...