想用python面向过程深度查重逐段对比相似度,使用excel输出最终结果,但是最后两行总是报错,想问问打击该怎么修改:
# -*- coding: utf-8 -*-
# coding=utf-8
import os
import shutil
import docx
from difflib import SequenceMatcher
import chardet
import pandas as pd
# 指定要创建文件夹的路径
path2 = "E:/Test/"
# 使用os模块中的mkdir函数来创建新的文件夹
os.mkdir(path2 + "higher")
os.mkdir(path2 + "next")
# 定义源文件夹和目标文件夹路径
source_folder = "E:/Test/passage"
target_folder = "E:/Test/higher"
target_folder1 = "E:/Test/higher/"
path3 = "E:/Test/next/"
ddl = 0.4 # 得到输入的重复度阈值
similarities = {'3150405011.周奔滔。2016.专业认识实习报告.docx': [('3150405014黄辉.2016专业认识实习报告.docx', 0.7375751820196265)], '3150405014黄辉.2016专业认识实习报告.docx': [('3150405011.周奔滔。2016.专业认识实习报告.docx', 0.7375751820196265)], '3150405020鲍冬2016专业认识实习报告.docx': [('3150405029.胡浩喆.2016专业认识实习报告.docx', 0.45556552962298025)], '3150405029.胡浩喆.2016专业认识实习报告.docx': [('3150405020鲍冬2016专业认识实习报告.docx', 0.45556552962298025)], '3150405023.林综艺.2016专业认识实习报告.docx': [('3150405024.秦嘉豪.2016专业认识实习报告.docx', 0.43817137147139645)], '3150405024.秦嘉豪.2016专业认识实习报告.docx': [('3150405023.林综艺.2016专业认识实习报告.docx', 0.43817137147139645), ('3150405027.沈磊.2016专业认识实习报告.docx', 0.403960396039604), ('3150405035.黄泽磊.2016专业认识实习报告.docx', 0.45032297754537065)], '3150405027.沈磊.2016专业认识实习报告.docx': [('3150405024.秦嘉豪.2016专业认识实习报告.docx', 0.403960396039604)], '3150405035.黄泽磊.2016专业认识实习报告.docx': [('3150405024.秦嘉豪.2016专业认识实习报告.docx', 0.45032297754537065)], '3150405025.俞逸豪.2016专业认识实习报告.docx': [('3150405026.吴登麒.2016专业认识实习报告.docx', 0.6036625245258339)], '3150405026.吴登麒.2016专业认识实习报告.docx': [('3150405025.俞逸豪.2016专业认识实习报告.docx', 0.6036625245258339)]}
# 获取源文件夹中所有要复制文件的文件名列表
keys_list = [key for key in similarities.keys()]
# 使用列表推导式将字典中的键存储到一个字符串列表keys_list中
print('diction is',similarities)
print('字典中的键:',keys_list)
max2 = len(similarities) # 得到字典的长度
print('字典的长度:',max2)
# 遍历docx文件列表,并将每个文件复制到目标文件夹中
deepsimilarities_list=list()
# 初始化深度查重的列表deepsimilarities_list
files_name=list()
# 创建一个名为files_name的列表,准备在制作excel文件时使用
# df = pd.DataFrame(data=data, columns=["file1", "file2", "similarity"])
# # DataFrame 类来创建一个数据表格,参数data是一个包含相似文章名和相似度的列表,
# # 参数 columns 是一个包含列名的列表,它指定了数据表格中每一列的名称,分别为"file1"、"file2" 和 "similarity"
# # 其中,"file1" 和 "file2" 列包含文件名的字符串,"similarity" 列包含一个表示两个文件相似度的数值。这些数据来自data是列表
for file_name in keys_list:
source_file_path = os.path.join(source_folder, file_name) # source_file_path得到每一个文件的源文件绝对路径
target_file_path = os.path.join(target_folder, file_name) # target_file_path得到每一个文件的目标文件绝对路径
shutil.copy(source_file_path, target_file_path)
# 复制超过阈值0.4的文件到higher文件夹
j = 0
while j < max2: # 对字典中的每一个键进行遍历,用于建立以基准文件为名字的文件夹。
str1 = str(path3 + keys_list[j].split(".")[0])
# 所创建的新的文件夹的路径记为str1
if not os.path.exists(str1):
os.mkdir(str1)
print(path3 + keys_list[j].split(".")[0])
# 使用os模块中的mkdir函数来创建新的文件夹,名字为该学生学号,keys_list[j]是文件夹题目所代表的docx文档,
# path3 + keys_list[j].split(".")[0]是该next文件夹中代表表基准文档的子文件夹的绝对路径
value = similarities.get(keys_list[j])
# 得到字典中目标键所对应的值
max3 = len(value) # 得到字典的值里所存的列表的长度
k = 0
while k < max3: # 对字典里的每一个值所代表的列表进行遍历,得到这些要被逐段查重的文章,并复制到next文件夹对应的子文件夹里
keys = value[k][0]
# 得到元组value中的字符串keys:是将要被逐段比较的文章的名字
source = os.path.join(target_folder, keys)
# 得到元组中的字符串所代表的文档的路径作为源路径source
target = os.path.join(path3, keys_list[j].split(".")[0])
# 得到要复制到的目标路径
shutil.copy(source, target)
# 复制文件由起点文件夹复制到目标文件夹
k = k + 1
file_list = os.listdir(target)
# 获取文件夹中的所有文件
docx_files = [filename for filename in file_list if not filename.startswith('~')]
# 排除不符合要求的文件
str2 = target_folder1 + keys_list[j]
# 得到作为对比重复度基准的docx文件的路径
doc1 = docx.Document(str2)
# 打开基准文件
text1 = [para.text for para in doc1.paragraphs]
# 逐段获取基准文档的内容并存入text1的列表之中
newtext1 = list() # 创建建一个新的列表newtext1用于存储进行过文本处理,去除空格,回车后的基准文章文章段落内容
for line in text1:
if line not in ['', ' ', '\n']:
newtext1.append(line.strip())
# file1文本处理,去除空格,回车
for docx_file in docx_files:
# 循环遍历docx_files文件列表(里面储存的是next文件夹中的对应的待分段查重文件),对被查重文件分段处理
doc2 = docx.Document(os.path.join(target, docx_file))
# 使用docx库Document函数读取docx_file中的文档的路径所代表的文档
text2 = [para.text for para in doc2.paragraphs]
# 逐段获取被查重文档的内容并存入text2的列表之中
newtext2 = list()
for line in text2:
if line not in ['', ' ', '\n']:
newtext2.append(line.strip())
# file2文本处理,去除空格,回车
deepsimilarities = {}
# 创建一个字典deepsimilarities存深度查重结果
for a in range(len(newtext1)):
text1 = newtext1[a]
# 遍历newtext1列表就是:第一个文档的每一行,此文档为基准文档
for b in range(len(newtext2)):
text2 = newtext2[b]
# 遍历newtext2列表就是:第二个文档的每一行
similarity = SequenceMatcher(None, text1, text2).ratio()
# 使用SequenceMatcher判断text1和text2相似度取值范围是:0-1
# print(text1,text2,similarity)
if similarity > ddl: # 设定相似度阈值
if text1 not in deepsimilarities:
deepsimilarities[text1] = []
# 初始化字典的值为一个空列表
deepsimilarities[text1].append((text2, similarity))
# 如果超过阈值,则保存结果到深度查重的字典里面
deepsimilarities_list.append(deepsimilarities)
# 把字典deepsimilarities追加到深度查重的列表deepsimilarities_list
# deepsimilarities_list = [{file1:[(file2,similarly),(file3,similarly)...]},{file1:[(file2,similarly),(file3,similarly)...]}...]
# 列出指定目录target :os.path.join(path3, keys_list[j].split(".")[0])中所有文件和子目录,返回一个包含目录中所有条目名称的列表
j = j + 1
print('已经完成深度查重!')
print(deepsimilarities_list)
# 以下为注释:
# 将相似度结果保存到 CSV 文件中
if deepsimilarities_list!=[]: # 判断深度查重结果,如果deepsimilarities列表不等于空
for c in range(len(deepsimilarities_list)):
# 遍历deepsimilarities_list列表c从0-19
# [{file1:[(file2,similarly),(file3,similarly)...]},{file1:[(file2,similarly),(file3,similarly)...]}...]
data = list()
# 创建一个空列表data
for file1, values in deepsimilarities_list[c].items():
# 遍历deepsimilarities_list字典中的每个键值对,其中file1将采用当前对的键,并将values采用当前对的值
# 对于deepsimilarities_list列表中第c个位置上的字典,依次遍历该字典中的所有键值对(key-value pairs)。
# 在每次遍历中,将当前遍历到的键值对的键赋值给file1变量,将该键值对的值赋值给values变量
x_1 = 0
for file2, similarity in values:
# 遍历values字典中的每个键值对,其中file2将采用当前对的键,并将similarity采用当前对的值
data.append([file1, file2, similarity])
# 向data列表里面添加[基准文件,查重文件,重复度]
print(data)
# 向data列表中加入由[file1,file2,similarity]组成的列表,并不断循环遍历
title_1 = list(similarities.keys()) # 基准文件列表
title_2 = list(similarities.values()) # 被查重文件列表
df = pd.DataFrame(data=data,columns=[title_1[c],title_2[c][x_1][0],"similarity"])
x_1 = x_1 + 1
"""
pd.DataFrame()是一个Pandas库提供的创建DataFrame对象的函数,它的第一个参数data是要填充到DataFrame中的数据,
第二个参数columns则是DataFrame中各列的列名。这里通过列表解析式,将file1和file2以及字符串"similarity"组成的列表
作为columns参数传递给了pd.DataFrame()函数。file1和file2是两个字符串类型的变量,分别表示DataFrame中的前两列的列名,
"similarity"则是第三列的列名。
"""
name_1 = list(similarities.keys())[c].split(".")[0]
# print(name_1)
df.to_excel(path3 + name_1 + ".xlsx", index=False)
# 使用 Pandas 库中的一个方法to_excel,将df代表的DataFrame保存为Excel文件,to_excel保存在next文件夹下similarities.xlsx,用于深度查重
但是这几行总是出错:
第138行这里:IndexError: list index out of range
df = pd.DataFrame(data=data,columns=[title_1[c],title_2[c][x_1][0],"similarity"])
和第149行这里:不可哈希类型错误
name_1 = list(similarities.keys())[c].split(".")[0]
# print(name_1)
df.to_excel(path3 + name_1 + ".xlsx", index=False)
想请问问大家我该怎么解决?
在第138行中,出现了IndexError: list index out of range的错误,原因是在columns参数中的列表没有足够的元素来匹配data中的列表。可以通过打印出title_1和title_2来查看是否存在问题。如果是这个问题,则需要检查data列表中是否存在缺失的元素,或者重新考虑columns列表的构建方式。
在第149行中,出现了不可哈希类型错误,原因是在使用split()函数时返回的结果是一个列表,而列表是不可哈希的类型。可以通过将split()函数返回的结果转换为字符串来解决这个问题,例如可以使用join()函数将列表中的元素拼接成一个字符串。
修改后的代码如下所示:
# -*- coding: utf-8 -*-
# coding=utf-8
import os
import shutil
import docx
from difflib import SequenceMatcher
import chardet
import pandas as pd
# 指定要创建文件夹的路径
path2 = "E:/Test/"
# 使用os模块中的mkdir函数来创建新的文件夹
os.mkdir(os.path.join(path2, "higher"))
os.mkdir(os.path.join(path2, "next"))
# 定义源文件夹和目标文件夹路径
source_folder = "E:/Test/passage"
target_folder = "E:/Test/higher"
target_folder1 = "E:/Test/higher/"
path3 = "
------------------------------------------------------------------------
### 如果我的建议对您有帮助、请点击采纳、祝您生活愉快