論文查重之小白都懂

赖国颢發表於2024-03-17
這個作業屬於哪個課程 軟體工程2024-雙學位(廣東工業大學)
這個作業要求在哪裡 軟體工程第二次作業
這個作業的目標 1. 在Gitcode倉庫中新建一個學號為名的資料夾
2. 記錄PSP表格
3. 使用程式語言完成論文查重程式
4. 使用Code Quality Analysis分析程式碼
5. 使用Studio Profiling Tools來最佳化程式碼
6. 使用Gitcode來管理程式碼
7. 使用單元測試對專案進行測試,並使用外掛檢視測試分支覆蓋率等指標
其他參考文獻

我的GitCode連結 |

目錄
    • 我的GitCode連結 |
  • 論文查重
    • PSP表格
    • 論文查詢程式設計
      • SequenceMatcher基本使用
        • 獲取匹配度
        • 找出匹配的塊
        • 查詢差異
      • Differ類
    • 使用者輸入的異常處理
    • 使用cprofile進行效能分析
    • 單元測試
    • 程式碼覆蓋率

論文查重

PSP表格

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃 30 60
·Estimate ·估計這個任務需要多少時間 300 440
Development 開發 60 40
·Analysis ·需求分析(包括學習新技術) 20 20
·Design Spec ·生成設計文件 20 30
·Design Review ·設計複審 10 30
·Coding Standard ·程式碼規範(為目前的開發制定合適的規範) 10 10
·Design ·具體設計 30 50
·Coding ·具體編碼 40 60
·Code Review ·程式碼複審 10 20
·Test ·測試(自我測試,修改程式碼,提交修改) 30 50
Reporting 報告 30 30
·TestReport ·測試報告 20 10
·Size Measurement ·計算工作量 10 10
·Postmortem & Process Improvement Plan ·事後總結,提出過程改進計劃 10 20
·合計 330 440

論文查詢程式設計

首先是程式語言的選擇。由於python在資料分析領域已經很成熟,並且資料分析的率也很高,所以綜合考慮後,python是最佳選擇。
經過查詢一些部落格,發現python的difflib庫非常適合論文查重,所以本部落格站在巨人的肩膀上再進行開發。
difflib中常用兩個類:SequenceMatcher 和 Differ,它們都可以用來比較兩個序列(如字串、列表、元組等)之間的差異,並生成相應的結果,十分方便。
difflib 庫中的 SequenceMatcher 類是 Python 的一個非常有用的工具,用於比較兩個序列之間的相似度,找出它們之間最長的連續匹配的子序列。它可以用於比較任何型別的序列(如字串、列表或元組),非常適合於文字比較和差異分析等場景。以下是 SequenceMatcher 的一些基本使用方法和介紹:

SequenceMatcher基本使用

首先,你需要從 difflib 模組匯入 SequenceMatcher 類:

from difflib import SequenceMatcher

然後,你可以建立一個 SequenceMatcher 物件,透過傳入兩個序列來初始化:

matcher = SequenceMatcher(None, "文字1", "文字2")

在建立 SequenceMatcher 物件時,第一個引數是一個可呼叫物件,用於指定如何判斷兩個元素相等。通常,如果你只是想簡單地比較序列中的元素,可以將其設定為 None,這樣比較就會使用預設的相等判斷。

獲取匹配度

SequenceMatcher 提供了 ratio() 方法來計算兩個序列之間的相似度(返回值是一個在 0 到 1 之間的浮點數,1 表示完全匹配):

similarity = matcher.ratio()
print(similarity)

找出匹配的塊

你可以使用 get_matching_blocks() 方法來獲取序列之間匹配的塊。這個方法返回一個列表,列表中的每個元素都是一個具有三個元素的元組 (a, b, n),表示序列 a 中從索引 a 開始、序列 b 中從索引 b 開始、長度為 n 的子序列是匹配的。

matching_blocks = matcher.get_matching_blocks()
for block in matching_blocks:
    print(block)

查詢差異

difflib.SequenceMatcher 還提供了 get_opcodes() 方法,返回一個操作碼列表,描述如何從第一個序列變換到第二個序列。這個方法非常有用於實現差異比較工具,可以顯示兩個序列之間的差異。

opcodes = matcher.get_opcodes()
for tag, i1, i2, j1, j2 in opcodes:
    print(f"{tag}: a[{i1}:{i2}] b[{j1}:{j2}]")

這裡的 tag 表示操作型別(如 'replace'、'delete'、'insert' 或 'equal'),i1:i2 表示第一個序列中受影響的範圍,而 j1:j2 表示第二個序列中受影響的範圍。
透過使用 SequenceMatcher,你可以非常靈活和高效地進行序列比較和差異分析。它是文字處理、資料清洗等場景中非常實用的工具。

Differ類

Differ類可以用來生成兩個序列之間的差異報告,由於本程式只需要查詢兩篇論文的相似度,並不需要具體的分析,所以此處不展開。

使用者輸入的異常處理

在本次開發中,出現錯誤的主要原因是使用者在輸入可執行程式時,出現引數不正確,論文的格式不正確,或者路徑不正確。這些異常都需要在程式中進行處理,以提高程式的完整性和可靠性。
異常處理要用到sys庫和os庫,主要程式碼如下:

import sys
import os
#檔案格式和檔案路徑的異常處理
def check_file(file_path, expected_extension):
    # 檢查檔案格式
    if not file_path.endswith(expected_extension):
        print(f"錯誤:檔案 '{file_path}' 不是期望的檔案格式 '{expected_extension}'。")
        return False
    # 檢查檔案是否存在
    if not os.path.exists(file_path):
        print(f"錯誤:檔案路徑不存在 '{file_path}'。")
        return False
    return True

# 獲取命令列引數
arguments = sys.argv

# 檢查引數數量是否正確
if len(arguments) != 4:
    print("Usage: python main.py [原文檔案] [抄襲版論文的檔案] [答案檔案]")
    sys.exit(1)
# 檢查檔案
if not(check_file(arguments[1], '.txt') and
        check_file(arguments[2], '.txt') and
        check_file(arguments[3], '.txt')):
    sys.exit(2)

以下是對異常處理的結果:

使用cprofile進行效能分析


由上面兩圖的對比可以看出,在程式的執行中,異常處理的函式呼叫是佔最多的,尤其是對檔案路徑是否存在的處理,要大量呼叫'get' of 'str' objects方法,所以如果想讓程式執行得更快,可以將異常處理進行簡化,下圖是簡化後的結果(將檔案路徑是否存在部分的異常處理去掉):

我們可以看出,程式的函式呼叫次數打打減少了,而且執行時間也從0.397s下降到0.001s。所以最終還是要看功能和效能之間的取捨的。

單元測試

程式碼如下:(由於異常單元部分在上面已經測試完畢,所以只測試 calculate_similarity單元)

由上可知測試結果無異常

程式碼覆蓋率


由上可知,程式碼覆蓋率完整,沒有bug。

相關文章