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

Как создать детектор плагиата на Python с Tkinter и Difflib

7 min read Разработка Обновлено 09 Jan 2026
Детектор плагиата на Python с Tkinter и Difflib
Детектор плагиата на Python с Tkinter и Difflib

Краткое руководство по созданию простого детектора плагиата на Python с графическим интерфейсом на Tkinter и сравнением текста через модуль Difflib. В статье показаны готовые фрагменты кода, пояснения к работе SequenceMatcher, подсветка совпадающих фрагментов и советы по интеграции методов NLP для более глубокого семантического анализа.

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

Введение

С ростом цифрового контента защита от копирования и неправомерного заимствования становится критичной. Детектор плагиата помогает преподавателям, исследователям и авторам быстро находить совпадения в текстах. Небольшой проект с Tkinter и Difflib одновременно служит учебной задачей и рабочим инструментом: вы изучаете сравнение последовательностей, работу с файлами и UI.

Далее мы разберём весь код по шагам, объясним, что делает каждый блок, и дадим рекомендации по улучшению с помощью методов NLP и встраивания в реальную систему.

Краткое описание используемых библиотек

  • Tkinter — стандартная библиотека Python для простых графических интерфейсов. Лёгкая, кросс-платформенная и удобная для быстрых прототипов.
  • Difflib — модуль стандартной библиотеки Python для сравнения последовательностей (строки, списки, файлы). SequenceMatcher вычисляет коэффициент сходства и возвращает операции (опкоды) для выделения различий и совпадений.

Ключевой термин: SequenceMatcher — алгоритм сравнения двух последовательностей; возвращает ratio (число от 0.0 до 1.0) и opcodes для подсветки изменений.

Пошаговая реализация детектора плагиата

Ниже — полные фрагменты кода из примера. Они оставлены в исходном виде для простоты копирования и запуска. После каждого фрагмента даётся пояснение и варианты доработки.

Загрузка файла и отображение содержимого

Функция load_file_or_display_contents отвечает за получение пути к файлу из поля ввода или открытия диалога выбора файла, затем чтение файла и вставку текста в виджет.

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)

Пояснение и советы:

  • Используйте кодировку при открытии файла: open(file_path, ‘r’, encoding=’utf-8’) чтобы избежать проблем с кириллицей.
  • Контролируйте исключения (FileNotFoundError, UnicodeDecodeError) и показывайте ошибки пользователю через messagebox.

Пример с открытием и вставкой текста:

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

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

Сравнение текстов: SequenceMatcher и opcodes

Функция compare_text использует SequenceMatcher для расчёта процентного сходства и получения опкодов для подсветки.

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

Пояснение:

  • ratio() возвращает значение от 0.0 до 1.0. Это простая оценка сходства последовательностей символов.
  • get_opcodes() возвращает список операций: (‘replace’|’delete’|’insert’|’equal’, start1, end1, start2, end2).

Ограничения этого подхода: чувствительность к перестановкам слов, форматированию, пунктуации и небольшим изменениям. Для семантического сравнения лучше применять NLP.

Отображение результата и подсветка совпадающих фрагментов

Функция show_similarity извлекает тексты из виджетов, вызывает compare_text и отображает процент совпадения. Также она снимает прежние теги подсветки и добавляет их заново.

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)

Далее цикл по diff и добавление тега “same” для равных фрагментов:

    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: создание окна и виджетов

Ниже — минимальная сборка интерфейса: метки, текстовые поля, кнопки и поля ввода путей к файлам.

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 1 открывает диалог выбора файла и заполняет первое поле. Аналогично для Load File 2. Кнопка Compare показывает процент сходства и подсвечивает совпадающие символы/фрагменты.

Приложение детектора плагиата с полной схожестью

Если тексты полностью совпадают, вы увидите 100% и подсветку всего текста.

Приложение детектора плагиата с частичной схожестью

При частичном совпадении подсвечиваются только общие фрагменты.

Приложение детектора плагиата с низкой или отсутствующей схожестью

При минимальной схожести подсвечиваются отдельные слова или буквы; процент небольшой.

Ограничения Difflib и когда он не подойдёт

  • Чувствителен к форматированию: разбиение на строки, пробелы, переносы влияют на результат.
  • Не понимает семантику: перефразировка при сохранении смысла часто дает низкий процент сходства.
  • Масштаб: работа с очень большими текстами (десятки мегабайт) требует оптимизации памяти и скорости.

Контрпример: если студент заменил слова синонимами и переставил части текста, Difflib может не определить плагиат — здесь нужен семантический анализ.

Улучшение детектора: методы NLP и альтернативы

Ниже — набор техник, которые применяют для более надёжного обнаружения плагиата:

  • Токенизация + нормализация: удаление пунктуации, приведение к нижнему регистру, лемматизация.
  • Jaccard similarity: сравнение множеств n-грам (подходит для обнаружения доли общих фрагментов).
  • Cosine similarity на векторных представлениях TF-IDF: хорошо работает при перефразировании и разных порядках слов.
  • Векторные эмбеддинги (word2vec, FastText, Sentence-BERT): позволяют оценивать семантическую близость на уровне предложений/абзацев.
  • Пороговые и многослойные проверки: сначала быстрый фильтр (difflib/jaccard), затем более дорогая семантическая проверка.
  • Модели seq2seq и специальные архитектуры для выявления перефразирования.

Практическая схема: сначала быстрый pre-filter (hashing или n-грам Jaccard), затем для подозрительных пар — TF-IDF/cosine или эмбеддинги.

Мини-методология внедрения (шаги)

  1. Сбор и предобработка текстов: нормализация, токенизация и очистка.
  2. Быстрый фильтр: Jaccard по 3- или 5-граммам или MinHash/LSH для снижения числа кандидатов.
  3. Точная проверка: TF-IDF + cosine или Sentence-BERT для семантики.
  4. Ручная ревизия и отчёт: выкладывайте отрывки, процент и метаданные (источник, дата).
  5. Логирование и хранение метрик для аудита.

Рольовые чек-листы

Для разработчика:

  • Обработать варианты кодировок.
  • Добавить обработку ошибок при чтении файлов.
  • Обеспечить юнит-тесты для функций сравнения.

Для преподавателя/рецензента:

  • Настроить пороги тревоги (напр., >70% — ручная проверка).
  • Сохранять текстовую цитату и ссылку на источник.

Для администратора системы:

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

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

  • Программа корректно загружает и отображает текстовые файлы в UTF-8.
  • Кнопка Compare возвращает значение от 0 до 100 и подсвечивает одинаковые фрагменты.
  • Обработка ошибок: приложение не падает при отсутствии файла или при ошибке чтения.
  • При больших текстах время отклика укладывается в SLA (если задано).

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

  • Пустые поля → сообщение об ошибке.
  • Полное совпадение двух текстов → 100% и полная подсветка.
  • Небольшое изменение (одна добавленная строка) → подсветка общих частей и процент < 100.
  • Файлы в разной кодировке (например, CP1251) → проверка корректного чтения или корректное сообщение об ошибке.

Примеры альтернатив и когда их выбрать

  • Если нужно находить заимствования с перефразировкой — используйте эмбеддинги предложений (Sentence-BERT).
  • Для массы документов и быстрого поиска похожих — применяйте MinHash/LSH.
  • Для академических систем с обвинениями в плагиате — комбинируйте автоматическую оценку с ручной проверкой и хранением доказательств.

Безопасность и приватность

  • Не храните пользовательские тексты дольше, чем нужно. Если храните — шифруйте данные в покое.
  • При интеграции в облако проверьте соответствие локальным законам о персональных данных (например, GDPR при работе с данными европейских граждан).
  • Логи должны исключать содержимое текстов, если это не требуется для расследования.

Модель зрелости (мини-матрица)

  • Уровень 0 — прототип: локальное приложение, ручная проверка результатов.
  • Уровень 1 — продуктив: предобработка, базовые метрики, стабильность загрузки.
  • Уровень 2 — продвинутый: многослойные проверки (Jaccard → TF-IDF → EMB), масштабирование.
  • Уровень 3 — корпоративный: распределённый поиск по репозиториям, аудит, интеграция с LMS и политиками конфиденциальности.

Быстрые рекомендации (чек-лист оптимизаций)

  • Используйте ленивую загрузку больших файлов.
  • Применяйте предварительное хеширование блоков для быстрого отсечения явно различных документов.
  • Кешируйте векторы для часто сравниваемых документов.

Decision flow (упрощённая диаграмма)

flowchart TD
  A[Новая пара документов] --> B{Размеры < порога?}
  B -- Да --> C[Быстрый фильтр: Jaccard/MinHash]
  B -- Нет --> D[Шардирование / потоковая обработка]
  C --> E{Прошёл фильтр?}
  E -- Нет --> F[Отчёт: низкая схожесть]
  E -- Да --> G[Семантическая проверка 'TF-IDF / Embeddings']
  G --> H{Процент > порога?}
  H -- Да --> I[Отчёт: подозрительное совпадение -> ручная проверка]
  H -- Нет --> F

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

  • Difflib: +быстро, прост; −чувствителен к форматированию и синтаксису.
  • Jaccard/n-граммы: +устойчивее к перестановкам; −не учитывает семантику.
  • TF-IDF + cosine: +учитывает вес терминов; −не всегда ловит перефразирование.
  • Embeddings: +семантика; −трудоёмкость и требования к ресурсам.

Локальные альтернативы и советы для русскоязычного контента

  • При работе с русским языком используйте лемматизацию (pymorphy2, Mystem) и корректную токенизацию.
  • FastText учитывает морфологию и может быть полезен для русского.
  • Проверяйте кодировки и нормализуйте кавычки и дефисы.

Заключение

Простой детектор плагиата на Tkinter и Difflib — отличный старт для понимания задач сравнения текстов. Для реального применения рекомендую комбинировать быструю символьную проверку с методами NLP: предобработка → быстрый фильтр → семантическая проверка. Не забывайте про безопасность данных и тестирование на реальных сценариях.

Ключевые шаги для дальнейшего развития: добавить поддержку нескольких кодировок, обработку больших корпусов через MinHash/LSH и интеграцию эмбеддингов для понимания смысла. После этого система станет гораздо устойчивее к перефразированию и форматированию.

Краткое резюме

  • Difflib хорош для простых, символьных сравнений.
  • NLP-методы дают семантику и лучше работают с перефразированием.
  • Комбинация быстрых фильтров и точных моделей — оптимальный путь.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

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

Градиенты в Canva: добавить и настроить
Дизайн

Градиенты в Canva: добавить и настроить

Ошибка Disabled accounts can't be contacted в Instagram
Социальные сети

Ошибка Disabled accounts can't be contacted в Instagram

Генерация случайных чисел в Google Sheets
Google Таблицы

Генерация случайных чисел в Google Sheets

Прокручиваемые скриншоты в Windows 11
Windows

Прокручиваемые скриншоты в Windows 11

Как установить корпусной вентилятор в ПК
Железо

Как установить корпусной вентилятор в ПК

Check In в iOS 17: настройка и безопасность
How-to

Check In в iOS 17: настройка и безопасность