在文档管理、代码审查或内容创作中,重复或高度相似的文件会带来诸多问题——占用存储空间、增加检索复杂度,甚至引发版权纠纷。手动识别这些文件既低效又容易遗漏,因此我们需要一个自动化工具来解决这一痛点。本文将带你实现一个文件内容查重工具,支持文本预处理、多种相似度算法,并输出高相似文件对,帮助你高效管理文档。
实现思路分析
我们的工具将围绕文件遍历→文本预处理→相似度计算→结果输出四个核心环节展开:
- 文件遍历:使用
glob模块递归扫描目标文件夹,收集所有文本文件(.txt、.md、.csv等)。 - 文本预处理:通过正则表达式去除标点、合并空格、统一小写,消除格式差异对相似度的影响。
- 相似度计算:提供两种算法选择:
- 编辑距离(简化版):适合短文本或精确匹配场景,通过计算字符串修改差异度(插入、删除、替换次数)衡量相似度。
- 余弦相似度(进阶版):适合长文本或语义相似场景,将文本转为TF-IDF向量,通过向量夹角的余弦值衡量语义重叠度。
- 结果输出:筛选相似度≥80%的文件对,格式化输出文件名和相似度,支持区分“完全重复”和“高度重叠”。
代码实现(Python)
下面是完整的代码实现,包含两种相似度算法,可根据需求选择:
import os
import re
import glob
import Levenshtein # 需安装:pip install python-Levenshtein
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
def collect_text_files(folder_path):
"""遍历文件夹,收集所有文本文件(.txt、.md、.csv)"""
file_extensions = ['*.txt', '*.md', '*.csv']
all_files = []
for ext in file_extensions:
# 递归匹配所有子文件夹中的目标文件
files = glob.glob(f"{folder_path}/**/{ext}", recursive=True)
all_files.extend(files)
return all_files
def preprocess_text(text):
"""文本预处理:去除标点、空格,转小写"""
# 去除标点(保留字母、数字、下划线、空格)
text = re.sub(r'[^\w\s]', '', text)
# 转小写、去除首尾空格、合并连续空格
text = text.lower().strip()
text = re.sub(r'\s+', ' ', text)
return text
def edit_distance_similarity(text1, text2):
"""基于编辑距离计算相似度:1 - 距离/最大长度"""
if not text1 and not text2:
return 1.0 # 两个空文本视为完全相同
max_len = max(len(text1), len(text2))
if max_len == 0:
return 1.0 # 避免除以0
# 计算编辑距离(Levenshtein距离)
distance = Levenshtein.distance(text1, text2)
# 转换为相似度:距离越小,相似度越高
similarity = 1 - (distance / max_len)
return similarity
def cosine_similarity_method(texts):
"""基于TF-IDF向量和余弦相似度计算文本对的相似度矩阵"""
vectorizer = TfidfVectorizer()
# 向量化所有文本(即使有空字符串,向量器也能处理)
tfidf_matrix = vectorizer.fit_transform(texts)
# 计算所有文本对的余弦相似度矩阵(n×n,n为文本数)
similarity_matrix = cosine_similarity(tfidf_matrix, tfidf_matrix)
return similarity_matrix
def main(folder_path, threshold=0.8, method='edit_distance'):
"""主函数:整合文件遍历、预处理、相似度计算、结果输出"""
# 1. 收集目标文件夹中的所有文本文件
files = collect_text_files(folder_path)
if not files:
print(f"错误:在路径 {folder_path} 中未找到文本文件!")
return
# 2. 读取并预处理文件内容
file_contents = []
for file in files:
try:
with open(file, 'r', encoding='utf-8') as f:
content = f.read()
processed = preprocess_text(content)
file_contents.append(processed)
except Exception as e:
print(f"读取文件 {file} 失败:{e}")
file_contents.append("") # 标记为无效内容,避免后续计算出错
# 3. 计算文件对的相似度
similar_pairs = []
if method == 'edit_distance':
# 遍历所有文件对(i<j,避免重复计算)
for i in range(len(files)):
for j in range(i + 1, len(files)):
text1 = file_contents[i]
text2 = file_contents[j]
sim = edit_distance_similarity(text1, text2)
if sim >= threshold:
similar_pairs.append((files[i], files[j], sim))
else: # 余弦相似度
similarity_matrix = cosine_similarity_method(file_contents)
for i in range(len(files)):
for j in range(i + 1, len(files)):
sim = similarity_matrix[i, j]
if sim >= threshold:
similar_pairs.append((files[i], files[j], sim))
# 4. 输出相似文件对(仅显示文件名,隐藏路径)
print("===== 相似文件分析结果 =====")
for pair in similar_pairs:
file1, file2, sim = pair
sim_percent = sim * 100
label = "(内容完全重复)" if sim == 1.0 else "(内容高度重叠)"
print(f"- {os.path.basename(file1)} 与 {os.path.basename(file2)}:相似度 {sim_percent:.1f}% {label}")
if __name__ == "__main__":
# 示例:请在当前目录下创建 test_files 文件夹,放入示例文件
test_folder = "test_files"
# 选择算法:'edit_distance'(编辑距离)或 'cosine'(余弦相似度)
main(test_folder, threshold=0.8, method='edit_distance')
代码解释与运行指南
- 文件遍历:
collect_text_files用glob递归扫描文件夹,支持通配符匹配多类文本文件。 - 文本预处理:
preprocess_text通过正则表达式去除标点、统一大小写、合并空格,消除格式干扰。 - 相似度算法:
- 编辑距离:通过
Levenshtein.distance计算字符串差异,转换为相似度(值越接近1,相似度越高)。适合短文本、精确匹配场景。 - 余弦相似度:用
TfidfVectorizer将文本转为TF-IDF向量,通过向量夹角的余弦值衡量语义相似度。适合长文本、语义级相似性分析。
- 编辑距离:通过
- 主函数逻辑:读取文件→预处理→计算相似度→筛选高相似对→格式化输出。
测试与扩展
测试步骤:
- 创建
test_files文件夹,放入示例文件:file1.txt:Hello world, this is a test.file2.txt:Hello world, this is a test.file3.txt:Hello world, this is another test.
- 运行代码,选择
method='edit_distance'或'cosine',观察输出是否与问题描述一致。
扩展方向:
- GUI界面:结合
tkinter或PyQt开发图形界面,支持文件夹选择、阈值设置。 - 性能优化:对大文件夹,可通过“按长度分组”减少不必要的相似度计算(长度差异大的文件相似度大概率低)。
- 算法升级:使用BERT等预训练模型生成文本向量,实现语义级相似度分析(需额外安装
transformers库)。
总结
通过这个项目,我们实践了文件IO、正则文本预处理、两种经典相似度算法的应用。编辑距离适合“精确重复”检测,余弦相似度适合“语义相似”分析。工具虽简单,但覆盖了文本处理的核心流程,是入门文件分析与相似度算法的绝佳实践。未来可结合更先进的NLP技术(如大模型向量),进一步提升相似性识别的准确性与鲁棒性。