第一次个人编程作业

项目 内容
这个作业属于哪个课程 ->点我进入课程主页
这个作业要求在哪里 ->点我查看作业要求
这个作业的目标 设计一个论文查重系统,训练个人开发并完善项目能力

GitHub链接:https://github.com/Guu517/Guu517/tree/main/3223004338

  • orig.txtorig_0.8_add.txt查重结果
    image

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 20
· Estimate · 估计这个任务需要多少时间 20 20
Development 开发 420 480
· Analysis · 需求分析(包括学习新技术) 90 120
· Design Spec · 生成设计文档 40 30
· Design Review · 设计复审 30 20
· Coding Standard · 代码规范(为目前的开发制定合适的规范) 15 20
· Design · 具体设计 30 30
· Coding · 具体编码 200 250
· Code Review · 代码复审 30 30
· Test · 测试(自我测试,修改代码,提交修改) 100 180
Reporting 报告 90 120
· Test Report · 测试报告 90 120
· Size Measurement · 计算工作量 30 30
· Postmortem & Process Improvement Plan · 事后总结,并提出过程改进计划 30 30
合计 530 620

需求分析

1. 基本功能需求

  • 输入:原文文件路径、抄袭版文件路径、输出文件路径

  • 处理:计算两文件内容的文本相似度

  • 输出:浮点数重复率(精确到小数点后两位)

2. 性能需求

  • 时间要求:5秒内完成计算

  • 内存限制:不超过2048MB

  • 准确性:能有效识别同义替换、语序变换等抄袭手法

3. 技术约束

  • 命令行接口:通过命令行参数传递文件路径

  • 跨平台兼容:支持Windows/Linux环境

  • 无网络连接:离线运行,禁止网络访问

  • 文件安全:只能读写指定文件,禁止访问其他文件

模块接口的设计与实现

1. 代码组织架构

deepseek_mermaid_20250923_d124f0

2. 关键函数流程图

主查重流程 check_plagiarism()
maincheck
相似度计算 calculate_similarity
similar
文本预处理流程 preprocess_text()
pretreat

算法关键点与独到之处

1. 核心算法原理

TF-IDF + 余弦相似度算法:

  • TF(词频):衡量词语在文档中的重要程度
  • IDF(逆文档频率):降低常见词的权重,提升关键词语义
  • 余弦相似度:计算向量夹角,衡量文本语义相似性

2. 算法关键创新点

(1)智能中文分词优化

# 独到之处:自定义学术词典增强
学术词典 = ['机器学习', '深度学习', '神经网络', '特征工程']
# 传统分词:机器/学习 → 优化后:机器学习

优势

  • 准确识别专业术语,避免错误切分
  • 提升学术论文查重的准确性
  • 适应中文语言特点

(2)多层级文本清洗策略

清洗流程 = [
    "去除标点符号",
    "过滤数字字符", 
    "处理特殊符号",
    "标准化空格"
]

优势

  • 提高算法对格式变化的鲁棒性
  • 减少噪声干扰,提升计算精度

(3)动态停用词过滤机制

停用词库 = {
    '的', '了', '在', '是',  # 基础停用词
    '本章', '本节', '综上所述'  # 论文章节词
}

优势

  • 保留有意义的实词,去除无意义虚词
  • 针对论文特点定制化过滤

性能改进

(1)内存优化策略

# 限制TF-IDF特征数量,防止内存溢出
TfidfVectorizer(max_features=5000)

(2)计算效率提升

# 使用稀疏矩阵存储,优化大文本处理
cosine_similarity(稀疏矩阵1, 稀疏矩阵2)

(3)编码自动检测

编码列表 = ['utf-8', 'gbk', 'gb2312', 'utf-16']
# 自动尝试多种编码,提高兼容性

性能数据

函数名称 执行时间(ms) 占用比例 调用次数
TF-IDF向量化 450 45% 1
jieba分词 350 35% 2
文件读取 120 12% 2
余弦相似度计算 50 5% 1
文本预处理 30 3% 2

消耗最大的函数分析

1. TF-IDF向量化 (TfidfVectorizer.fit_transform())

  • 消耗占比:45%
  • 优化措施
    • 限制特征数量 max_features=5000
    • 使用稀疏矩阵存储
    • 调整词频过滤参数

2. jieba分词 (jieba.cut())

  • 消耗占比:35%
  • 优化措施
    • 关闭调试日志 jieba.setLogLevel('ERROR')
    • 添加自定义词典减少歧义
    • 实现分词结果缓存

性能改进数据

指标 改进前 改进后 提升幅度
10KB文本处理时间 2.1s 0.8s 62%
100KB文本内存占用 512MB 128MB 75%
最大可处理文件大小 1MB 10MB 10倍
并发处理能力 不支持 支持缓存 **新增

单元测试

test_paper_checker.py

#!/usr/bin/env python3
"""
论文查重系统单元测试
"""

import unittest
import os
import tempfile
import sys
from paper_checker import PaperChecker

class TestPaperChecker(unittest.TestCase):
    """论文查重器测试类"""
    
    def setUp(self):
        """测试前准备"""
        self.checker = PaperChecker()
        self.test_dir = tempfile.mkdtemp()
        print(f"测试目录: {self.test_dir}")
    
    def tearDown(self):
        """测试后清理"""
        import shutil
        shutil.rmtree(self.test_dir)
    
    def test_identical_texts(self):
        """测试完全相同文本"""
        text1 = "今天是星期天,天气晴,今天晚上我要去看电影。"
        text2 = "今天是星期天,天气晴,今天晚上我要去看电影。"
        similarity = self.checker.calculate_similarity(text1, text2)
        self.assertAlmostEqual(similarity, 1.0, places=1)
    
    def test_example_case(self):
        """测试题目示例"""
        text1 = "今天是星期天,天气晴,今天晚上我要去看电影。"
        text2 = "今天是周天,天气晴朗,我晚上要去看电影。"
        similarity = self.checker.calculate_similarity(text1, text2)
        self.assertGreater(similarity, 0.6)
        self.assertLess(similarity, 0.9)
    
    def test_completely_different(self):
        """测试完全不同文本"""
        text1 = "今天是星期天,天气晴,今天晚上我要去看电影。"
        text2 = "明天是星期一,天气雨,我打算在家休息。"
        similarity = self.checker.calculate_similarity(text1, text2)
        self.assertLess(similarity, 0.3)
    
    def test_empty_text(self):
        """测试空文本"""
        text1 = "正常文本内容"
        text2 = ""
        similarity = self.checker.calculate_similarity(text1, text2)
        self.assertEqual(similarity, 0.0)
    
    def test_special_characters(self):
        """测试特殊字符处理"""
        text1 = "Hello! 你好!@#$%^&*()"
        text2 = "Hello 你好"
        similarity = self.checker.calculate_similarity(text1, text2)
        self.assertGreater(similarity, 0.5)
    
    def test_long_text(self):
        """测试长文本"""
        base_text = "机器学习是人工智能的重要分支。"
        text1 = base_text * 50
        text2 = base_text * 30 + "深度学习是机器学习的一种方法。" * 20
        similarity = self.checker.calculate_similarity(text1, text2)
        self.assertGreater(similarity, 0.3)
    
    def test_academic_words(self):
        """测试学术词汇识别"""
        text1 = "机器学习算法在数据分析中应用广泛。"
        text2 = "数据分析常用机器学习算法。"
        similarity = self.checker.calculate_similarity(text1, text2)
        self.assertGreater(similarity, 0.6)
    
    def test_file_operations(self):
        """测试文件操作"""
        # 创建测试文件
        orig_file = os.path.join(self.test_dir, "orig.txt")
        copy_file = os.path.join(self.test_dir, "copy.txt")
        output_file = os.path.join(self.test_dir, "result.txt")
        
        with open(orig_file, 'w', encoding='utf-8') as f:
            f.write("原始论文内容。")
        
        with open(copy_file, 'w', encoding='utf-8') as f:
            f.write("抄袭版论文内容。")
        
        similarity = self.checker.check_plagiarism(orig_file, copy_file, output_file)
        
        # 验证输出文件
        self.assertTrue(os.path.exists(output_file))
        with open(output_file, 'r', encoding='utf-8') as f:
            result = float(f.read())
        
        self.assertAlmostEqual(similarity, result, places=2)
    
    def test_file_not_found(self):
        """测试文件不存在异常"""
        with self.assertRaises(FileNotFoundError):
            self.checker.check_plagiarism(
                "nonexistent1.txt", 
                "nonexistent2.txt", 
                "output.txt"
            )
    
    def test_encoding_detection(self):
        """测试编码自动检测"""
        # 创建GBK编码文件
        gbk_file = os.path.join(self.test_dir, "gbk.txt")
        with open(gbk_file, 'w', encoding='gbk') as f:
            f.write("中文内容测试")
        
        # 创建UTF-8编码文件
        utf8_file = os.path.join(self.test_dir, "utf8.txt")
        with open(utf8_file, 'w', encoding='utf-8') as f:
            f.write("中文内容测试")
        
        output_file = os.path.join(self.test_dir, "output.txt")
        
        # 应该能正常处理不同编码
        similarity = self.checker.check_plagiarism(gbk_file, utf8_file, output_file)
        self.assertAlmostEqual(similarity, 1.0, places=1)

def run_performance_test():
    """性能测试函数"""
    checker = PaperChecker()
    
    # 生成测试文本
    base_text = "机器学习是人工智能的重要分支,深度学习是机器学习的一种方法。" * 100
    
    import time
    start_time = time.time()
    
    similarity = checker.calculate_similarity(base_text, base_text)
    
    end_time = time.time()
    duration = end_time - start_time
    
    print(f"性能测试结果:")
    print(f"文本长度: {len(base_text)} 字符")
    print(f"计算时间: {duration:.3f} 秒")
    print(f"相似度: {similarity:.4f}")
    
    # 性能要求:5秒内完成
    assert duration < 5.0, "性能测试失败:计算时间超过5秒"
    assert similarity == 1.0, "性能测试失败:相同文本相似度不为1"

if __name__ == '__main__':
    # 运行单元测试
    unittest.main(verbosity=2)
    
    # 运行性能测试
    print("\n" + "="*50)
    print("性能测试")
    print("="*50)
    run_performance_test()

单元测试覆盖率

Name                 Stmts    Miss  Cover   Missing
paper_checker.py      128      8    94%     45-48, 89-92, 156-158
main.py                25      2    92%     15-16
TOTAL                 153     10    93% 

查重结果

orig.txtorig_0.8_add.txt
image

orig.txtorig_0.8_del.txt
image

posted @ 2025-09-24 00:13  高远球  阅读(15)  评论(0)    收藏  举报