如何使用Python構(gòu)建一個(gè)抄襲檢測(cè)系統(tǒng)?
譯文譯者 | 布加迪
審校 | 重樓
隨著數(shù)字內(nèi)容越來(lái)越受歡迎,保護(hù)它們免受復(fù)制和濫用變得比以往更加重要。抄襲檢測(cè)工具可以幫助教師評(píng)估學(xué)生的作業(yè),幫助機(jī)構(gòu)審閱研究論文,幫助作家發(fā)現(xiàn)其知識(shí)產(chǎn)權(quán)被盜的現(xiàn)象。
構(gòu)建抄襲檢測(cè)工具可以幫助您理解序列匹配、文件操作和用戶(hù)界面。您還可以探索自然語(yǔ)言處理(NLP)技術(shù)以改進(jìn)您的應(yīng)用程序。
Tkinter和Difflib模塊
要構(gòu)建抄襲檢測(cè)器,您將使用Tkinter和Difflib模塊。Tkinter是一個(gè)簡(jiǎn)單的跨平臺(tái)庫(kù),可以用來(lái)快速創(chuàng)建圖形用戶(hù)界面。
Difflib模塊是Python標(biāo)準(zhǔn)庫(kù)的一部分,它提供了用于比較字符串、列表和文件等序列的類(lèi)和函數(shù)。有了它,您可以構(gòu)建文本自動(dòng)糾錯(cuò)器、簡(jiǎn)化版本控制系統(tǒng)或文本摘要工具之類(lèi)的程序。
如何使用Python構(gòu)建抄襲檢測(cè)器?
導(dǎo)入所需的模塊。定義一個(gè)方法load_file_or_display_contents(),它接受entry和text_widget作為參數(shù)。該方法將加載文本文件,并在文本組件中顯示內(nèi)容。
使用get()方法提取文件路徑。如果用戶(hù)沒(méi)有輸入任何內(nèi)容,使用askopenfilename()方法打開(kāi)文件對(duì)話框窗口,選擇想要進(jìn)行抄襲檢查的文件。如果用戶(hù)選擇了文件路徑,從頭到尾清除前一個(gè)條目(如果有的話),并插入所選擇的路徑。
import tkinter as tk
from tkinter import filedialog
from difflib import SequenceMatcher
def load_file_or_display_contents(entry, text_widget):
file_path = entry.get()
if not file_path:
file_path = filedialog.askopenfilename()
if file_path:
entry.delete(0, tk.END)
entry.insert(tk.END, file_path)
以讀取模式打開(kāi)文件,并將內(nèi)容存儲(chǔ)在text變量中。清除text_widget的內(nèi)容,并插入前面提取的文本。
with open(file_path, 'r') as file:
text = file.read()
text_widget.delete(1.0, tk.END)
text_widget.insert(tk.END, text)
定義一個(gè)方法compare_text(),您將用它來(lái)比較兩段文本并計(jì)算它們的相似度百分比。使用Difflib的SequenceMatcher()類(lèi)來(lái)比較序列并確定相似度。將自定義比較函數(shù)設(shè)置為None以使用默認(rèn)比較,并傳遞想要比較的文本。
使用比率方法以浮點(diǎn)格式獲得相似度,可以用來(lái)計(jì)算相似度百分比。使用get_opcodes()方法檢索一組操作,可以用來(lái)高亮顯示文本的相似部分,并將其與相似度百分比一同返回。
def compare_text(text1, text2):
d = SequenceMatcher(None, text1, text2)
similarity_ratio = d.ratio()
similarity_percentage = int(similarity_ratio * 100)
diff = list(d.get_opcodes())
return similarity_percentage, diff
定義一個(gè)方法show_similarity()。使用get()方法從兩個(gè)文本框中提取文本,并將它們傳遞給compare_text()函數(shù)。清除將顯示結(jié)果的文本框中的內(nèi)容,插入相似度百分比。從之前的高亮顯示中刪除“same”標(biāo)簽(如果有的話)。
def show_similarity():
text1 = text_textbox1.get(1.0, tk.END)
text2 = text_textbox2.get(1.0, tk.END)
similarity_percentage, diff = compare_text(text1, text2)
text_textbox_diff.delete(1.0, tk.END)
text_textbox_diff.insert(tk.END, f"Similarity: {similarity_percentage}%")
text_textbox1.tag_remove("same", "1.0", tk.END)
text_textbox2.tag_remove("same", "1.0", tk.END)
get_opcode()方法返回五個(gè)元組:操作碼字符串、第一個(gè)序列的開(kāi)始索引、第一個(gè)序列的結(jié)束索引、第二個(gè)序列的開(kāi)始索引和第二個(gè)序列的結(jié)束索引。
操作碼字符串可以是四個(gè)可能的值之一:replace、delete、insert和equal。當(dāng)兩個(gè)序列中的一部分文本不同,并且有人把一部分換成另一部分時(shí),您將獲得replace。當(dāng)文本的一部分存在于第一個(gè)序列而不存在于第二個(gè)序列時(shí),您將獲得delete。
當(dāng)文本的一部分在第一個(gè)序列中不存在但在第二個(gè)序列中存在時(shí),您將獲得insert。當(dāng)文本的部分相同時(shí),您將獲得equal。將所有這些值存儲(chǔ)在適當(dāng)?shù)淖兞恐?。如果操作碼字符串是equal,向文本序列添加same標(biāo)簽。
for opcode in diff:
tag = opcode[0]
start1 = opcode[1]
end1 = opcode[2]
start2 = opcode[3]
end2 = opcode[4]
if tag == "equal":
text_textbox1.tag_add("same", f"1.0+{start1}c", f"1.0+{end1}c")
text_textbox2.tag_add("same", f"1.0+{start2}c", f"1.0+{end2}c")
初始化Tkinter根窗口。設(shè)置窗口的標(biāo)題,并在其中定義一個(gè)框架。在兩個(gè)方向用適當(dāng)?shù)奶畛?/span>來(lái)組織框架。定義兩個(gè)標(biāo)簽以顯示Text 1和Text 2。設(shè)置它應(yīng)該駐留的父元素和它應(yīng)該顯示的文本。
定義三個(gè)文本框,兩個(gè)用于要比較的文本,一個(gè)用于顯示結(jié)果。聲明父元素、寬度和高度,并將換行選項(xiàng)設(shè)置為tk.WORD,以確保程序在最近的邊界處對(duì)單詞換行,并且不中斷中間的任何單詞。
root = tk.Tk()
root.title("Text Comparison Tool")
frame = tk.Frame(root)
frame.pack(padx=10, pady=10)
text_label1 = tk.Label(frame, text="Text 1:")
text_label1.grid(row=0, column=0, padx=5, pady=5)
text_textbox1 = tk.Text(frame, wrap=tk.WORD, width=40, height=10)
text_textbox1.grid(row=0, column=1, padx=5, pady=5)
text_label2 = tk.Label(frame, text="Text 2:")
text_label2.grid(row=0, column=2, padx=5, pady=5)
text_textbox2 = tk.Text(frame, wrap=tk.WORD, width=40, height=10)
text_textbox2.grid(row=0, column=3, padx=5, pady=5)
定義三個(gè)按鈕,兩個(gè)用于加載文件,一個(gè)用于比較。定義父元素、它應(yīng)該顯示的文本,以及它在被點(diǎn)擊時(shí)應(yīng)該執(zhí)行的函數(shù)。創(chuàng)建兩個(gè)輸入組件來(lái)輸入文件路徑,并定義父元素及其寬度。
使用網(wǎng)格管理器以行和列的形式組織所有這些元素。使用pack來(lái)組織compare_button和text_textbox_diff。在必要的地方添加適當(dāng)?shù)奶畛洹?/span>
file_entry1 = tk.Entry(frame, width=50)
file_entry1.grid(row=1, column=2, columnspan=2, padx=5, pady=5)
load_button1 = tk.Button(frame, text="Load File 1", command=lambda: load_file_or_display_contents(file_entry1, text_textbox1))
load_button1.grid(row=1, column=0, padx=5, pady=5, columnspan=2)
file_entry2 = tk.Entry(frame, width=50)
file_entry2.grid(row=2, column=2, columnspan=2, padx=5, pady=5)
load_button2 = tk.Button(frame, text="Load File 2", command=lambda: load_file_or_display_contents(file_entry2, text_textbox2))
load_button2.grid(row=2, column=0, padx=5, pady=5, columnspan=2)
compare_button = tk.Button(root, text="Compare", command=show_similarity)
compare_button.pack(pady=5)
text_textbox_diff = tk.Text(root, wrap=tk.WORD, width=80, height=1)
text_textbox_diff.pack(padx=10, pady=10)
用黃色背景和紅色字體高亮顯示標(biāo)記為相同的文本。
text_textbox1.tag_configure("same", foreground="red", background="lightyellow")
text_textbox2.tag_configure("same", foreground="red", background="lightyellow")
mainloop()函數(shù)告訴Python運(yùn)行Tkinter事件循環(huán)并監(jiān)聽(tīng)事件,直到您關(guān)閉窗口。
root.mainloop()
把它們放在一起,然后運(yùn)行代碼以檢測(cè)抄襲。
抄襲檢測(cè)器的輸出示例
當(dāng)您運(yùn)行這個(gè)程序時(shí),它會(huì)顯示一個(gè)窗口。點(diǎn)擊Load File 1按鈕后,將打開(kāi)文件對(duì)話框,要求您選擇一個(gè)文件。選擇一個(gè)文件后,程序在第一個(gè)文本框內(nèi)顯示內(nèi)容。在輸入路徑并點(diǎn)擊Load File 2后,程序?qū)?/span>在第二個(gè)文本框內(nèi)顯示內(nèi)容。在點(diǎn)擊Compare按鈕后,您得到的相似度為100%,它高亮顯示相似度100%的整個(gè)文本。
如果您為其中一個(gè)文本框添加另一行并點(diǎn)擊Compare,程序?qū)?/span>高亮顯示相似的部分,并忽略其余部分。
如果幾乎沒(méi)有相似度,程序會(huì)高亮顯示一些字母或單詞,但相似度百分比非常低。
使用NLP進(jìn)行抄襲檢測(cè)
雖然Difflib是一種功能強(qiáng)大的文本比較方法,但它對(duì)微小的變化很敏感,對(duì)上下文的理解有限,并且對(duì)于龐大文本而言通常無(wú)效。這時(shí)候您應(yīng)該考慮探究自然語(yǔ)言處理,因?yàn)樗梢詧?zhí)行文本的語(yǔ)義分析,提取有意義的特征,而且能夠理解上下文。
此外,您可以針對(duì)不同的語(yǔ)言訓(xùn)練模型,并對(duì)其進(jìn)行優(yōu)化以提高效率。可以用于抄襲檢測(cè)的一些技術(shù)包括Jaccard相似性、余弦相似性、單詞嵌入、潛在序列分析以及序列到序列模型。
您可以在這個(gè)GitHub代碼倉(cāng)庫(kù)中找到使用Python構(gòu)建抄襲檢測(cè)器的全部源代碼:https://github.com/makeuseofcode/Plagiarism-Detector-using-Python
原文標(biāo)題:How to Build a Plagiarism Detector Using Python,作者:Sai Ashish Konchada