Cách làm công cụ phát hiện đạo văn bằng Python

Xây dựng một công cụ phát hiện đạo văn có thể giúp bạn hiểu kết hợp chuỗi, hoạt động của file và giao diện người dùng. Bạn cũng khám phá được các kỹ thuật xử lý ngôn ngữ tự nhiên để nâng cao ứng dụng.

Lập trình ứng dụng

Ở bài viết này, hãy cùng Quantrimang.com tìm hiểu cách xây dựng công cụ kiểm tra đạo văn và những tính năng mạnh mẽ của mô đun Difflib nhé!

Mô đun Tkinter và Difflib

Để xây dựng công cụ phát hiện đạo văn, bạn sẽ dùng mô đun Tkinter và Difflib. Tkinter là một thư viện chéo nền tảng, đơn giản mà bạn có thể dùng để tạo giao diện người dùng đồ họa nhanh chóng.

Mô đun Difflib là một phần của thư viện chuẩn Python, cung cấp class và các hàm so sánh các chuỗi như string, list, file. Nhờ nó, bạn có thể xây dựng chương trình như tự động sửa lỗi văn bản, hệ thống kiểm soát phiên bản đơn giản hoặc một công cụ tóm tắt văn bản.

Cách xây dựng một công cụ phát hiện đạo văn bằng Python

Nhập các mô đun cần thiết. Xác định một phương thức load_file_or_display_contents() lấy entry text_widget làm đối số. Phương thức này sẽ tải một file text và hiện nội dung của nó trong một widget text.

Dùng get() để truy xuất đường dẫn file. Nếu người dùng không nhập bất kỳ thông tin gì, dùng askopenfilename() để mở một cửa sổ hộp thoại file chọn tệp tin muốn kiểm tra đạo văn. Nếu người dùng chọn đường dẫn file này, xóa mục trước đó nếu có, từ đầu tới cuối và chèn đường dẫn được chọn.

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)

Mở file ở chế độ đọc và lưu nội dung trong biến text. Xóa nội dung của text_widget và chèn text bạn đã truy xuất trước đó.

        with open(file_path, 'r') as file:
            text = file.read()
            text_widget.delete(1.0, tk.END)
            text_widget.insert(tk.END, text)

Xác định một phương thức, compare_text() mà bạn sẽ dùng để so sánh hai phần văn bản, đồng thời, tính toán phần trăm tương đồng. Dùng class SequenceMatcher() của Difflib để so sánh các chuỗi và xác định sự giống nhau. Đặt hàm so sánh tùy chỉnh sang None để dùng so sánh mặc định và chuyển text bạn muốn so sánh.

Dùng phương pháp tính tỷ lệ để xác định mức độ giống nhau ở định dạng floating-point mà bạn có thể dùng để tính toán phần trăm tương đồng. Dùng get_opcodes() để truy xuất một nhóm hoạt động mà bạn có thể dùng để highlight các phần tương tự trong văn bản và trả lại phần đó cùng với phần trăm giống nhau.

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

Xác định một phương thức show_similarity(). Dùng get() để truy xuất văn bản từ cả hai text box và đưa chúng vào hàm compare_text(). Xóa nội dung của textbox hiện kết quả và chèn phần trăm tương đồng. Loại bỏ tag “same” từ highlight trước đó (nếu có).

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() trả về 5 bộ dữ liệu: chuỗi opcode, chỉ mục bắt đầu chuỗi thứ nhất, chỉ mục kết thúc chuỗi đầu tiên, chỉ mục bắt đầu chuỗi thứ hai và chỉ mục kết thúc chuỗi thứ hai.

Chuỗi opcode có thể là một trong số 4 giá trị: replace, delete, insert, và equal. Bạn sẽ dùng replace khi một phần văn bản ở cả hai chuỗi khác nhau, và ai đó đã thay thế một phần nội dung bằng phần khác. Delete sẽ được dùng khi một phần text tồn tại trong chuỗi đầu tiên, không phải thứ hai.

Insert được dùng khi một phần text không có ở chuỗi đầu tiên mà hiện ở chuỗi thứ hai. Bạn nhận được kết quả ngang bằng khi các phần nội dung đều giống nhau. Lưu tất cả những giá trị này trong các biến phù hợp. Nếu chuỗi opcode là equal, thêm tag same cho chuỗi text.

    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")

Khởi tạo cửa sổ gốc Tkinter. Đặt tên cửa sổ và xác định một khung hình bên trong nó. Sắp xếp khung với phần đệm (padding) phù hợp ở cả hai hướng. Xác định hai nhãn để hiện Text 1Text 2. Đặt thành phần cha mà nó nằm bên trong và nội dung nó hiển thị.

Xác định 3 hộp văn bản, hai cho text bạn muốn so sánh và một để hiện kết quả. Khai báo thành phần cha, chiều rộng và cao, đặt tùy chọn đóng gói sang tk.WORD để đảm bảo rằng chương trình này bao bọc các từ ở ranh giới gần nhất và không ngắt bất kỳ từ nào ở giữa.

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)

Xác định 3 nút bấm, hai để tải file và một để so sánh. Xác định thành phần cha, text nó sẽ hiện và hàm nó sẽ chạy khi được click. Tạo hai widget đầu vào để nhập đường dẫn file và xác định thành phần cha cùng với chiều rộng của nó.

Sắp xếp tất cả những thành phần này theo hàng và cột bằng trình quản lý dạng grid. Dùng pack để sắp xếp compare_button & text_textbox_diff. Thêm phần đệm phù hợp tại vị trí cần thiết.

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)

Highlight text đã được đánh dấu giống nhau trên nền vàng và màu font đỏ.

text_textbox1.tag_configure("same", foreground="red", background="lightyellow")
text_textbox2.tag_configure("same", foreground="red", background="lightyellow")

Hàm mainloop() báo Python chạy lặp sự kiện Tkinter và lắng nghe sự kiện cho tới khi bạn đóng cửa sổ.

root.mainloop()

Đặt tất cả lại với nhau và chạy code để phát hiện đạo văn.

Kết quả ví dụ về công cụ phát hiện đạo văn

Khi chạy chương trình này, nó hiện một cửa sổ. Khi nhấn nút Load File 1, một hộp thoại file mở ra và yêu cầu bạn chọn file. Khi chọn file, chương trình này hiện nội dung bên trong text box đầu tiên. Khi nhập đường dẫn và nhấn Load File 2, chương trình hiện nội dung ở text box thứ hai. Khi nhấn nút Compare, bạn sẽ có điểm tương đồng là 100% và nó highlight toàn bộ văn bản giống nhau hoàn toàn.

Công cụ so sánh text

Nếu thêm dòng khác vào một textbox, rồi nhấn Compare, chương trình này highlight phần giống nhau và giữ nguyên phần còn lại.

So sánh văn bản

Nếu có rất ít điểm giống nhau, chương trình highlight một số chữ cái hoặc từ, nhưng phần trăm điểm tương đồng khá thấp.

Kết quả so sánh văn bản

Trên đây là cách tạo công cụ phát hiện đạo văn bằng Python. Như bạn thấy cũng khá đơn giản phải không? Chúc các bạn thành công!

Thứ Năm, 10/08/2023 16:37
54 👨 449
1 Bình luận
Sắp xếp theo
  • Công Khanh
    Công Khanh

    anh có thể chia sẽ với em thêm về code kh ạ


    Thích Phản hồi 17:43 27/12
    ❖ Python