出于疫情防控要求,近期需要向新生统计健康码、行程码等截图,确保秋季学期正常开学。
问题简述
过去的解决方案是收截图, 然后再一个一个进行核验, 在此之前需要对截图进行分类. 分类的工作通常是由核验人负责或是新生按照标准要求打包发送给核验人.
两种方案都有一些缺陷, 例如核验人的负担过重, 部分新生提交的数据不符合要求等等. 尽管目前可以通过调查问卷(收集表)的形式简化收集流程, 但是对于导出到本地的数据仍然需要进行分类处理.
这里在调查问卷收集的基础上使用 Python 进行分类处理,简化流程。后序还可添加对图片进行 OCR 识别处理的功能。
使用调查问卷的好处是数据清晰,上手简单,对于不需要归档存储的截图使用这种方式已经可以达到目的。本次提出的解决方案是针对数据导出后的分类处理问题。
基本原理
对于腾讯问卷导出的数据,有 CSV 和附件两种,CSV 中存储了用户的填写顺序,附件则是按照问题分文件夹提供了附件。
对于文件夹中的附件,平台会根据填写顺序添加前缀,很大程度上简化了之后的工作
因此,程序只需要实现:
- 从 CVS 中读取到用户的填写顺序
- 分别遍历每一个文件夹(即每一个问题所提交的所有附件)
- 将每一个附件按照提交顺序修改成对应的姓名
- 修改结束后将所有的文件移动到指定的文件夹中
代码解释
Part 1 处理 CSV 和附件中的数据
CSV 中包含问卷回收的数据, 我们只需要根据序号和姓名构建一个有序映射即可.
腾讯问卷导出的附件会自动存储到对应的文件夹里,文件夹名通常为“ q-*-xxx ”,其中 * 为问题编号。
在这里假定问题顺序为["健康码","行程卡","核酸检测"]
,将 * 按照顺序排序然后构建一个映射即可.
import os
import shutil
import pandas as pd
import numpy as np
_nameList=["健康码","行程卡","核酸检测"] # 标记文件夹内的信息,按照问题顺序
name={"0":"0"}
imgName={'0':'0'}
quesNumList=[]
# 对人员名单进行初始化,从 CSV 文件中获取到填写顺序
dirList= os.listdir('./')
for dirName in dirList:
if(dirName.find('.')!=-1):
if(dirName.split('.')[1]=='csv'):
_data = pd.read_csv(dirName)
numberList = _data["编号"]
studentList = _data["1.姓名"] #获取某一标题的数据,根据不同的问卷设计,这里需要进行更改
_name = np.array(studentList)
_number = np.array(numberList)
idx=0;
for newName in _name:
name[_number[idx]]=newName # 存储为一个映射
idx+=1
print(name) # 将获取到的名单输出到控制台
break
def getOrder():
dirList= os.listdir('./')
idx=0
for dirName in dirList:
if(dirName.find('.')==-1):
quesNumList.append(dirName.split('-')[1])
idx+=1
quesNumList.sort()
idx=0
for i in quesNumList:
imgName[i]=_nameList[idx]
idx+=1
print(imgName)
Part 2 重命名图片
根据 CSV 中构建的映射,可以根据图片的前缀编号进行重命名.
def _rename(fileName):
num=fileName[0:2]
num=num.split('_')[0] # 获取文件的前缀编号,即填写顺序
shutil.move('./'+dirName+'/'+fileName,'./'+dirName+'/'+name[int(num)]+'.jpg')
#通过 dict 直接获取编号到姓名的映射
# 循环遍历所有文件
dirList= os.listdir('./')
for dirName in dirList:
if(dirName.find('.')==-1):
fileList=os.listdir('./'+dirName+'/')
for fileName in fileList:
_rename(fileName)
Part 3 移动图片到指定文件夹
重命名后需要将文件移动到指定文件夹中, 在移动的同时对图片进行了”健康码””行程卡””核酸检测”的标识.
在移动的同时判断路径是否存在, 不存在则创建一个新文件夹
def _remove(dirName,fileName,number):
newName=fileName.split('.')[0]
# 判断文件夹是否存在,不存在则创建文件夹,然后移动当前文件到指定位置
if(os.path.exists('./.result')==False):
os.mkdir('./.result')
if(os.path.exists('./.result/'+newName)==False):
os.mkdir('./.result/'+newName)
shutil.move('./'+dirName+'/'+fileName, './.result/'+newName+'/')
# 为文件添加一个唯一的标识,防止重名覆盖
os.renames('./.result/'+newName+'/'+fileName,'./.result/'+newName+'/'+imgName[number]+"-"+fileName)
dirList= os.listdir('./')
for dirName in dirList:
if(dirName.find('.')==-1):
fileList=os.listdir('./'+dirName+'/')
for fileName in fileList:
_remove(dirName,fileName,dirName.split('-')[1])
完整代码
import os
import shutil
import pandas as pd
import numpy as np
_nameList=["健康码","行程卡","核酸检测"] # 标记文件夹内的信息,按照问题顺序
name={"0":"0"}
imgName={'0':'0'}
quesNumList=[]
# 对人员名单进行初始化,从 CSV 文件中获取到填写顺序
dirList= os.listdir('./')
for dirName in dirList:
if(dirName.find('.')!=-1):
if(dirName.split('.')[1]=='csv'):
_data = pd.read_csv(dirName)
numberList = _data["编号"]
studentList = _data["1.姓名"] #获取某一标题的数据,根据不同的问卷设计,这里需要进行更改
_name = np.array(studentList)
_number = np.array(numberList)
idx=0;
for newName in _name:
name[_number[idx]]=newName # 存储为一个映射
idx+=1
print(name) # 将获取到的名单输出到控制台
break
def getOrder():
dirList= os.listdir('./')
idx=0
for dirName in dirList:
if(dirName.find('.')==-1):
quesNumList.append(dirName.split('-')[1])
idx+=1
quesNumList.sort()
idx=0
for i in quesNumList:
imgName[i]=_nameList[idx]
idx+=1
print(imgName)
def _remove(dirName,fileName,number):
newName=fileName.split('.')[0]
# 判断文件夹是否存在,不存在则创建文件夹,然后移动当前文件到指定位置
if(os.path.exists('./.result')==False):
os.mkdir('./.result')
if(os.path.exists('./.result/'+newName)==False):
os.mkdir('./.result/'+newName)
shutil.move('./'+dirName+'/'+fileName, './.result/'+newName+'/')
# 为文件添加一个唯一的标识,防止重名覆盖
os.renames('./.result/'+newName+'/'+fileName,'./.result/'+newName+'/'+imgName[number]+"-"+fileName)
def _rename(fileName):
num=fileName[0:2]
num=num.split('_')[0] # 获取文件的前缀编号,即填写顺序
shutil.move('./'+dirName+'/'+fileName,'./'+dirName+'/'+name[int(num)]+'.jpg')
#通过 dict 直接获取编号到姓名的映射
getOrder()
# 进行重命名操作
dirList= os.listdir('./')
for dirName in dirList:
if(dirName.find('.')==-1):
fileList=os.listdir('./'+dirName+'/')
for fileName in fileList:
_rename(fileName)
# 进行移动操作
dirList= os.listdir('./')
for dirName in dirList:
if(dirName.find('.')==-1):
fileList=os.listdir('./'+dirName+'/')
for fileName in fileList:
_remove(dirName,fileName,dirName.split('-')[1])
print("处理完毕")
os.system("pause")
# By SDUT Bulbul
# In 2022.Sept.