论文查重算法作业
课程 | 软件工程2024-双学位 (广东工业大学) |
---|---|
标题 | 个人项目作业-论文查重 |
需求 | 设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。 |
---手动分割线---
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 90 |
-Estimate | · 估计这个任务需要多少时间 | 480 | 700 |
Development | 开发 | 50 | 200 |
-Analysis | · 需求分析 (包括学习新技术) | 300 | 300 |
-Design Spec | · 生成设计文档 | 20 | 30 |
-Design Review | · 设计复审 | 15 | 10 |
-Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 15 | 15 |
-Design | · 具体设计 | 60 | 90 |
-Coding | · 具体编码 | 60 | 180 |
-Code Review | · 代码复审 | 30 | 90 |
-Test | · 测试(自我测试,修改代码,提交修改) | 30 | 95 |
Reporting | 报告 | 30 | 45 |
-Test Report | · 测试报告 | 15 | 15 |
-Size Measurement | · 计算工作量 | 15 | 15 |
-Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
Total | · 合计 | 660 | 1105 |
1. 计算模块接口的设计与实现过程
一开始不知怎么做,选择哪种语言,在这次作业列表中了解到了LCS算法和余弦算法,以及通过Python自带库difflib来实现文本比对功能,最后选择了Python,感觉比较简单和方便。
1.1 构思与设计
首先定义一个计算模块,在主函数中会用到这个计算模块来计算相似度;然后再设计一个函数来接收从命令行传入的参数,这里可以加入对参数的异常判定;然后读取文件并且存入某个地址;在主函数中跟踪上述地址找到文件数据,并且调用计算模块,最后打印结果。
1.2 实现过程
-
在计算模块,也就是调用difflib库的SequenceMatcher模块来计算,它是用于对比文本差异并且给出一个大概的相似度的,对于这次作业的目标任务而言相当合适
def Similarity_Rate(file1,file2): return difflib.SequenceMatcher(None,file1,file2).ratio()
-
接收命令行参数时,用一个变量打包获取一系列系统变量的值,不直接使用系统变量主要是为了使这段代码更加直观,下面的注释也是为了同样的目的
file_Adrs=sys.argv
-
在读取文件数据部分加入了异常判定,判定成功则用固定格式获取文本
try: with open(sys.argv[1], 'r', encoding='utf-8') as f: t1=f.read() with open(sys.argv[2], 'r', encoding='utf-8') as f: t2=f.read() except: if len(file_Adrs) != 4: print("Please enter \"你的文件名 *原文件 *相似文件 *报告文件(文件路径)\"") sys.exit(1) else: print("Please check the state of your files") sys.exit(2)
2. 计算模块接口部分的性能改进
difflib库的计算方法已经固定,所以从其它方面入手,比如减少调用参数,文本预处理,相对来讲后者的影响大一些,适合这里的方法有停用词过滤,但是在此之前,还要进行分词处理,因为太难了不想做,所以可以在SequenceMatcher
模块里调整参数,比如autojunk
和isjunk
,效果会差不少,但是可以省不少开发时间
3. 计算模块接口部分的性能改进
因为系统原因,实时,精确地监测性能有点难度,可以确定的是性能指标并不优秀,在面对长文本时处理时间和CPU占用都会有比较大的提升,因此在文件中加入时间计算库time
,并且在文件末尾打印
4. 计算模块部分单元测试展示
见代码仓,测试用例较少
5. 计算模块部分异常处理说明
代码详见上文,没有单独设计异常处理模块,合入了读取文件并获取内容的模块中,try...except
语句的作用是先尝试执行代码片段,若失败再进行原因排查,减少代码量的同时还可以稍微地减轻运算量,成功执行就不做判定了,但是这种构建法只适用于变量和参数不多的小型项目,因为一旦执行错误会引发一些不知名的参数,内存错误,在大型项目中这种异常会如链式反应一般传递开来