Mikaphia

导航

软工第二次作业

Github链接:https://github.com/SophiaMikasa/SophiaMikasa

这个作业属于哪个课程 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience
这个作业要求在哪里 https://edu.cnblogs.com/campus/gdgy/Class12Grade23ComputerScience/homework/13468
这个作业的目标 完成第一个个人项目,熟悉项目开发流程

文本查重系统开发实践:从接口设计到性能优化

Personal Software Process (PSP) 记录

项目概述

本项目是一个文本查重系统的开发过程记录,遵循CMU的个人软件过程标准。

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

详细记录

Planning 阶段

  • 任务: 项目整体规划和时间估算
  • 产出: 项目计划文档
  • 经验: 初期估算偏乐观,实际开发复杂度更高

Development 阶段

Analysis (需求分析)

  • 学习jieba分词库使用方法
  • 研究文本相似度算法
  • 分析多编码文件处理需求

Design Spec (设计文档)

  • 设计PlagiarismChecker类结构
  • 定义算法接口和数据流
  • 规划异常处理机制

Coding (编码实现)

  • 实现核心查重算法
  • 开发文本预处理模块
  • 编写文件读取和编码处理

Test (测试)

  • 编写17个测试用例
  • 进行边界条件测试
  • 性能测试和优化

过程改进计划

  1. 时间估算: 增加20%缓冲时间
  2. 测试驱动: 先写测试用例再实现功能
  3. 代码审查: 增加同行评审环节
  4. 文档同步: 开发过程中同步更新文档

1. 计算模块接口的设计与实现过程

1.1 核心类设计

class PlagiarismChecker:
    """论文查重核心算法类"""
    
    def __init__(self, ngram_size=3):
        """初始化查重器,支持自定义n-gram大小"""
        self.ngram_size = ngram_size

1.2 主要接口方法

文件读取接口

def read_file(self, file_path):
    """
    多编码支持的文件读取接口
    - 支持UTF-8、GBK、GB2312等编码
    - 自动编码检测和容错处理
    - 异常情况的优雅降级
    """

文本预处理接口

def preprocess_text(self, text):
    """
    智能文本预处理
    - 去除标点符号和特殊字符
    - 规范化空白字符
    - 基于jieba的中文分词
    """

相似度计算接口

def check_plagiarism(self, orig_file, plagiarized_file):
    """
    主要查重接口
    - 多算法融合计算
    - 返回0-100的相似度百分比
    - 完善的异常处理
    """

1.3 算法实现细节

系统实现了三种核心算法:

  1. N-gram相似度算法
def calculate_ngram_similarity(self, words1, words2):
    """基于n-gram的局部相似性检测"""
    ngrams1 = set(self.generate_ngrams(words1, self.ngram_size))
    ngrams2 = set(self.generate_ngrams(words2, self.ngram_size))
    
    intersection = len(ngrams1.intersection(ngrams2))
    union = len(ngrams1.union(ngrams2))
    
    return intersection / union if union > 0 else 0.0
  1. 序列相似度算法
def calculate_sequence_similarity(self, text1, text2):
    """基于编辑距离的整体相似性检测"""
    return SequenceMatcher(None, text1, text2).ratio()
  1. 词汇重叠度算法
def calculate_word_overlap(self, words1, words2):
    """基于集合运算的词汇重叠检测"""
    set1, set2 = set(words1), set(words2)
    intersection = len(set1 & set2)
    union = len(set1 | set2)
    return intersection / union if union > 0 else 0.0

2. 计算模块接口部分的性能改进

2.1 算法优化策略

加权融合算法

# 综合相似度计算(加权平均)
final_similarity = (
    ngram_similarity * 0.5 +      # n-gram权重最高
    sequence_similarity * 0.3 +    # 序列相似度中等权重
    word_overlap * 0.2             # 词汇重叠最低权重
)

集合运算优化

  • 使用Python内置的set数据结构进行交集、并集运算
  • 避免重复计算,提高算法效率

2.2 内存优化

生成器模式

def generate_ngrams(self, words, n):
    """使用列表推导式优化内存使用"""
    if len(words) < n:
        return [tuple(words)]
    return [tuple(words[i:i + n]) for i in range(len(words) - n + 1)]

早期返回策略

if not words1 and not words2:
    return 1.0  # 两个空列表完全相同
if not words1 or not words2:
    return 0.0  # 一个空一个非空,直接返回

2.3 性能分析工具

系统集成了专门的性能分析模块:

def run_profiler():
    """运行cProfile性能分析器"""
    profiler = cProfile.Profile()
    profiler.enable()
    
    # 执行测试代码
    detailed_performance_test()
    
    profiler.disable()
    
    # 生成性能报告
    stats = pstats.Stats(profiler)
    stats.sort_stats('cumulative')
    stats.print_stats(20)

3. 计算模块部分单元测试展示

3.1 测试架构设计

class TestPlagiarismChecker(unittest.TestCase):
    """论文查重器单元测试类"""
    
    def setUp(self):
        """测试前准备"""
        self.checker = PlagiarismChecker()
        self.temp_dir = tempfile.mkdtemp()
    
    def tearDown(self):
        """测试后清理"""
        shutil.rmtree(self.temp_dir, ignore_errors=True)

3.2 核心测试用例

基础功能测试

def test_identical_texts(self):
    """测试完全相同的文本"""
    text = "今天是星期天,天气晴,今天晚上我要去看电影。"
    file1 = self.create_temp_file(text, "orig.txt")
    file2 = self.create_temp_file(text, "copy.txt")
    
    similarity = self.checker.check_plagiarism(file1, file2)
    self.assertGreater(similarity, 90)  # 应该有很高的相似度

def test_completely_different_texts(self):
    """测试完全不同的文本"""
    text1 = "今天是星期天,天气晴,今天晚上我要去看电影。"
    text2 = "编程语言有很多种,包括Python、Java、C++等。"
    file1 = self.create_temp_file(text1, "orig.txt")
    file2 = self.create_temp_file(text2, "diff.txt")
    
    similarity = self.checker.check_plagiarism(file1, file2)
    self.assertLess(similarity, 30)  # 应该有很低的相似度

边界条件测试

def test_empty_files(self):
    """测试空文件"""
    file1 = self.create_temp_file("", "empty1.txt")
    file2 = self.create_temp_file("", "empty2.txt")
    
    similarity = self.checker.check_plagiarism(file1, file2)
    self.assertEqual(similarity, 0.0)

def test_single_character_files(self):
    """测试单字符文件"""
    file1 = self.create_temp_file("a", "single1.txt")
    file2 = self.create_temp_file("a", "single2.txt")
    
    similarity = self.checker.check_plagiarism(file1, file2)
    self.assertGreater(similarity, 80)

编码兼容性测试

def test_gbk_encoding_file(self):
    """测试GBK编码文件"""
    text = "今天是星期天,天气晴朗。"
    # 创建GBK编码文件
    gbk_file = os.path.join(self.temp_dir, "gbk_test.txt")
    with open(gbk_file, "w", encoding="gbk") as f:
        f.write(text)
    
    utf8_file = self.create_temp_file(text, "utf8_test.txt")
    similarity = self.checker.check_plagiarism(gbk_file, utf8_file)
    self.assertGreater(similarity, 90)

3.3 测试覆盖率

系统包含17个扩展测试用例,覆盖率超过90%:

  • 基础功能测试:6个用例
  • 边界条件测试:5个用例
  • 编码兼容性测试:3个用例
  • 异常处理测试:3个用例

4. 计算模块部分异常处理说明

4.1 文件读取异常处理

def read_file(self, file_path):
    """多层次的异常处理策略"""
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"文件不存在: {file_path}")
    
    # 尝试多种编码
    encodings = ['utf-8', 'gbk', 'gb2312', 'latin1']
    
    for encoding in encodings:
        try:
            with open(file_path, 'r', encoding=encoding) as f:
                content = f.read().strip()
                if content:
                    return content
        except (UnicodeDecodeError, UnicodeError):
            continue
        except Exception as e:
            if encoding == encodings[-1]:
                raise OSError(f"无法读取文件 {file_path}: {e}")
            continue
    
    # 最后的容错处理
    try:
        with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
            content = f.read().strip()
            return content if content else ""
    except Exception as e:
        raise OSError(f"无法读取文件 {file_path}: {e}")

4.2 计算过程异常处理

def check_plagiarism(self, orig_file, plagiarized_file):
    """主接口的异常处理"""
    try:
        # 核心计算逻辑
        orig_text = self.read_file(orig_file)
        plagiarized_text = self.read_file(plagiarized_file)
        
        # ... 计算过程 ...
        
        return final_similarity * 100
        
    except Exception as e:
        raise Exception(f"查重过程中发生错误: {e}")

4.3 异常处理测试

def test_file_not_found_error(self):
    """测试文件不存在异常"""
    with self.assertRaises(FileNotFoundError):
        self.checker.read_file("nonexistent_file.txt")

def test_mixed_encoding_error_handling(self):
    """测试混合编码错误处理"""
    # 创建包含特殊字符的文件
    special_file = self.create_temp_file("测试\x00特殊字符", "special.txt")
    normal_file = self.create_temp_file("正常文本", "normal.txt")
    
    # 应该能够处理而不抛出异常
    try:
        similarity = self.checker.check_plagiarism(special_file, normal_file)
        self.assertIsInstance(similarity, float)
    except Exception:
        self.fail("应该能够处理混合编码文件")

5. 使用说明

5.1 环境要求

# Python版本要求
Python >= 3.7

# 依赖包安装
pip install jieba

5.2 基本使用

from plagiarism_checker import PlagiarismChecker

# 创建查重器实例
checker = PlagiarismChecker(ngram_size=3)

# 执行查重检测
similarity = checker.check_plagiarism("original.txt", "suspected.txt")

print(f"文本相似度: {similarity:.2f}%")

5.3 命令行使用

# 基本查重
python main.py examples/orig.txt examples/orig_add.txt

# 运行测试
python -m pytest test_plagiarism_checker.py -v

# 性能分析
python performance_analysis.py

5.4 高级配置

# 自定义n-gram大小
checker = PlagiarismChecker(ngram_size=4)

# 批量处理
files_to_check = [
    ("doc1.txt", "doc2.txt"),
    ("doc3.txt", "doc4.txt")
]

for orig, suspect in files_to_check:
    similarity = checker.check_plagiarism(orig, suspect)
    print(f"{orig} vs {suspect}: {similarity:.2f}%")

总结

本文详细介绍了文本查重系统的设计与实现过程,从接口设计到性能优化,从单元测试到异常处理,展现了一个完整的软件开发流程。该系统具有以下特点:

  1. 模块化设计:清晰的接口定义和职责分离
  2. 算法优化:多算法融合和性能优化策略
  3. 健壮性:完善的异常处理和边界条件处理
  4. 可测试性:高覆盖率的单元测试和性能分析
  5. 易用性:简洁的API设计和详细的使用文档

posted on 2025-09-23 18:57  Mikaphia  阅读(17)  评论(0)    收藏  举报