软工作业2-个人项目(论文查重)
作业
| 这个作业属于哪个课程 | 软件工程 |
|---|---|
| 这个作业的要求在哪里 | 作业要求 |
| 这个作业的目标 | 完成一个论文查重的个人项目 |
| github链接 | Github链接 |
PSP表格
| PSP2.1 | Personal Software ProcessStages | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| Planning | 计划 | 30 | 44 |
| Estimate | 估计这个任务需要多少时间 | 300 | 450 |
| Development | 开发 | 120 | 150 |
| Analysis | 需求分析(包括学习新技术) | 40 | 60 |
| Design Spec | 生成设计文档 | 30 | 45 |
| Design Review | 设计复审 | 20 | 25 |
| Coding Standard | 代码规范(为目前的开发制定合适的规范) | 15 | 15 |
| Design | 具体设计 | 60 | 80 |
| Coding | 具体编码 | 120 | 180 |
| Code Review | 代码复审 | 15 | 10 |
| Test | 测试(自我测试,修改代码,提交修改) | 30 | 40 |
| Reporting | 报告 | 80 | 95 |
| Test Repor | 测试报告 | 15 | 15 |
| Size Measurement | 计算工作量 | 5 | 5 |
| Postmortem & Process Improvement Plan | 事后总结,并提出过程改进计划 | 10 | 10 |
| 合计 | 590 | 774 |
问题要求
题目:论文查重
描述如下:
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。
- 原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
- 抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:
- 从命令行参数给出:论文原文的文件的绝对路径。
- 从命令行参数给出:抄袭版论文的文件的绝对路径。
- 从命令行参数给出:输出的答案文件的绝对路径。
我们提供一份样例,课堂上下发,上传到班级群,使用方法是:orig.txt是原文, 其他orig_add.txt等均为抄袭版论文。
注意:答案文件中输出的答案为浮点型,精确到小数点后两位
模块设计
流程图

关键代码
将html转换成txt
def html_to_text(html): # 用于将HTML转换为纯文本的函数
soup = BeautifulSoup(html, 'html.parser') # 使用BeautifulSoup解析HTML
text = soup.get_text() # 获取纯文本内容
return text # 返回纯文本
分词过滤
def distinguish(text):
# 使用正则表达式将HTML标签从文本中删除
text_without_html = re.sub(r'<[^>]+>', '', text)
# 使用正则表达式将英文单词与标点符号之间的空格替换为特殊字符
text_without_html = re.sub(r'([a-zA-Z0-9]+)([,。、!?,.!?\n])', r'\1\2', text_without_html)
# 使用jieba库进行中文分词,同时保留英文单词
words = list(jieba.cut(text_without_html, cut_all=False, HMM=True))
# 恢复特殊字符为原始空格
result = [word.replace('_', ' ') if '_' in word else word for word in words if re.match(u"[a-zA-Z0-9\u4e00-\u9fa5]", word)]
return result # 返回分词结果
计算文本相似度
# 计算文本相似度的函数
def calc_similarity(text1, text2):
# 将输入的文本转换为字符串,如果它们已经是列表
if isinstance(text1, list):
text1 = ' '.join(text1)
if isinstance(text2, list):
text2 = ' '.join(text2)
# 将两个文本拆分为词语列表
texts = [text1.split(), text2.split()]
dictionary = corpora.Dictionary(texts) # 创建文本词典
corpus = [dictionary.doc2bow(text) for text in texts] # 将文本转换为词袋模型
similarity = similarities.Similarity('-Similarity-index', corpus, num_features=len(dictionary)) # 计算相似度
test_corpus_1 = dictionary.doc2bow(text1.split()) # 将第一个文本转换为词袋模型
cosine_sim = similarity[test_corpus_1][1] # 计算余弦相似度
return float(cosine_sim) # 返回相似度值作为浮点数
项目结构以及覆盖率
覆盖率较低部分为处理异常部分

调用时间占比

性能分析图
使用pycharm自带的性能分析功能生成性能分析图如下:

主要测试
出现不存在文件或文件路径
def test_non_existing_file(self):
# 模拟不存在的文件
# 模拟一个不存在的文件路径
mock_path = 'non_existent.txt'
result = get_file_contents(mock_path)
self.assertIsNone(result)

相似度计算
def test_similarity_calculation(self):
# 测试相似度计算是否正确
# 模拟两个文本以进行相似度计算
text1 = "This is a sample text for testing."
text2 = "This is a test text for sample."
similarity_score = calc_similarity(text1, text2)
# 更新期望值,保留更多小数点位数
expected_similarity = 0.7143
self.assertAlmostEqual(similarity_score, expected_similarity, places=4)
文件为空
def test_empty_content(self):
# 测试处理空内容的情况
# 模拟空内容
empty_content = ''
text = distinguish(empty_content)
self.assertEqual(text, [])
分词过滤
def test_distinguish(self):
# 编写测试用例以测试distinguish函数
# 模拟包含不同类型文本的测试用例
# 1. 测试包含中英文混合的文本
text = "这是一个示例文本。This is an example."
expected_tokens = ["这是", "一个", "示例", "文本", "This", "is", "an", "example"]
actual_tokens = distinguish(text)
self.assertEqual(actual_tokens, expected_tokens)
# 2. 测试处理空文本的情况
empty_text = ""
empty_tokens = distinguish(empty_text)
self.assertEqual(empty_tokens, [])
# 3. 测试处理只包含标点符号的情况
punctuation_text = ",。!?,.!?"
punctuation_tokens = distinguish(punctuation_text)
self.assertEqual(punctuation_tokens, [])
# 4. 测试处理只包含空格的情况
space_text = " "
space_tokens = distinguish(space_text)
self.assertEqual(space_tokens, [])
# 5. 测试处理只包含英文单词的情况
english_text = "This is a test sentence."
english_tokens = distinguish(english_text)
self.assertEqual(english_tokens, ["This", "is", "a", "test", "sentence"])
# 6. 测试处理只包含中文文本的情况
chinese_text = "这是一句测试文本。"
chinese_tokens = distinguish(chinese_text)
self.assertEqual(chinese_tokens, ["这是", "一句", "测试", "文本"])
# 7. 测试处理包含HTML标签的情况
html_text = "<p>This is <b>bold</b> and <i>italic</i> text.</p>"
html_tokens = distinguish(html_text)
expected_html_tokens = ["This", "is", "bold", "and", "italic", "text"]
self.assertEqual(html_tokens, expected_html_tokens)
# 8. 再次测试处理包含HTML标签的情况,以确保没有副作用
html_text = "<p>This is <b>bold</b> and <i>italic</i> text.</p>"
html_tokens = distinguish(html_text)
self.assertEqual(html_tokens, expected_html_tokens)
浙公网安备 33010602011771号