提取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+'---并不存在
')
        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每个工作表..
")
    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秒后退出
")
                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("循环所有工作表完毕,已经追加到单集列表和剧集列表..暂未生成图片列
")


#处理单元格值中的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 None


def getUUID():
    return uuid.uuid1().hex

#去除标点符号
def remove_punctuation(str):
    new_str=re.sub('[^wu4e00-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
"%(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 这种格式
")
    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("给单集列表生成图片路径列完毕
")



#给剧集新增加一列key,值是图片列的英文首字母加上路径名拼接字符串,比如"excel_pic_dir/tv_hj.jpg" 这种格式
def add_pic_col_for_tv(tv_list):
    exec_log.write("给剧集列表生成图片路径列excel_pic_dir/mv_hj.jpg 这种格式
")
    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("给剧集列表生成图片路径列完毕
")


#把剧集的都放在一个字典中,key是剧集首字母,value是剧集列表
def format_tv(tv_list):
    # tv_dict={}
    exec_log.write("把剧集的都放在一个大字典中,key是剧集首字母,value是剧集列表
")
    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("把剧集的都放在一个大字典中完毕
")

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("单集最终字典列表获取完毕
")

exec_log.write("开始dump---单集---数据到json文件中
")
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---单集---数据完毕
")
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文件中
")
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---剧集---数据完毕
")
print("dump---剧集---数据完毕..")
print("程序执行完毕,2秒后退出..")
error_log.close()
exec_log.close()
time.sleep(2)

  

 最后打包成exe交给开发那边

把使用说明告诉开发即可

 

 

 运行结果

 

原文地址:https://www.cnblogs.com/nmap/p/10474142.html