这个作业属于哪个课程 22计科12班
作业要求 作业
github链接 Github
作业目标 设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率

需求分析
题目:论文查重
描述如下:
设计一个论文查重算法,给出一个原文文件和一个在这份原文上经过了增删改的抄袭版论文的文件,在答案文件中输出其重复率。

PSP2.1 ersonal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 10 20
Estimate 估计这个任务需要多少时间 300 200
Development 开发 400 450
Analysis 需求分析 (包括学习新技术) 60 60
Design Spec 生成设计文档 60 60
Design Review 设计复审 60 60
Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 30
Design 具体设计 50 60
Coding 具体编码 30 40
Code Review 代码复审 60 40
Test 测试(自我测试,修改代码,提交修改) 10 20
Reporting 报告 20 30
Test Report 测试报告 30 30
Size Measurement 计算工作量 60 70
Reporting 事后总结, 并提出过程改进计划 30 30
合计 1210 1200

原文示例:今天是星期天,天气晴,今天晚上我要去看电影。
抄袭版示例:今天是周天,天气晴朗,我晚上要去看电影。
要求输入输出采用文件输入输出,规范如下:

从命令行参数给出:论文原文的文件的绝对路径。
从命令行参数给出:抄袭版论文的文件的绝对路径。
从命令行参数给出:输出的答案文件的绝对路径。
我们提供一份样例,课堂上下发,上传到班级群,使用方法是:orig.txt是原文,其他orig_add.txt等均为抄袭版论文。

注意:答案文件中输出的答案为浮点型,精确到小数点后两位

思路分析

可以基于字符串匹配算法比对两篇文章,使用动态规划算法实现,实现较为复杂
使用simHash算法 + 海明距离实现,将高维度特征向量降维,计算海明距离
采用余弦相似度算法,将文章分词后向量化,计算词频向量的夹角余弦值
本次作业项目采用的是第3种方法,通过求余弦相似度来计算文章重复率,实现论文查重

流程分析

使用文件I/O流加载两篇目标文章,读取文章内容
对文章内容进行分词,获得一个个基本分词,便于后续向量化降低维度
采用TFIDF算法来计算两篇文章内容的分词向量,映射在低维空间
计算文本向量的夹角余弦值,得到余弦相似度,并保存在指定文件

解释:

  • 处理文章内容函数file_handle
  • 内容分词函数segment
  • 向量化函数vector_transform
  • 计算余弦相似度函数calculate_cos_similarity
  • 保存结果到文件函数save_file

文件结构

为对程序功能进行较为全面的评估,采用单元测试的方式进行过功能检验,测试程序代码的健壮性,进行以下一共10个单元测试,从不同角度,不同函数进行测试分析

test_read_empty_file:测试读取空文件

测试读取空文件

def test_read_empty_file(self):
    orig_path = ""
    orig_add_path = "C:/Users/L/Desktop/3121005134/3121005134/resource/orig_0.8_add.txt"
    paperChecked.file_handle(orig_path, orig_add_path)

test_read_notExist_file:测试读取不存在的文件

测试读取不存在的文件

def test_read_notExist_file(self):
    orig_path = "C:/Users/L/Desktop/3121005134/3121005134/resource/orig_add.txt"
    orig_add_path = "C:/Users/L/Desktop/3121005134/3121005134/resource/orig_0.8_add.txt"
    paperChecked.file_handle(orig_path, orig_add_path)

test_filter_dot:测试读取的文件能否过滤标点符号

测试读取的文件能否过滤标点符号

def test_filter_dot(self):
    orig_path = "C:/Users/L/Desktop/3121005134/3121005134/resource/orig.txt"
    orig_add_path = "C:/Users/L/Desktop/3121005134/3121005134/resource/orig_0.8_add.txt"
    orig_file, orig_add_file = paperChecked.file_handle(orig_path, orig_add_path)
    print(orig_file, orig_add_file)

test_segment:测试文件内容分词效果

测试文件内容分词效果

def test_segment(self):
    orig_path = "C:/Users/L/Desktop/3121005134/3121005134/resource/orig.txt"
    orig_add_path = "C:/Users/L/Desktop/3121005134/3121005134/resource/orig_0.8_add.txt"
    orig_file, orig_add_file = paperChecked.file_handle(orig_path, orig_add_path)
    orig_string, orig_add_string = paperChecked.segment(orig_file, orig_add_file)
    print(orig_string, orig_add_string)

test_vectorize:测试分词向量化效果

测试分词向量化效果

def test_vectorize(self):
    orig_string = '今天 天气 很好 晴朗 舒适'
    orig_add_string = '今日 天气 非常好 晴 愉快'
    vector1, vector2 = paperChecked.vector_transform(orig_string, orig_add_string)
    print(vector1, vector2)

test_calculate_cos_similarity:测试余弦相似度计算

测试余弦相似度计算

def test_calculate_cos_similarity(self):
    vector1 = np.array([1, 2, 3, 4, 5, 6])
    vector2 = np.array([1, 2, 3, 4, 5, 6])
    similarity = paperChecked.calculate_cos_similarity(vector1, vector2)
    print(similarity)

test_save_file:测试输出结果到指定文件中

测试输出结果到指定文件中

def test_save_file(self):
    answer_path = "C:/Users/L/Desktop/3121005134/3121005134/resource/answer02.txt"
    result = 0.86748569623
    similarity = paperChecked.save_file(answer_path, result)
    print(similarity)

test_save_not_exist_file:测试输出结果到不存在文件中

测试输出结果到不存在文件中

def test_save_not_exist_file(self):
    answer_path = ""
    result = 0.86748569623
    similarity = paperChecked.save_file(answer_path, result)
    print(similarity)

test_result_not_float:测试输出的结果不是浮点型

测试输出的结果不是浮点型

def test_result_not_float(self):
    answer_path = "C:/Users/L/Desktop/3121005134/3121005134/resource/answer03.txt"
    answer = 2
    result = paperChecked.save_file(answer_path, answer)
    print(result)

test_paper_check:测试文章查重

测试文章查重

def test_paper_check(self):
    main.paper_check()test_result_not_float

性能分析

覆盖率测试

除测试异常代码外的代码覆盖率较高

运行结果

发现均能通过测试

异常处理

文件读取异常 FileNotFoundError
​ 在单元测试test_read_empty_filetest_read_notExist_filetest_save_not_exist_file都有体现

处理文件函数

def file_handle(path1, path2):
    try:
        # 读取文件内容
        with open(path1, 'r', encoding='utf-8') as orig_file, open(path2, 'r', encoding='utf-8') as orig_add_file:
            orig_file = orig_file.read()
            orig_add_file = orig_add_file.read()
    except FileNotFoundError:
        print("请输入正确的文件路径")
        return FileNotFoundError
    # 过滤文件内容的标点符号
    dot_str = "\n\r 、,。;:?‘’“”''""!《》,.;:?!<>"
    for char in dot_str:
       orig_file = orig_file.replace(char, '')
       orig_add_file = orig_add_file.replace(char, '')
    return orig_file, orig_add_file
结果值非浮点类型异常 ValueError
​ 在单元测试test_result_not_float体现
# 保存结果到文件中,保留两位小数
def save_file(answer_path, answer):
    try:
        if isinstance(answer, float):
            with open(answer_path, 'w') as answer_file:
                print('%.2f' % answer, file=answer_file)
            return round(answer, 2)
        else:
            raise ValueError
    except ValueError:
        print("结果必须是浮点型")
        return ValueError
    except FileNotFoundError:
        print("保存结果的文件不存在")
        return FileNotFoundError
posted on 2024-09-12 12:37  ppyandlzq  阅读(35)  评论(0编辑  收藏  举报