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

Детектор плагиата на 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
Автор
Редакция

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

Обновление Apple TV до tvOS 11 — пошагово
Руководства

Обновление Apple TV до tvOS 11 — пошагово

Частный DNS на Android: настройка и зачем нужен
Android безопасность

Частный DNS на Android: настройка и зачем нужен

Распознать поддельные отзывы на Amazon
Онлайн-шопинг

Распознать поддельные отзывы на Amazon

Отключение Samsung Calendar на Galaxy
Android.

Отключение Samsung Calendar на Galaxy

Как сделать Google Chrome браузером по умолчанию
Инструкции

Как сделать Google Chrome браузером по умолчанию

Лучшие расширения Chrome для продуктивности
Продуктивность

Лучшие расширения Chrome для продуктивности