第一次个人项目作业

这个作业属于哪个课程 班级的链接
这个作业要求在哪里 作业要求的链接
这个作业的目标 设计论文查重算法并开发,用PSP表格记录
Github https://github.com/Altriaaaa/3119005433

实现思路

网上信息收集可以知道,实现论文查重有多重算法思路,本人使用余弦定理,当然欧式距离,海明距离也是可以的。

需要def的函数:open_file_read,cut,caculate_similarity,main

整体思路为:

首先通过open_file_read函数,把要原文和要查重的文章读入程序。过滤掉各种标点符号和换行,只匹配英文数字和汉字,生成字符串。得到的字符串用jieba库的lcut函数来分词,生成一个list。接着调用gensim,创建语料库,用doc2bow实现bow模型,计算两个向量的余弦相似度,即可得到两篇文章的相似度,最后把相似度写进answer文本里面。

接口分析

jieba.cut

可以兼容中文句子进行分词,此处用精确模式即可,详细功能见Github

import jieba

sent = "我是谭清允,我就读于广东工业大学"
print(jieba.lcut(sent))

# ['我', '是', '谭清允', ',', '我', '就读于', '广东', '工业', '大学']

re.match

因为文章里面有中文,英文,各种标点符号和换行符,所以要用re模块的match正则匹配换行符和标点符号。\W匹配除了字母,数字,下划线之外的字符,匹配到就替换为空。

import jieba
import re

sent = "我是谭清允,我就读。!‘于广东工业大学。,"
cut = jieba.lcut(sent)
res = []
for word in cut:
    if (re.match(u"[\W+]", word)):
        res.append(word)
    else:
        pass
print (res)

# [',', '。', '!', '‘', '。', ',']

gensim.dictionary.doc2bow

Doc2Bow是gensim中封装的一个方法,主要用于实现Bow模型。原理参考文章

首先给出两个简单的文本文档如下:

John likes to watch movies. Mary likes too.
John also likes to watch football games.

基于上述两个文档中出现的单词,构建如下一个词典 (dictionary):

{"John": 1, "likes": 2,"to": 3, "watch": 4, "movies": 5,"also": 6, "football": 7, "games": 8,"Mary": 9, "too": 10}

上面的词典中包含10个单词, 每个单词有唯一的索引, 那么每个文本我们可以使用一个10维的向量来表示。如下:

[1, 2, 1, 1, 1, 0, 0, 0, 1, 1]
[1, 1,1, 1, 0, 1, 1, 1, 0, 0]

该向量与原来文本中单词出现的顺序没有关系,而是词典中每个单词在文本中出现的频率。
也是通过余弦定理计算两个句子的相似度。

def caculate_similarity(cut_first_text, cut_second_text):
    texts = [cut_first_text, cut_second_text]
    # 创建语料库
    repository = gensim.corpora.Dictionary(texts)
    # doc2bow
    corpus = [repository.doc2bow(text) for text in texts]
        # num_features代表生成的向量的维数(根据词袋的大小来定)
    cosine_similarity = gensim.similarities.Similarity('-Similarity-index', corpus, num_features=len(repository))
    # 获取句子相似度
    testing_corpus = repository.doc2bow(cut_first_text)
    cosine_similarity = cosine_similarity[testing_corpus][1]
    return cosine_similarity

代码实现

代码部分

import re
import gensim
import jieba
import sys


# 打开文件并读取内容
def open_file_read(path):
    text = ''
    file = open(path, 'r', encoding='UTF-8')
    each_line = file.readline()
    while each_line:
        text += each_line
        each_line = file.readline()
    # 使用re模块的sub()实现正则匹配,替换标点符号为空
    # \W匹配除了字母,数字,下划线之外的字符
    final_text = re.sub('\W+', '', text).replace("_", '')
    file.close()
    return final_text


def cut(final_text):
    res = jieba.lcut(final_text)
    return res


def caculate_similarity(cut_first_text, cut_second_text):
    texts = [cut_first_text, cut_second_text]
    # 创建语料库
    repository = gensim.corpora.Dictionary(texts)
    # doc2bow
    corpus = [repository.doc2bow(text) for text in texts]
    # num_features代表生成的向量的维数(根据词袋的大小来定)
    cosine_similarity = gensim.similarities.Similarity('-Similarity-index', corpus, num_features=len(repository))
    # 获取句子相似度
    testing_corpus = repository.doc2bow(cut_first_text)
    cosine_similarity = cosine_similarity[testing_corpus][1]
    return cosine_similarity


def main():
    try:
        first_path = sys.argv[1]
        second_path = sys.argv[2]
        answer = sys.argv[3]

        first_text = open_file_read(first_path)
        second_text = open_file_read(second_path)

        cut_first_text = cut(first_text)
        cut_second_text = cut(second_text)

        cosine_similarity = caculate_similarity(cut_first_text, cut_second_text)

        print("cosine_similarity is %.2f" % cosine_similarity)
        answer_file = open(answer, 'w', encoding="utf-8")
        answer_file.write("cosine_similarity is %.2f" % cosine_similarity)
        answer_file.close()
    except Exception as e:
        print(e)
        exit("请使用命令行传参,格式如python main.py [原文文件] [抄袭版论文的文件] [答案文件]")

def test_main():
    first_path='C:\\Users\\84330\\Desktop\\3119005433-main\\测试文本2\\orig.txt'
    second_path='C:\\Users\\84330\\Desktop\\3119005433-main\\测试文本2\\orig_0.8_add.txt'
    first_text = open_file_read(first_path)
    second_text = open_file_read(second_path)
    cut_first_text = cut(first_text)
    cut_second_text = cut(second_text)
    cosine_similarity = caculate_similarity(cut_first_text, cut_second_text)
    cosine_similarity = round(cosine_similarity.item(), 2)
    return cosine_similarity

if __name__ == '__main__':
    main()

运行结果

image-20210919233702974

两篇文章相似度高达99%,可以实现查重任务的准确性。

单元测试

用到python的unittest单元测试框架

代码部分

import unittest
from main import *



class MyTestCase(unittest.TestCase):
    def testing(self):
        self.assertEqual(test_main(), 0.99)

if __name__ == '__main__':
    unittest.main()

运行结果

image-20210919231337684

可以看到相似度校验通过

性能分析

代码覆盖率

image-20210919235141135

main.py的代码覆盖率100%,达到要求。

except Exception as e:
    print(e)
    exit("请使用命令行传参,格式如python main.py [原文文件] [抄袭版论文的文件] [答案文件]")

耗费的时间

image-20210919233652644

符合题目5秒内给出答案,能完成查重任务。

异常处理

image-20210919233833814

如果没有用命令行传参,会显示错误信息并提示用命令行传参

PSP表格

*PSP2.1* *Personal Software Process Stages* *预估耗时(分钟)* *实际耗时(分钟)*
Planning 计划 30 30
· Estimate · 估计这个任务需要多少时间 30 30
Development 开发 410 490
· Analysis · 需求分析 (包括学习新技术) 120 150
· Design Spec · 生成设计文档 30 30
· Design Review · 设计复审 40 50
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 20
· Design · 具体设计 60 60
· Coding · 具体编码 100 150
· Code Review · 代码复审 30 30
· Test · 测试(自我测试,修改代码,提交修改) 30 60
Reporting 报告 30 30
· Test Repor · 测试报告 20 20
· Size Measurement · 计算工作量 10 10
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 30 40
· 合计 590 750
posted @ 2021-09-20 01:09  Altriaaaa  阅读(44)  评论(0编辑  收藏  举报