第一次个人编程作业
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/gdgy/CSGrade22-34 |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13229 |
这个作业的目标 | 完成论文查重项目,了解项目开发工程流程,学会使用PSP表格,性能分析以及单元测试等 |
一、Github 项目地址
https://github.com/Memset-Lee/Memset-Lee/tree/main/3122004695
二、需求
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。
原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:
从命令行参数给出:论文原文的文件的绝对路径。
从命令行参数给出:抄袭版论文的文件的绝对路径。
从命令行参数给出:输出的答案文件的绝对路径。
注意:答案文件中输出的答案为浮点型,精确到小数点后两位。
三、PSP
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 80 |
Estimate | 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | 180 | 210 |
Analysis | 需求分析 (包括学习新技术) | 30 | 60 |
Design Spec | 生成设计文档 | 30 | 30 |
Design Review | 设计复审 | 20 | 30 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 30 |
Design | 具体设计 | 60 | 40 |
Coding | 具体编码 | 120 | 90 |
Code Review | 代码复审 | 20 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 120 |
Reporting | 报告 | 30 | 20 |
Test Repor | 测试报告 | 30 | 20 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 20 |
合计 | 710 | 790 |
四、计算模块接口的设计与实现过程
代码总共包含get_arguments
、read_file
、write_file
、segment_text
、get_ans
、check_file_path
、check_empty_file
七个函数:
get_arguments
:获取命令行参数
read_file
:读取文件内容
write_file
:写入文件内容
segment_text
:对文本进行分词
get_ans
:构建TF-IDF特征矩阵并计算相似度
check_file_path
:判断路径是否正确
check_empty_file
:判断文件是否为空
代码逻辑和函数关系:
首先通过get_arguments
获取命令行参数,然后通过check_file_path
判断输入的路径是否正确,接着通过read_file
将这些路径的文件内容读取出来,再通过check_empty_file
判断文件是否为空,然后通过segment_text
利用jieba库对文本内容进行分词,再通过get_ans
根据分词后的结果构建TF-IDF特征矩阵并计算相似度,最后打印相似度并通过write_file
保存到答案文本中。
关键之处和独到之处:
代码的关键之处在于对文本内容进行分词、构建TF-IDF特征矩阵以及计算相似度。在进行这些操作时,我选择调用了jieba库和scikit-learn库,因此代码逻辑会清晰明了许多,可读性也大大提高。
因为代码流程十分简单,并且我也在代码中写了许多注释,所以在这里就不给出流程图了,相信只要看过代码都能马上理解。
五、计算模块接口部分的性能改进
首先使用PyCharm提供了代码静态审查功能,消除了代码的所以警告:
然后使用第三方库line_profiler,对代码进行性能分析,结果如下图所示:
分析:
从结果中可以知道segment_text
函数所消耗的时间是最多的,比其他所有函数所消耗的时间的总和还多。该函数用于对文本进行分词并去除标点符号,其中调用jieba库进行分词将近占了该函数所消耗时间的100%。因为这是调用第三方库,并且调用jieba库进行分词已经十分高效了,所以暂时没有什么地方可以进一步提高代码性能。
六、计算模块部分单元测试展示
以下是我对segment_text
函数所编写的单元测试代码:
构造测试数据的主要思路是要尽可能多的包含不同的符号,如中文、数字、标点符号等等。该单元测试包含了5组数据,能够全面的测试出segment_text
函数的功能以及函数的设计是否有漏洞。
import re
import jieba
import unittest
def segment_text(text): # 对文本进行分词
text_without_punctuation = re.sub(r'[^\w\s]', '', text) # 去除标点符号
segment_list = jieba.cut(text_without_punctuation, cut_all=False)
text_with_spaces = " ".join(segment_list) # 用空格分词
return text_with_spaces
class TestSegmentText(unittest.TestCase):
def test_1(self):
self.assertEqual(segment_text('你好,我是计科三班的一名学生。'), '你好 我 是 计科 三班 的 一名 学生')
def test_2(self):
self.assertEqual(segment_text('你好我是计科三班的一名学生'), '你好 我 是 计科 三班 的 一名 学生')
def test_3(self):
self.assertEqual(segment_text('123,456,789'), '123456789')
def test_4(self):
self.assertEqual(segment_text('123456789'), '123456789')
def test_5(self):
self.assertEqual(segment_text(',,。。!!'), '')
if __name__ == '__main__':
unittest.main()
# cd C:\Users\26973\Desktop\Tools\Python Code\SEPersonalProject
# coverage run test_segment_text.py
# coverage report
以下是测试结果:
可以看出,五组数据全部通过,并且测试覆盖率达到100%,说明segment_text
函数基本没有漏洞。
其余函数的单元测试,我就不再这里一一展示了,我将所有测试代码都上传到了 Github,需要的可以上Github找。我在本地测试时,全部函数都通过了单元测试的所有数据,并且测试覆盖率达到100%。
七、计算模块部分异常处理说明
在项目中,我设计了路径不存在、文件为空、输入参数过少三个异常处理。
路径不存在:
目标:当输入的路径不存在时,会在cmd窗口中显示出哪些路径是不存在的。
如下图所示,第二和第三个路径是不存在的,它就会在cmd中打印出第二和第三个路径。
通过以下代码来具体实现该功能:
def check_file_path(file_paths): # 判断路径是否正确
flag = 0
for file_path in file_paths:
if not os.path.exists(file_path):
print(f'Path does not exist: {file_path}')
flag = 1
if flag == 1:
sys.exit()
文件为空:
目标:当原文文件或者抄袭文件为空时,会在cmd窗口显示出哪些文件是空的。
如下图所示,抄袭文件是空的,它就会在cmd中显示抄袭文件是空的。
通过以下代码来具体实现该功能:
def check_empty_file(text1, text2): # 判断文件是否为空
flag = 0
if not text1:
print('The original text file is empty.')
flag = 1
if not text2:
print('The plagiarized text file is empty.')
flag = 1
if flag == 1:
sys.exit()
输入参数过少:
目标:当输入的参数过少时,会在cmd窗口中显示缺少了哪些文件。
如下图所示,只输入了原文文件的路径,他就会在cmd中显示缺少抄袭文件和答案文件。
通过系统报错来具体实现该功能
posted on 2024-09-11 21:41 Memset_Lee 阅读(20) 评论(0) 编辑 收藏 举报