正文
提取excel表数据成json格式的以及对图片重命名
小程序:扫一扫查出行
【扫一扫了解最新限行尾号】
复制小程序
【扫一扫了解最新限行尾号】
复制小程序
开发那边的需求
1、功夫熊猫以及阿狸布塔故事集都是属于剧集的。意思就是有很多集,这里称他们为tv
最下面这几行第一列没名字的都是单集的,这里称它们为mv
需要统计所有工作表里面的数据把tv放一个大的json里面
把mv放一个大的json里面
2、需要检索图片名列。然后检测文件夹里面是否有对应的图片。
同时把图片提取首字母并生成新文件名
比如
功夫熊猫.jpg 会变成 tv_gfxm.jpg
必备古诗.jpg 会变成 mv_gfxm.jpg
下面是最终效果图
这是单个mv的数据和字段
下面是一个tv
功能实现
这里没使用到uuid。本来想把它当做一个key的。后面发现不需要
# -*- coding: utf-8 -*-
import xlrd
import uuid
import re,time,json,shutil,os#临时存放所有单集
mv_list=[]
#临时存放剧集,后面调用format_tv方法存成tv_dict
tv_list=[]#tv_dict是所有剧集,key是首字母缩写,值是列表,列表每个元素是剧集的一行
tv_dict={}#图片集合,后期用来给图片重命名使用
pic_list=[]exec_log=open('执行日志.log','a',encoding='utf-8')# 追加模式
error_log=open('错误日志.log','a',encoding='utf-8')# 追加模式
#获取excel表中需要提取的视频文件名列表,返回值是个excel句柄
def OpenExcel(excel_file):
try:
dataHandle = xlrd.open_workbook(excel_file)
return dataHandle
except Exception as ex:
print(str(ex))
error_log.write('打开excel表失败,可能---'+excel_file+'---并不存在\n')
error_log.close()
exit(1)#读取excel数据
def ReadExcel(excel_file):
workbook=OpenExcel(excel_file)
exec_log.write("正在读取excel表内容")
print('打印所有sheet:', workbook.sheet_names())
#工作表个数
sheet_name_list=workbook.sheet_names()
sheet_count=len(workbook.sheet_names())
print("excel表sheet个数:",sheet_count)
exec_log.write("准备循环excel每个工作表..\n")
for i in range(sheet_count):
current_sheet = workbook.sheet_by_index(i) # sheet索引从0开始
rows_num = current_sheet.nrows
cols_num = current_sheet.ncols
print("当前sheet的名字是:%s 行数:%s 列数:%s:"%(sheet_name_list[i],rows_num,cols_num))
print("#####################################################")
for r in range(1,rows_num):
# 一行数据的实体
entity_dict = {}
for c in range(0,cols_num):
cell_value=get_value_and_get_int(current_sheet,r,c)
#这里如果单元格内容为空或者是None的话,再次判断是是否属于合并单元格
if (cell_value is None or cell_value == ''):
cell_value = (get_merged_cells_value(current_sheet, r, c))
the_key = 'colnum' + str(c + 1)
entity_dict[the_key] = cell_value
#第7列判断是否有空格
if entity_dict["colnum7"] is None or entity_dict['colnum7'] == '':
error_log.write("遇到图片所在列为空值的情况,无法对空值处理,格式异常位置为,3秒后退出\n")
exec_log.write("当前sheet的名字是:%s 行数:%s "%(sheet_name_list[i],r))
exec_log.close()
print("遇到图片所在列为空值的情况,无法对空值处理,格式异常位置为,3秒后退出")
print("当前sheet的名字是:%s 行数:%s "%(sheet_name_list[i],r))
time.sleep(3)
exit(1)
#第7列去掉空格,因为要把图片转成首字母
entity_dict["colnum7"].replace(' ','')
if entity_dict['colnum1'] is None or entity_dict['colnum1'] == '':
mv_list.append(entity_dict)
else:
tv_list.append(entity_dict)
exec_log.write("循环所有工作表完毕,已经追加到单集列表和剧集列表..暂未生成图片列\n")#处理单元格值中的int类型,因为xlrd模块会把int自动转成了float,再改回去
def get_value_and_get_int(sheet,r,c):
cell_value = sheet.row_values(r)[c]
# 这由于xlrd会把int类型自动转存float,这里做一个处理,把它再转回int类型
cell_type = sheet.cell(r,c).ctype # 表格的数据类型
if cell_type == 2 and cell_value % 1 == 0.0: # ctype为2且为浮点
cell_value = int(cell_value) # 浮点转成整型
return cell_value#找到所有合并单元格的坐标(上下左右)
def get_merged_cells(sheet):
"""
获取所有的合并单元格,格式如下:
[(4, 5, 2, 4), (5, 6, 2, 4), (1, 4, 3, 4)]
(4, 5, 2, 4) 的含义为:行 从下标4开始,到下标5(不包含) 列 从下标2开始,到下标4(不包含),为合并单元格
:param sheet:
:return:
"""
return sheet.merged_cells# 获取单元格的值
def get_merged_cells_value(sheet, row_index, col_index):
"""
先判断给定的单元格,是否属于合并单元格;
如果是合并单元格,就返回合并单元格的内容
:return:
"""
merged = get_merged_cells(sheet)
for (rlow, rhigh, clow, chigh) in merged:
if (row_index >= rlow and row_index < rhigh) and (col_index >= clow and col_index < chigh) :
cell_value = sheet.cell_value(rlow, clow)
# print('该单元格[%d,%d]属于合并单元格,值为[%s]' % (row_index, col_index, cell_value))
return cell_value
# print(cell_value)
# return Nonedef getUUID():
return uuid.uuid1().hex#去除标点符号
def remove_punctuation(str):
new_str=re.sub('[^\w\u4e00-\u9fff]+', '',str)
return new_str#获取单个汉字的首字母
def single_get_first(unicode1):
str1 = unicode1.encode('gbk')
try:
ord(str1)
return str1
except:
asc = str1[0] * 256 + str1[1] - 65536
if asc >= -20319 and asc <= -20284:
return 'a'
if asc >= -20283 and asc <= -19776:
return 'b'
if asc >= -19775 and asc <= -19219:
return 'c'
if asc >= -19218 and asc <= -18711:
return 'd'
if asc >= -18710 and asc <= -18527:
return 'e'
if asc >= -18526 and asc <= -18240:
return 'f'
if asc >= -18239 and asc <= -17923:
return 'g'
if asc >= -17922 and asc <= -17418:
return 'h'
if asc >= -17417 and asc <= -16475:
return 'j'
if asc >= -16474 and asc <= -16213:
return 'k'
if asc >= -16212 and asc <= -15641:
return 'l'
if asc >= -15640 and asc <= -15166:
return 'm'
if asc >= -15165 and asc <= -14923:
return 'n'
if asc >= -14922 and asc <= -14915:
return 'o'
if asc >= -14914 and asc <= -14631:
return 'p'
if asc >= -14630 and asc <= -14150:
return 'q'
if asc >= -14149 and asc <= -14091:
return 'r'
if asc >= -14090 and asc <= -13119:
return 's'
if asc >= -13118 and asc <= -12839:
return 't'
if asc >= -12838 and asc <= -12557:
return 'w'
if asc >= -12556 and asc <= -11848:
return 'x'
if asc >= -11847 and asc <= -11056:
return 'y'
if asc >= -11055 and asc <= -10247:
return 'z'
return ''#获取每个汉字每个首字母并返回英文首字母字符串
def getPinyin(str):
if str==None:
return None
str_list = list(str)
charLst = []
for item in str_list:
charLst.append(single_get_first(item))
return ''.join(charLst)#拷贝文件
def copy_file(source_file,target_file):
if os.path.exists(source_file) and not os.path.exists(target_file):
shutil.copy(source_file,target_file)
else:
error_log.write("下面路径文件不存在: %s\n"%(source_file))
print("下面路径文件不存在: %s"%(source_file))
time.sleep(0.1)#处理图片列表[[pic1,tar1],[pic2,tar2],去重并且调用拷贝文件方式拷贝为新文件
def copy_file_from_list(pic_list):
#对列表去重,这里无法使用set,因为set无法对子元素为列表的元素做hash
new_pic_list=[]
for item in pic_list:
if item not in new_pic_list:
new_pic_list.append(item)
for item in new_pic_list:
copy_file(item[0],item[1])#给单集新增加一列key,值是图片列的英文首字母加上路径名拼接字符串,比如"excel_pic_dir/mv_hj.jpg" 这种格式
def add_pic_col_for_mv(mv_list):
exec_log.write("给单集列表生成图片路径列excel_pic_dir/mv_hj.jpg 这种格式\n")
for item in mv_list:
#格式化汉字字符串,去掉特殊符号
temp_str=remove_punctuation(item['colnum7'])
#获取首字母字符串
temp_letter=getPinyin(temp_str)
# print(item['colnum7'])
# temp_letter=getPinyin(temp_letter)
# temp_letter=getPinyin(item['colnum7'])
# print(temp_letter)
#拼接为图片路径,一个放到图片集合中给后面重命名使用,一份直接增加到excel行字典中
source_file="excel_pic_dir/"+temp_str+".jpg"
target_file="excel_pic_dir/mv_"+temp_letter+".jpg"
pic_list.append([source_file,target_file])
# copy_file(source_file,target_file)
item["pic_path"]=target_file
exec_log.write("给单集列表生成图片路径列完毕\n")#给剧集新增加一列key,值是图片列的英文首字母加上路径名拼接字符串,比如"excel_pic_dir/tv_hj.jpg" 这种格式
def add_pic_col_for_tv(tv_list):
exec_log.write("给剧集列表生成图片路径列excel_pic_dir/mv_hj.jpg 这种格式\n")
for item in tv_list:
#格式化汉字字符串,去掉特殊符号
temp_str=remove_punctuation(item['colnum7'])
#获取首字母字符串
temp_letter=getPinyin(temp_str)
#拼接为图片路径
source_file="excel_pic_dir/"+temp_str+".jpg"
target_file="excel_pic_dir/tv_"+temp_letter+".jpg"
#拼接为图片路径,一个放到图片集合中给后面重命名使用,一份直接增加到excel行字典中
pic_list.append([source_file,target_file])
# copy_file(source_file,target_file)
# temp_path="excel_pic_dir/tv_"+temp_letter+".jpg"
item["pic_path"]=target_file
exec_log.write("给剧集列表生成图片路径列完毕\n")#把剧集的都放在一个字典中,key是剧集首字母,value是剧集列表
def format_tv(tv_list):
# tv_dict={}
exec_log.write("把剧集的都放在一个大字典中,key是剧集首字母,value是剧集列表\n")
for tv_item in tv_list:
#先获取字符串,去掉标点符号
temp_str=remove_punctuation(tv_item['colnum1'])
#获取首字母字符串
temp_key=getPinyin(temp_str)
if temp_key in tv_dict:
tv_dict[temp_key].append(tv_item)
else:
tv_dict[temp_key]=[]
tv_dict[temp_key].append(tv_item)
exec_log.write("把剧集的都放在一个大字典中完毕\n")if __name__ == "__main__":
ReadExcel("001.xlsx")
# print(mv_list[0])
add_pic_col_for_mv(mv_list)
add_pic_col_for_tv(tv_list)
format_tv(tv_list)
copy_file_from_list(pic_list)
print("单集个数:",len(mv_list))
print("剧集套数:",len(tv_dict))# print(mv_list[0])
# for k,v in tv_dict.items():
# print(k,v)
# break#获取单集最终字典列表
programMovieList=[]
for item in mv_list:
new_item={}
new_item["programName"]=item["colnum3"]
new_item["programYear"]=""
new_item["programType"]=""
new_item["programDirector"]=""
new_item["programActor"]=""
new_item["programPoster"]=item["pic_path"]
new_item["programIntroduce"]=item["colnum5"]
new_item["sitnum"]=0
new_item["code"]=item["colnum2"]
new_item["cpCode"]=item["colnum6"]
programMovieList.append(new_item)
exec_log.write("单集最终字典列表获取完毕\n")exec_log.write("开始dump---单集---数据到json文件中\n")
with open('mv.json', 'w',encoding='utf-8') as f_mv:
json.dump(programMovieList, f_mv,ensure_ascii=False,sort_keys=True, indent=4)
exec_log.write("dump---单集---数据完毕\n")
print("dump---单集---数据完毕..")
time.sleep(2)def get_seriesList(item_list):
seriesList=[]
for item in item_list:
new_item={}
new_item["programName"]=item["colnum3"]
new_item["code"]=item["colnum2"]
seriesList.append(new_item)
return seriesList
#获取剧集最终字典列表
programTvList=[]
for item in tv_dict:
new_item={}
# print(item)
new_item["programName"]=tv_dict[item][0]["colnum1"]
new_item["programYear"]=""
new_item["programType"]=""
new_item["programDirector"]=""
new_item["programActor"]=""
new_item["programPoster"]=tv_dict[item][0]["pic_path"]
new_item["programIntroduce"]=tv_dict[item][0]["colnum5"]
new_item["sitnum"]=len(tv_dict[item])
new_item["cpCode"]=tv_dict[item][0]["colnum6"]
new_item["recommend"]=""
new_item["seriesList"]=get_seriesList(tv_dict[item])
programTvList.append(new_item)
# for k,v in new_item.items():
# print("\""+k+"\"",v)
#indent参数是缩进的意思,它可以使得数据存储的格式变得更加优雅。
# with open('data.json', 'w',encoding='utf-8') as f:
# json.dump(new_item, f,sort_keys=True, indent=4)
exec_log.write("开始dump---剧集---数据到json文件中\n")
with open('tv.json', 'w',encoding='utf-8') as f_tv:
json.dump(programTvList, f_tv,ensure_ascii=False,sort_keys=True, indent=4)
exec_log.write("dump---剧集---数据完毕\n")
print("dump---剧集---数据完毕..")
print("程序执行完毕,2秒后退出..")
error_log.close()
exec_log.close()
time.sleep(2)
最后打包成exe交给开发那边
把使用说明告诉开发即可
运行结果