这个作业属于哪个课程 | 班级的链接 |
---|---|
这个作业要求在哪里 | 作业要求的链接 |
这个作业的目标 | 初步接触单元测试 对我个人而言学习了一些Python |
GitHub仓库链接(作业存放于学号文件)
1、作业要求
题目:论文查重
描述如下:
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。
原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:
从命令行参数给出:论文原文的文件的绝对路径。
从命令行参数给出:抄袭版论文的文件的绝对路径。
从命令行参数给出:输出的答案文件的绝对路径。
我们提供一份样例,课堂上下发,上传到班级群,使用方法是:orig.txt是原文,其他orig_add.txt等均为抄袭版论文。
注意:答案文件中输出的答案为浮点型,精确到小数点后两位
2.思路
根据相关资料调查得出以下步骤
1.根据 jieba 库进行分词
2.统计每个词出现的次数,
本来想使用C++编写该程序,不过因为 C++ 中文分词的第三方库比较难找,所以选择了 Python
3.将数据代入夹角余弦定理
关于算法我主要参考的是这个文章(http://www.ruanyifeng.com/blog/2013/03/cosine_similarity.html)
身边还有使用 SimHash 算法的同学 也还有其他算法可以选择
Jieba.cut接口功能展示
精准模式
代码:
import jieba
seg_list = jieba.cut("今天一定要提交作业") #精准模式
print(", ".join(seg_list))
输出结果
今天,一定,要,提交,作业
本次作业用精准模式即可
3.代码实现
def read_file(path1,path2,path3):
file_words = {}
ignore_list = [u'的',u'了',u'和',u'呢',u'啊',u'哦',u'恩',u'嗯',u'吧'];
accepted_chars = re.compile(r"[\u4E00-\u9FA5]+")
file_object = open(path1,encoding='utf-8')
try:
all_the_text = file_object.read()
seg_list = jb.cut(all_the_text, cut_all=True)
for s in seg_list:
if accepted_chars.match(s) and s not in ignore_list:
if s not in file_words.keys():
file_words[s] = [1,0]
else:
file_words[s][0] += 1
finally:
file_object.close()
file_object2 = open(path2,encoding='utf-8')
try:
all_the_text = file_object2.read()
seg_list = jb.cut(all_the_text, cut_all=True)
for s in seg_list:
if accepted_chars.match(s) and s not in ignore_list:
if s not in file_words.keys():
file_words[s] = [0,1]
else:
file_words[s][1] += 1
finally:
file_object2.close()
sum_2 = 0
sum_file1 = 0
sum_file2 = 0
for word in file_words.values():
sum_2 += word[0]*word[1]
sum_file1 += word[0]**2
sum_file2 += word[1]**2
rate = sum_2/(sqrt(sum_file1*sum_file2))
f = open(path3, 'w', encoding="utf-8")
f.write("文章相似度: %.2f" % rate)
f.close()
return rate
read_file('D:\PythonCode\Code1\orig.txt','D:\PythonCode\Code1\orig_0.8_add.txt','D:\PythonCode\Code1\JG.txt')
运行:
将原文件orig.txt与修改文件orig_0.8_add.txt 作比较
文件路径:
运行成功:
结果保存至输出文件:
代码覆盖率:
性能分析
调用次数
代码优化:jieba功能已经很强大,所以从别处入手
目前只加入了部分语气屏蔽词,但是还有些不太重要的词没有屏蔽。比如没有,有这类非名词,如果可以做到屏蔽不重要词,可以让相似度更高
4.单元测试
需要用到python的unittest 具体参考Python Unit_test
根据作业要求 以及需要进行单元测试 我们加点代码
def main_test():
result=round(read_file('D:\PythonCode\Code1\orig.txt','D:\PythonCode\Code1\orig_0.8_dis_15.txt','D:\PythonCode\Code1\JG.txt'),2)
return result
if __name__ == '__main__':
main_test()
单元测试文件
import unittest
from main import main_test
class MyTestCase(unittest.TestCase):
def test_something(self):
self.assertEqual(0.98,main_test()) #前面是预期 后面是实际运行的
if __name__ == '__main__':
unittest.main()
测试1:
预期结果0.98
测试成功
测试2:
改一下预期结果 改为0.97 对比文件不变
def main_test():
result=round(read_file('D:\PythonCode\Code1\orig.txt','D:\PythonCode\Code1\orig_0.8_dis_15.txt','D:\PythonCode\Code1\JG.txt'),2)
size1 = os.path.getsize('D:\PythonCode\Code1\.txt')
size2 = os.path.getsize('D:\PythonCode\Code1\orig_0.8_dis_15.txt')
if size1 == 0:
print('原文件是空的')
return 0
elif size2 == 0:
print('对比文件为空')
return 0
else:
result=round(read_file('D:\PythonCode\Code1\orig.txt','D:\PythonCode\Code1\orig_0.8_dis_15.txt','D:\PythonCode\Code1\JG.txt'),2)
return result
if __name__ == '__main__':
main_test()
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 120 | 80 |
Estimate | 估计这个任务需要多少时间 | ||
Development | 开发 | 500 | 600 |
Analysis | 需求分析 (包括学习新技术) | 300 | 240 |
Design Spec | 生成设计文档 | 30 | 20 |
Design Review | 设计复审 | 10 | |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | ||
Design | 具体设计 | 5 | |
Coding | 具体编码 | 150 | |
Code Review | 代码复审 | ||
Test | 测试(自我测试,修改代码,提交修改) | 40 | |
Reporting | 报告 | ||
Test Repor | 测试报告 | ||
Size Measurement | 计算工作量 | ||
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | ||
总计 | 1365 | 1180 |