读取单个文件,并获取培养目标和学分学时比例说明数据
filename1 = r"E:\vscode\reddemo\edudata\02\一本\02.docx" # 可以存储到字典中了,但字典格式可以优化下 import numpy as np # 创建一个接受匹配不成功的反馈记录 # 第4项的数据 培养目标 re_4_start =re.compile("^四.{1}培养目标") # 匹配用 四.{1}培养目标 开头的文本 re_4_end =re.compile("^五.{1}毕业要求:") # 第8项的数据 学分学时比例说明数据 re_8_start =re.compile("^八.{1}学分学时比例说明") re_8_end =re.compile("^九.{1}备注说明") # 抽取模式,不校验数据的准确性 def docx_read(file1): # 定义接受当前文档的part_4和part_8 part_all_dict_new = {} # print("当前文件:====>",os.path.join("",file1)) document = Document(os.path.join("",file1)) # df=pd.DataFrame(columns =['总学分','课内学分','课内学分占比','实践教学学分','实践教学占比','选修课学分', # '选修课学分占比','通识教育平台学分','通识教育平台学分占比','学科基础教育平台学分','学科基础教育平台学分占比', # '专业教育平台学分','专业教育平台学分占比']) # 所有的段落,存放list all_paragraphs = document.paragraphs start_4_part = 0 # 培养目标 起始位置 end_4_part = 0 # 培养目标 结束位置 start_8_part = 0 # 学分学时比例说明 起始位置 end_8_part = 0 # 学分学时比例说明 结束位置 start_paragraphs_num = 0 # 定义段落初始值为0 for i in all_paragraphs: # 便利所有的段落 start_paragraphs_num +=1 if(re.match(re_4_start,i.text)): # 如果该段以 四.{1}培养目标 为开头 start_4_part = start_paragraphs_num # 将该段落的值设置为 培养目标 起始位置 elif (re.match(re_4_end,i.text)): # 如果该段以 五.{1}毕业要求: 为开头 end_4_part = start_paragraphs_num elif(re.match(re_8_start,i.text)): # 如果该段以 八.{1}学分学时比例说明 为开头 start_8_part = start_paragraphs_num elif(re.match(re_8_end,i.text)): # 如果该段以 九.{1}备注说明 为开头 end_8_part = start_paragraphs_num else: pass # 提取第4部分内容 str_4_part_all = "" if start_4_part ==0 or end_4_part ==0 : print(file1,"的第4部分无法匹配") else: print("start_4_part : ",start_4_part) print("end_4_part : ",end_4_part) part_4 = all_paragraphs[start_4_part:end_4_part-1] # 通过list切片的方式获取 第4部分培养目标 的全部段落数据 for i in part_4: str_4_part_all = str_4_part_all+i.text # 把所有段落拼接到一个字符串变量str_4_part_all 中 # print(str_4_part_all,"第4段的完成匹配") # 提取第8部分内容 str_8_part_all = "" if start_8_part ==0 or end_8_part ==0 : print(file1,"的第8部分无法匹配") else: print("start_8_part : ",start_8_part) print("end_8_part : ",end_8_part) part_8 = all_paragraphs[start_8_part:end_8_part-1] for i in part_8: str_8_part_all = str_8_part_all+i.text # print(str_8_part_all,"的第8部分完成匹配") # print() # part_all_dict_new[file1+".id"] = file1 # part_all_dict_new[file1+".part_4"] = str_4_part_all # part_all_dict_new[file1+".part_8"] = str_8_part_all # ID为文件名称 part_4为第4部分数据 part_8为第8部分数据 part_all_dict_new[file1]={ "ID":file1, "part_4":str_4_part_all, "part_8":str_8_part_all, } return file1,part_all_dict_new print("*"*10) file1,part_all_dict_new = docx_read(filename1) print(file1) print(part_all_dict_new)
运行,输出为:
**********
start_4_part : 8
end_4_part : 10
start_8_part : 63
end_8_part : 66
E:\vscode\reddemo\edudata\02\一本\02.docx
{‘E:\vscode\reddemo\edudata\02\一本\02.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\02\一本\02.docx’, ‘part_4’: ‘本专业培养适应我国社会主义现代化建设需要,德智体美劳全面发展,具有扎XX领域理论基础和专业知识,并熟练XXX人才。’, ‘part_8’: ‘总学分为170学分,其中课内学分(含课内实践)为119.5学分,占总学分的70.29%,实践教学(含课内实践、集中实践、综合实践)学分为60.5学分,占总学分的35.59%;选修课学分为44学分,占总学分的25.88%。通识教育平台学分为48学分,占总学分的28.24%,学科基础教育平台学分为29.5学分,占总学分的17.35%,专业教育平台学分为42学分,占总学分的24.71%。课内总学时(含课内实践)为1976学时,其中选修课学时为400学时,占课内总学时的20.24%。通识教育平台学时为832学时,占课内总学时的42.11%;学科基础教育平台学时为472学时,占课内总学时的23.89%,专业教育平台学时为672学时,占课内总学时的34.01%。’}}
2.2.4 获取指定目录下所有文档中的数据
通过遍历的方式,获取指定目录下的所有文件,并对doc文件另存为docx文件,提取docx中的相关数据,代码如下:
filedirs=r'E:\vscode\reddemo\edudata' # 所有文件存在的路径 # filenames = os.listdir("str1") part_all_dict_new = {} # 存放所有匹配到的文件中的 四.{1}培养目标" 和八.{1}学分学时比例说明 数据 def contentExtract(str1): # 内容抽取函数 files = glob(str1 + '/*') # 匹配指定目录下的所有多层目录 print(files) for i in files: print("当前文件为:",i) if re.findall('.docx',i): # 如果当前文件为docx结尾 fname,part_all_dict = docx_read(str(i)) # fname为文件名称ID,part_all_dict为该文件内容抽取后匹配到的数据 # print(part_all_dict[fname]) part_all_dict_new[fname] = part_all_dict[fname] # 将指定文件抽取后的数据 写入 part_all_dict_new字典, 用文件名称ID作为key # print("part_all_dict_new[fname]",part_all_dict_new[fname]) # print(part_all_dict) # part_all_dict_new.update(part_all_dict) elif re.findall('.doc',i): # 如果当前文件以doc结尾 doc_read(str(i)) # 将doc文件另存为docx fname,part_all_dict =docx_read(str(i) + 'x') # 读取另存后的docx文件 part_all_dict_new[fname] = part_all_dict[fname] # print(part_all_dict) # part_all_dict_new.update(part_all_dict) elif re.findall('.pdf',i): # 如果当前文件以pdf结尾 print("这是一个pdf文件") elif os.path.isdir(i): print("当前为目录:",i) contentExtract(str(i)) # 迭代 如果为目录 # print("part_all_dict_new*******",part_all_dict_new) return part_all_dict_new part_all_dict_new1 = contentExtract(filedirs) part_all_dict_new1
输出为:
Output exceeds the size limit. Open the full output data in a text editor [‘E:\vscode\reddemo\edudata\01’, ‘E:\vscode\reddemo\edudata\02’, ‘E:\vscode\reddemo\edudata\03’, ‘E:\vscode\reddemo\edudata\04’, ‘E:\vscode\reddemo\edudata\05’, ‘E:\vscode\reddemo\edudata\06’, ‘E:\vscode\reddemo\edudata\07’, ‘E:\vscode\reddemo\edudata\08’, ‘E:\vscode\reddemo\edudata\09’, ‘E:\vscode\reddemo\edudata\10’, ‘E:\vscode\reddemo\edudata\11’, ‘E:\vscode\reddemo\edudata\12’, ‘E:\vscode\reddemo\edudata\13’, ‘E:\vscode\reddemo\edudata\14’, ‘E:\vscode\reddemo\edudata\tree.txt’] 当前文件为: E:\vscode\reddemo\edudata\01 当前为目录: E:\vscode\reddemo\edudata\01 [‘E:\vscode\reddemo\edudata\01\一本’, ‘E:\vscode\reddemo\edudata\01\普本’] 当前文件为: E:\vscode\reddemo\edudata\01\一本 当前为目录: E:\vscode\reddemo\edudata\01\一本 [‘E:\vscode\reddemo\edudata\01\一本\01人才培养方案(2021版)2021年9月13日 - 02.docx’, ‘E:\vscode\reddemo\edudata\01\一本\02人才培养方案-2021版.doc’, ‘E:\vscode\reddemo\edudata\01\一本\02人才培养方案-2021版.docx’] 当前文件为: E:\vscode\reddemo\edudata\01\一本\01人才培养方案(2021版)2021年9月13日 - 02.docx E:\vscode\reddemo\edudata\01\一本\01人才培养方案(2021版)2021年9月13日 - 02.docx 的第4部分无法匹配 E:\vscode\reddemo\edudata\01\一本\01人才培养方案(2021版)2021年9月13日 - 02.docx 的第8部分无法匹配 当前文件为: E:\vscode\reddemo\edudata\01\一本\02人才培养方案-2021版.doc start_4_part : 9 end_4_part : 18 E:\vscode\reddemo\edudata\01\一本\02人才培养方案-2021版.docx 的第8部分无法匹配 当前文件为: E:\vscode\reddemo\edudata\01\一本\02人才培养方案-2021版.docx start_4_part : 9 end_4_part : 18 E:\vscode\reddemo\edudata\01\一本\02人才培养方案-2021版.docx 的第8部分无法匹配 当前文件为: E:\vscode\reddemo\edudata\01\普本 当前为目录: E:\vscode\reddemo\edudata\01\普本 [‘E:\vscode\reddemo\edudata\01\普本\03.doc’, ‘E:\vscode\reddemo\edudata\01\普本\03.docx’, ‘E:\vscode\reddemo\edudata\01\普本\04.doc’, ‘E:\vscode\reddemo\edudata\01\普本\04.docx’, ‘E:\vscode\reddemo\edudata\01\普本\05.docx’] 当前文件为: E:\vscode\reddemo\edudata\01\普本\03.doc start_4_part : 9 end_4_part : 11 start_8_part : 21 … end_4_part : 9 start_8_part : 22 end_8_part : 25 当前文件为: E:\vscode\reddemo\edudata\tree.txt Output exceeds the size limit. Open the full output data in a text editor {‘E:\vscode\reddemo\edudata\01\一本\01人才培养方案(2021版)2021年9月13日 - 02.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\01\一本\01人才培养方案(2021版)2021年9月13日 - 02.docx’, ‘part_4’: ‘’, ‘part_8’: ‘’}, ‘E:\vscode\reddemo\edudata\01\一本\02人才培养方案-2021版.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\01\一本\02人才培养方案-2021版.docx’, ‘part_4’: ‘培养XX并具有自主学习和适应发展的能力。’, ‘part_8’: ‘’}, ‘E:\vscode\reddemo\edudata\01\普本\03.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\01\普本\03.docx’, ‘part_4’: ‘本专业XX应用技术型人才。’, ‘part_8’: ‘总学分为170学分,XX占课内总学时的26.2%。’}, ‘E:\vscode\reddemo\edudata\01\普本\04.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\01\普本\04.docx’, ‘part_4’: ‘本专业培养适应XX应用技术型人才。’, ‘part_8’: ‘总学分为170学分,其中课内XX占总学时的21%。’}, ‘E:\vscode\reddemo\edudata\01\普本\05.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\01\普本\05.docx’, ‘part_4’: ‘培养适应XX才。’, ‘part_8’: ‘总学分为170学分,XX占课内总学时的15.02%。’}, ‘E:\vscode\reddemo\edudata\02\0224+工程造价双学位(更新后20211009).docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\02\0224+工程造价双学位(更新后20211009).docx’, ‘part_4’: ‘’, ‘part_8’: ‘’}, ‘E:\vscode\reddemo\edudata\02\一本\01.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\02\一本\01.docx’, ‘part_4’: ‘工程管理专业培养适应XX能力。’, ‘part_8’: ‘总学分为170学分,XX占课内总学时的31.20%。’}, ‘E:\vscode\reddemo\edudata\02\一本\02.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\02\一本\02.docx’, ‘part_4’: ‘本专业培养XX人才。’, ‘part_8’: ‘总学分为170学分,XX占课内总学时的34.01%。’}, ‘E:\vscode\reddemo\edudata\02\双学位\022.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\02\双学位\022.docx’, … ‘part_4’: ‘法学双学位XX工作。’, ‘part_8’: ‘总学分为50学分,XX占课内总学时的37.5%。’}, ‘E:\vscode\reddemo\edudata\14\第二学士学位\01.docx’: {‘ID’: ‘E:\vscode\reddemo\edudata\14\第二学士学位\01.docx’, ‘part_4’: ‘本专业XX人才。’, ‘part_8’: ‘总学分为80学分,XX占课内总学时的51.6%。’}}
以上会返回一个字典,包含了文件名,第4部分内容,第8部分内容
2.2.5 将结果字典保存到DataFrame中
通过字典转换为DataFrame格式。
df1 = pd.DataFrame(part_all_dict_new) df1
转置DataFrame,并重置索引
dfnew = df1.T dfnew1 = dfnew.reset_index() dfnew1
输出为:
删除index列
del dfnew1["index"] dfnew1 • 1 • 2
输出为:
把数据保存到excel中
dfnew1.to_excel("firstData_T.xlsx",encoding="UTF-8") • 1
生成的如下所示:
2.2.6 提取学分学时数据并保存
定义一个DataFrame,用来获取part_8中的学分学时信息
dfnew1_split=pd.DataFrame(columns =['总学分','课内学分','课内学分占比','实践教学学分','实践教学占比','选修课学分', '选修课学分占比','通识教育平台学分','通识教育平台学分占比','学科基础教育平台学分','学科基础教育平台学分占比', '专业教育平台学分','专业教育平台学分占比','课内总学时','选修课学时','选修课学时占比','通识教育平台学时', '通识教育平台学时占比','学科基础教育平台学时','学科基础教育平台学时占比','专业教育平台学时', '专业教育平台学时占比','ID']) print(dfnew1_split.shape) dfnew1_split.set_index('ID',inplace=True) dfnew1_split
输出为:
以上代码定义了一个空的DataFrame。
遍历dfnew1的每一行数据,并对part_8列数据进行正则表达式匹配,获取学时学分数据。
dfnew1的数据如下:
代码如下:
for i in range(dfnew1['ID'].count()): # 根据数据行数进行遍历 str1 = dfnew1['ID'][i] # 获取第i行的id 即文件全路径 str1 = str1[26:] # 切片操作 str1 = str1.replace('.docx','') # 替换掉docx # 定义正则表达式匹配数据 # 原始数据为 ''' 总学分为173学分,其中课内学分(含课内实践)为134学分,占总学分的77.5%, 实践教学(含课内实践、集中实践、综合实践)学分为60.5学分,占总学分的35%; 选修课学分为21学分,占总学分的12.1%。 通识教育平台学分为48学分,占总学分的27.7%, 学科基础教育平台学分为44学分,占总学分的25.4%,专业教育平台学分为42学分,占总学分的24.3%。 课内总学时(含课内实践)为2208学时,其中选修课学时为336学时,占课内总学时的15.2%。 通识教育平台学时为832学时,占课内总学时的37.7%; 学科基础教育平台学时为704学时,占课内总学时的31.9%, 专业教育平台学时为672学时,占课内总学时的30.4%。 ''' reg = '总学分.*课内学分.*实践教学.*选修课.*通识教育平台.*学科基础教育.*专业教育平台.*课内总学时.*选修课.*通识教育平台.*学科基础教育.*专业教育平台.*' if len(re.findall(reg,str(dfnew1['part_8'][i])))!=0: q=re.findall(r'[0-9]+\.?[0-9]*',str(dfnew1['part_8'][i])) # q的值为list类型,值为 '170 129 75.88 73.5 43.24 23 13.53 48 28.24 26 15.29 55 32.35 2128 368 17.29 832 39.10 416 19.55 880 41.35' # print(len(q)) # print(q) dfnew1_split.loc[str1]=q else: dfnew1_split.loc[str1]='' dfnew1_split
保存数据到excel
dfnew1_split.to_excel("Course_Credit.xlsx",encoding="UTF-8") • 1
保存后的数据如下: