## Как работает processor Processor находится в `modules/processor.py`. Он получает уже очищенный исходный текст УК РФ и готовит его к анализу. В коде используются простые инструменты: регулярные выражения, списки стоп-слов, `pymorphy3` для лемматизации, `Counter` для подсчета частот, `csv` и `json` для записи результата. ## Что делает processor Основные задачи: 1. Найти слова в тексте. 2. Привести каждое слово к нормальной форме. 3. Удалить лишние слова: стоп-слова, служебные слова структуры закона, числительные, единицы измерения после чисел, имена собственные и названия объектов. 4. Собрать подготовленный текст. 5. Построить предметный указатель на 100 самых частых слов. ## Поиск слов Слова ищутся регулярным выражением: ```python WORD_RE = re.compile(r"[А-Яа-яЁё]+(?:-[А-Яа-яЁё]+)?") ``` Оно находит русские слова, в том числе слова с дефисом: ```text уголовно-правовой социально-опасный ``` Цифры и пунктуация этим выражением не выбираются. ## Лемматизация Лемматизация выполняется через `pymorphy3`. Функция: ```python parse_word(word) ``` возвращает: ```python lemma, tag ``` Например: ```text преступлений -> преступление лишением -> лишение осужденного -> осудить ``` `tag` нужен для фильтрации числительных и имен собственных. Чтобы одно и то же слово не разбирать много раз, используется `lru_cache`. ## Стоп-слова Стоп-слова лежат в множестве: ```python STOP_WORDS ``` Туда входят обычные служебные слова: ```text и, в, на, что, этот, который ``` и структурные слова закона: ```text статья, часть, глава, раздел, пункт, кодекс ``` Они часто встречаются, но не являются полезными терминами предметного указателя. ## Удаление числительных Числительные удаляются двумя способами. Первый способ: по списку слов: ```python NUMERAL_WORDS ``` Например: ```text один, два, три, пятьсот, тысяча, миллион ``` Второй способ: по морфологическим тегам `pymorphy3`: ```python NUMR Anum ``` Так удаляются формы вроде: ```text трех пяти первой второго ``` ## Удаление единиц после чисел Есть слова, которые сами по себе могут быть полезными, но после числа обычно являются частью числительного выражения. Например: ```text до трех лет 500 рублей на срок шесть месяцев ``` Для этого используется список: ```python NUMBER_UNITS ``` Туда входят: ```text год, месяц, день, час, рубль, процент, метр ``` Если такое слово стоит после числительного или после цифры, оно удаляется. ## Удаление имен собственных Имена собственные удаляются тремя способами. Первый способ: по морфологическим тегам: ```python Name, Surn, Patr, Geox, Orgn ``` Так удаляются имена, фамилии, отчества, географические названия и организации, если их распознал `pymorphy3`. Второй способ: по списку отдельных слов: ```python PROPER_WORDS ``` Например: ```text москва, россия, рф, ельцин, интернет ``` Третий способ: по устойчивым словосочетаниям: ```python PROPER_PHRASES ``` Например: ```text российская федерация государственная дума федеральный закон уголовный кодекс центральный банк ``` Сначала слова в строке лемматизируются, затем функция `find_phrase_positions()` ищет такие фразы среди лемм и помечает их позиции как лишние. ## Фильтрация одной строки Основная функция для одной строки: ```python good_words_from_line(line) ``` Она делает следующее: 1. Разбивает строку на слова. 2. Для каждого слова находит лемму и морфологические теги. 3. Находит позиции слов, которые входят в имена собственные из нескольких слов. 4. Проверяет каждое слово функцией `is_bad_word()`. 5. Возвращает только подходящие слова. ## Подготовленный текст Функция: ```python prepare_text(text) ``` проходит по строкам исходного текста, оставляет только хорошие леммы и склеивает их обратно в строки. Результат записывается в: ```text output/uk_rf_prepared.txt ``` ## Предметный указатель Функция: ```python build_subject_index(text, top_n=100) ``` строит индекс так: 1. Проходит по всем подготовленным словам. 2. Считает частоты через `Counter`. 3. Запоминает первое появление каждого слова: номер строки, номер символа и исходную форму слова. 4. Возвращает 100 самых частотных слов. Одна запись индекса выглядит так: ```python { "word": "срок", "count": 3342, "line": 34, "char": 151, "source_word": "срок", } ``` ## Запись результатов Для сохранения индекса есть две функции: ```python write_subject_index_csv(entries, path) write_subject_index_json(entries, path) ``` Они создают: ```text output/uk_rf_subject_index.csv output/uk_rf_subject_index.json ``` CSV удобен для просмотра в таблице, JSON удобен для дальнейшей обработки программой.