Гид по технологиям

Детектор плагиата на Python — Tkinter и Difflib

6 min read Разработка Обновлено 21 Dec 2025
Детектор плагиата на Python — Tkinter & Difflib
Детектор плагиата на Python — Tkinter & Difflib

Мужчина использует ноутбук, чтобы записать информацию

О чём эта статья

Здесь мы разберём:

  • базовый GUI на Tkinter для загрузки и отображения текстов;
  • сравнение строк и файлов с помощью difflib.SequenceMatcher;
  • подсветку одинаковых фрагментов и вывод процента сходства;
  • ограничения метода и способы улучшения с помощью NLP;
  • рекомендации по тестированию, приёмке и эксплуатационной проверке.

Важно: цель — образец для обучения и прототипирования, а не решение для промышленного обнаружения плагиата.

Короткая техническая справка

SequenceMatcher — алгоритм сравнения последовательностей из стандартной библиотеки Python. Он работает на уровне символов и возвращает коэффициент сходства (ratio) и набор операций (opcodes), описывающих различия между последовательностями.

Tkinter — кроссплатформенная библиотека для создания простых GUI-приложений в Python.

Определения в одну строку:

  • SequenceMatcher: класс для сравнения двух последовательностей и получения коэффициента схожести.
  • opcode: операция, описывающая участок сравнения (replace, delete, insert, equal).

Полный пошаговый пример: логика и код

Ниже — собранный пример приложения. Код разбит на функции с пояснениями. Сохраните файл, например, как detector.py и запустите в окружении с Python 3.

import tkinter as tk
from tkinter import filedialog
from difflib import SequenceMatcher


def load_file_or_display_contents(entry, text_widget):
    """Загружает файл: если в entry указан путь, использует его, иначе открывает диалог."""
    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)

        # Открываем файл в текстовом режиме и отображаем содержимое
        with open(file_path, 'r', encoding='utf-8', errors='ignore') as file:
            text = file.read()
            text_widget.delete(1.0, tk.END)
            text_widget.insert(tk.END, text)


def compare_text(text1, text2):
    """Возвращает процент сходства (int) и список opcode для подсветки."""
    d = SequenceMatcher(None, text1, text2)
    similarity_ratio = d.ratio()
    similarity_percentage = int(similarity_ratio * 100)

    diff = list(d.get_opcodes())
    return similarity_percentage, diff


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)

    # Проходим по opcodes и отмечаем равные участки
    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")


# Инициализация GUI
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)

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)

# Настройка стиля подсветки одинаковых участков
text_textbox1.tag_configure("same", foreground="red", background="lightyellow")
text_textbox2.tag_configure("same", foreground="red", background="lightyellow")

root.mainloop()

Пояснения к коду

  • load_file_or_display_contents: запрашивает путь в поле или показывает диалог выбора файла; затем читает файл и вставляет текст в соответствующий Text.
  • compare_text: использует SequenceMatcher для вычисления коэффициента и получения opcodes — набора операций, которые удобны для подсветки фрагментов.
  • show_similarity: обновляет поле с процентом сходства и помечает одинаковые фрагменты тегом “same”.

Обратите внимание на кодировку при чтении файла: часто полезно указывать encoding=’utf-8’ и errors=’ignore’ для устойчивости к файлам с разной кодировкой.

Как работает SequenceMatcher (технически)

SequenceMatcher сравнивает последовательности символов и ищет длинные совпадающие подстроки, затем строит на их основе разметку (opcodes). Типичные значения opcode:

  • replace — обе последовательности имеют участок, но они разные;
  • delete — участок есть в первой последовательности, отсутствует во второй;
  • insert — участок отсутствует в первой, присутствует во второй;
  • equal — участки идентичны.

Этот подход чувствителен к перестановкам и небольшим правкам. SequenceMatcher более эффективен для сравнений текстов небольшого и среднего размера.

Примеры вывода

При полном совпадении программа показывает “Similarity: 100%” и подсвечивает весь текст как одинаковый. Если изменить одну строку, подсветятся совпадающие фрагменты, а процент снизится.

Детектор плагиата: приложение с полным совпадением

Детектор плагиата: приложение с частичным совпадением

Детектор плагиата: приложение с низким сходством

Ограничения подхода difflib

  • чувствителен к орфографическим/пунктуационным правкам: замена слов синонимами снижает сходство;
  • не учитывает семантику: перефразирование с сохранением смысла часто обходит детектор;
  • производительность: для очень больших документов сравнение по символам может быть медленным и требовать большой памяти;
  • нечувствительность к языковой структуре: для других языков может требоваться предобработка.

Когда difflib не подойдёт:

  • когда нужно обнаруживать перефразированный текст;
  • для сопоставления источников в разных форматах (PDF, DOCX) без предварительной унификации;
  • когда требуется сопоставлять большие корпуса (миллионы документов).

Улучшения и альтернативные подходы (кратко)

  1. Предобработка текста: нормализация регистра, удаление пунктуации, стемминг/лемматизация, удаление стоп-слов.
  2. N-gram-подход: сравнение множеств n-грам (например, 3- и 5-грам) с Jaccard или cosine similarity.
  3. Векторные представления (word embeddings): cosine similarity между векторными представлениями предложений или документов.
  4. Регулярные выражения и критерии для исключения цитат или общих фраз (boilerplate removal).
  5. Sequence-to-sequence и модели типа BERT для семантического сравнения; использование sentence-transformers для извлечения эмбеддингов.
  6. Индексация больших корпусов с помощью векторных поисков (FAISS, Annoy) для быстрого поиска похожих документов.

Мини-методология для повышения качества детектора

  1. Сбор корпуса: собрать репрезентативную выборку источников, где возможен плагиат.
  2. Предобработка: нормализация, удаление метаданных и boilerplate.
  3. Модель сходства: начать с n-gram + Jaccard, затем перейти на векторные эмбеддинги для семантики.
  4. Валидация: создать тестовый набор пар с разными типами изменений (копирование/перефразирование/пересказ).
  5. Порог и интерфейс: выставить пороги для предупреждений и для обязательного ручного анализа.

Критерии приёмки

  • Приложение загружает и отображает текстовые файлы (.txt) корректно;
  • Кнопка Compare возвращает числовой процент сходства и обновляет текст с подсветкой;
  • Подсветка равных фрагментов соответствует opcodes от SequenceMatcher;
  • Обработка ошибок: при попытке загрузить несуществующий файл приложение не падает;
  • Документация: краткое руководство внутри репозитория о запуске и ограничениях.

Тестовые случаи и примеры приёма

  1. Полное совпадение: два одинаковых файла → 100% и полная подсветка.
  2. Частичное совпадение: файл A + файл B, где добавлена одна строка → подсветка совпадающих фрагментов, процент снижен.
  3. Перефразирование: тот же смысл, иные слова → низкий процент у difflib; при использовании эмбеддингов — выше.
  4. Пустые поля: оба поля пусты → процент 0 или сообщение об отсутствии данных (зависит от реализации).
  5. Некорректная кодировка файла → приложение должно не падать, лучше показывать предупреждение.

Роли и чек-лист для развертывания

Разработчик:

  • добавить логирование ошибок чтения файлов;
  • поддержать кодировки UTF-8 и Windows-1251 при чтении;
  • добавить тесты на opcodes.

Тестировщик:

  • проверить граничные случаи (пустой файл, очень большой файл, бинарный файл с .txt расширением);
  • проверить корректность подсветки для разных шифтов.

Оператор/администратор:

  • следить за правами доступа к папкам с исходниками;
  • по необходимости настроить ограничение максимального размера файла на загрузку.

Риск-матрица и рекомендации по смягчению

  • Ложноположительные срабатывания (false positives): поставить порог и требовать ручной проверки;
  • Ложноотрицательные (false negatives): комбинировать синтаксические и семантические методы;
  • Утечка конфиденциальных данных: не хранить переданные документы дольше, чем требуется; реализовать удаление.

Конкретные идеи для локализации и масштабирования

  • Для русского языка полезна лемматизация (pymorphy2) и нормализация кириллицы;
  • Для наставнических систем (университеты) добавить интеграцию с LMS через API;
  • Для больших корпусов использовать инкрементальную индексацию и векторный поиск.

Краткое руководство по безопасности и приватности

  • Не сохраняйте пользовательские тексты на сервере без согласия;
  • Логи не должны содержать фрагментов текста пользователей;
  • Предусмотрите возможность удаления всех загруженных материалов пользователем по требованию.

Сравнение подходов (кратко)

  • difflib (символьный): прост в реализации, точен для буквального копирования, слаб при перефразировании.
  • n-gram + Jaccard/cosine: лучше устойчив к вставкам/удалениям, но чувствителен к перестановкам.
  • эмбеддинги + cosine: позволяет улавливать семантику, требует моделей и вычислительных ресурсов.

Рекомендации по производительности

  • Ограничьте максимальный размер загружаемых файлов при работе в UI;
  • Для пакетной проверки документов используйте потоковую обработку и индексацию;
  • Для семантических методов применяйте батчинг эмбеддингов и ANN-поиск.

Примерный план развития (roadmap)

  1. Версия 0.1: базовый GUI + difflib (этот пример);
  2. Версия 0.2: предобработка и поддержка нескольких кодировок;
  3. Версия 0.3: n-gram анализ и пороговые показатели;
  4. Версия 1.0: семантические эмбеддинги и поиск по индексу;
  5. Версия 2.0: интеграции с LMS и масштабируемая backend-часть.

Заключение

Этот пример демонстрирует фундаментальную идею процедуры сравнения текстов: показать, где тексты совпадают, и дать числовую оценку сходства. Для практического детектора плагиата стоит комбинировать несколько подходов: синтаксический (difflib, n-gram) и семантический (эмбеддинги), а также внедрять процессы ручной верификации для спорных случаев.

Важно: даже самые продвинутые алгоритмы не заменят экспертной оценки, особенно в академических и юридически значимых контекстах.

Ключевые шаги на старте: собрать примеры, реализовать предобработку и провести валидацию на наборах реальных кейсов.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство