Хабр, привет! Меня зовут Ману, и я бывший фронтенд-разработчик, который уже семь лет работает корпоративным юристом. Да, звучит странно. Но именно эта комбинациХабр, привет! Меня зовут Ману, и я бывший фронтенд-разработчик, который уже семь лет работает корпоративным юристом. Да, звучит странно. Но именно эта комбинаци

Как я автоматизировал юридическую рутину

2026/03/07 21:30
16м. чтение
Для обратной связи или замечаний по поводу данного контента, свяжитесь с нами по адресу [email protected]
ab3ca98f7de4ee50ac217ae12fe7b2e9.jpg

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

В этой статье я расскажу, как из Excel-таблиц пришел к Python-скрипту, который генерирует десятки документов за пару секунд. Эта история о том, как технический бэкграунд помогает использовать ИИ не просто для генерации текстов, а создавать инструменты, которые реально экономят часы рутинной работы. Прежде всего для минимизации фактора человеческой ошибки и автоматизации рутины.

Как Minecraft привёл меня в юриспруденцию

Начну с предыстории. Под конец 9-го класса я увлекся Minecraft, но не самой игрой, а возможностью создать свой проект под нее. Это были 2012-2015 годы, когда индустрия игровых серверов переживала настоящий бум. Сидя на форумах и изучая, как собрать лаунчер и сайт для своего проекта, я решил начать с дизайна. Так меня и втянуло в веб-разработку.

Около шести лет я проработал в небольшой студии верстальщиком и фронтендером, хотя второе можно было назвать с большой натяжкой. Потом началась взрослая жизнь, и надо было думать о чем-то более серьезном. Меня пригласили в юридическую фирму стажером просто потому, что я разбирался в компьютерах и знал, что такое Word. Да, тогда с наймом было чуточку проще :)

С 2019 года началась моя полноценная юридическая практика. Я полностью ушел из разработки и переключился на юриспруденцию. Работаю в основном с корпоративным и миграционным правом. И вот тут началось самое интересное.

Я быстро понял, что работа юриста делится на два типа. Первая – это более творческий подход, где включается и работает мозг на полную. Сюда относится все, что связано с аналитикой: составление стратегии защиты в суде, написание юридических заключений с анализом нестандартных ситуаций, разработка сложных договорных конструкций. А вторая – формализированная бюрократическая рутина, когда ты просто заполняешь типовые договора, заявления, ходатайства для государственных органов. И вот вторая часть съедала львиную долю времени.

Эксель как первая попытка не сойти с ума

Еще в начале карьеры я устал копировать одни и те же данные из документа в документ. Наименование юридического лица тут, его адрес там, ОГРН в третьем месте – и так по кругу. Тогда мне пришла идея сверстать типовые бланки в Excel и объединить их в один файл по разным вкладкам.

Схема была простая:

  • На первой вкладке (мастер-вкладка) я заполнял всю информацию о клиенте;

  • Со второй и по предпоследнюю (верстка) шли готовые формы документов;

  • А последняя вкладка (техническая) работала как мозг всей системы.

Техническая вкладка забирала данные с первой, унифицировала их, форматировала и так далее и выдавала конечный результат. Также тут были прописаны условия вроде «если поле пустое, выведи прочерк».

После заполнения я просто переходил на нужную вкладку и печатал документ напрямую из Excel. Конечно, были сложности с версткой, потому что печать из Excel – не тоже самое, что и из Word. Приходилось возиться с отступами и размерами ячеек, чтобы все красиво укладывалось на стандартный лист А4.

Однако, этот подход можно было использовать до поры до времени. Но проблема в том, что формы живут своей жизнью. Ведомства обновляют приказы, вводят новые бланки, меняют старые. И каждый раз нужно было переверстывать Excel-файл. Учитывая сложность верстки, руки доходили до этого не сразу – проще было вручную забить данные в новый документ. Со временем форм становилось все больше, и система начала трещать по швам. Нужно было придумать что-то кардинально новое.

214c33fa3de0e4e1ba3fa196cbc59bd8.png

Мечты о красивом решении и почему я их забросил

Возвращаться обратно к Excel не хотелось. Требовалось унифицированное решение, которое можно было бы масштабировать и передать коллегам без особых проблем. Плюс использовать не только в моей практике, но и других областях. В голове сразу возникла идея: берем регламентированные формы в PDF, сохраняем их и накладываем текст поверх через SVG. Реализовать это можно было бы через обычное SPA-приложение на React.

Но когда я начал прикидывать объем работы, энтузиазм быстро остыл. Нужно было:

  1. Упорно и долго писать код на JavaScript;

  2. Разбираться в тонкостях React, и других библиотеках для работы с SVG или canvas;

  3. Сделать превью документа;

  4. Придумать интерфейс для разметки форм;

  5. И много еще чего, включая дебаг и небыстрое начало к самой сути – заполнения документов.

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

Эта идея очень долго висела в моей голове мертвым грузом. Я на протяжении нескольких лет раздумывал как подступиться к этой проблеме и с чего начать. Были разные мысли о том, как группировать данные по категориям (например, база юридических лиц, база физических лиц) и при создании нового проекта просто выбирать стороны, параметры и генерировать нужные документы. Но до реализации так и не доходило.

Как ContentControl стал спасением

Время шло, формы менялись и добавлялись новые. И тут в наше бюро пришел клиент – запрос объемный и с большой типовой документацией. Откладывать больше уже было нельзя.

Все новое – хорошо забытое старое. Думал я, и решил пойти проверенным путем: скормить вордовский документ ИИ и посмотреть, что получится. Результат меня не удивил – он выдал непонятное что вместо верстки, и его нельзя в этом винить. Он не видит то, что видит человек. В его мире алгоритмов – все сделано в соответствии с правилами.

Тогда в наших юридических документах, где требовался аналитический подход, я вовсю использовал Элементы управления контентом (ContentControl). Но его применение было по минимуму: выбрать дату из календарика, вместо ручного прописывания; выбор формы юридического лица (АО или ООО); список с арбитражными судами и их адресами; выбор поверенных лиц и так далее. Простые вещи, упрощающие работу, но не более того.

И тут меня осенило: а что, если использовать ContentControl на полную катушку? Идея была такая:

  • в папке проекта у нас лежит мастер-файл (вордовского формата), внутри него уже приличная и красивая таблица, где слева указаны название полей (наименование, ОГРН, ИНН и т.д.), а справа само поле ContentControl для ввода данных;

  • рядом с мастер-файлом находятся подпапки с формами для разных инстанций;

    • сами формы внутри также размечены полями ContentControl, но их идентификаторы полностью совпадают с идентификаторами из мастер-файла.

project/ │ ├── master.docx # Мастер-файл с данными ├── script.py # Скрипт обработки │ ├── forms_tax/ │ ├── *.docx # Формы с ContentControl │ ├── *_map.json # Конфиги (если нужны) │ └── PDF/ # ← создается скриптом │ ├── forms_migration/ │ ├── *.docx │ └── PDF/ │ └── forms_court/ ├── *.docx └── PDF/

А дальше в дело вступает скрипт на Python, который и является мозгом всей этой затеи. Запускаем через консоль скрипт, и он проходится по всем подпапкам, смотрит вордовские файлы и вставляет данные из мастер-файла в соответствующие поля с одинаковыми идентификаторами. Если в процессе выполнения не обнаружены ошибки, то в каждой подпапке создается папка PDF, где в них будут располагаться сгенерированные PDF-документы.

Так выглядит на текущий момент мастер-файл и размеченные поля типовой формы. Как видно из скриншота, в форме имеется как обычное написание текста, так и по клеткам.
Так выглядит на текущий момент мастер-файл и размеченные поля типовой формы. Как видно из скриншота, в форме имеется как обычное написание текста, так и по клеткам.

Сначала я хотел положить все формы в один вордовский файл и обновлять поля через VBA, но быстро от этой затеи отказался из-за разных типов полей в формах (об этом – далее).

Реализовать задуманное через Python, как я видел, можно посредством вызова функции Word или LibreOffice. Однако, проблемы возникли и тут. При запуске, Word сильно капризничал и каждый раз хотел права на просмотр папок и редактирование файлов, тогда как LibreOffice – нет. Пытался также сделать вызов Word в «тихом» режиме без запуска GUI, но мой скрипт сломался. И на данный момент я решил полностью остановиться на LibreOffice. Буду благодарен, если знающие специалисты подскажут как в будущих итерациях отказаться от этой зависимости и использовать только open-source библиотеки для Python.

Технические грабли, по которым я прошелся

При первых тестах и пробах уже вырисовывался контур этой архитектуры. Она была понятной и простой, не требовала значительного времени и усердной верстки. Буквально за 4-6 часов я размечал и тестировал 12 шаблонов, тогда как на верстку одного документа у меня уходило по несколько суток.

Итак, технически, формат docx – это обычный zip-архив с XML внутри. Если вы когда-нибудь смотрели на древо веб-страницы в DevTools, то структура вордовского документа покажется знакомой. Те же вложенные теги, те же атрибуты, только namespace другой. Библиотека python-docx предназначенная для создания, чтения, редактирования вордовских файлов и позволяет работать с ними напрямую, не открывая Word вообще.

Скрипт при запуске читает мастер-файл, собирает все ContentControl-поля и их значения в словарь (по аналогии с объектами в JavaScript), где ключ – это идентификатор поля, а значение – то, что вы туда вписали. Дальше он обходит все подпапки, находит размеченные вордовские файлы и в каждом из них заменяет поля с совпадающими идентификаторами на нужный текст. После этого запускается LibreOffice (без GUI, просто прыгающая иконка) и генерируются PDF. Пока не дошел до способа, чтобы приложение вообще не запускалось, а работало только через консольные команды.

Не сказать, что все обошлось без ошибок и проблем. Word хранит текст внутри XML весьма своеобразно. Простая фраза [company_name] может быть разбита на несколько отдельных XML-элементов, каждый со своим форматированием. В структуре XML-файла вордовского документа текст внутри абзаца (<w:p>) разбивается на так называемые «прогоны» (runs) – элементы <w:r>.

Это примерно, как если бы текст в теге <p> был разбит на десяток <span> без видимой причины. Поэтому простая замена строки не работала. Чтобы корректно обновить данные, было решено собирать текст всего абзаца воедино, выполнять замену и перезаписывать содержимое, предварительно очищая структуру от лишних «прогонов».

Когда разобрался с обычным текстом, пришел черед нестандартных ситуаций. Например, некоторые государственные формы содержат таблицы, где каждая буква пишется в отдельную клетку. Поле «наименование организации» это 34 клетки подряд, каждая отдельная ячейка в XML. Размечать такое через ContentControl – это сизифов труд. Нужно было искать другое решение.

Для таких форм я ввёл дополнительный файл конфигурации имя_файла_map.json. Простой JSON, где для каждого поля указывается в какие таблицы и ячейки писать символы. Скрипт читает значение из мастер-файла и последовательно вписывает каждый символ в соответствующую ячейку. Чтобы не высчитывать индексы ячеек вручную, была разработана утилита, которая генерирует размеченную версию документа. Суть заключалась в том, что в каждой пустой ячейке красным мелким шрифтом пишется её индекс. Открываешь размеченный документ в Word, смотришь нужные координаты и прописываешь их в map-файл.

Так выглядит размеченный документ после работы скрипта.
Так выглядит размеченный документ после работы скрипта.

В итоге получилось три типа полей, с которым скпт умеет работать:

  1. ContentControl для стандартных форм и простой разметки;

  2. Побуквенное заполнение для нестандартных форм;

  3. Гибридный вариант, сочетающий оба подхода.

Отдельно пришлось повозиться с датами. В государственных формах дата рождения – восемь клеток (две под число, две под месяц, четыре под год). Для некоторых ячеек под год выделено не четыре клетки, а две. Поэтому в map-файле для дат есть отдельная секция, где явно указывается какие ячейки под что. Скрипт берёт дату из мастер-файла в формате ДД.ММ.ГГГГ, разбивает её и раскладывает по нужным индексам.

Была и ещё одна нетривиальная проблема. Это когда одно ContentControl-поле находится внутри другого, такое случается если копировать и вставлять поля в Word. Визуально всё выглядит нормально, но при открытии сгенерированного файла Word выдавал предупреждение о повреждённом содержимом. XML был синтаксически валидным, но семантически нет, потому что вложенные поля – это неподдерживаемая конструкция. Пришлось добавить предварительную обработку, чтобы перед заполнением скрипт разворачивал все вложенные поля, заменяя их на простой текст.

Про форматирование стоит сказать отдельно. При заполнении некоторых форм я придерживаюсь единообразия: заглавные буквы, жирный шрифт и конкретный размер. Если в мастер-файле мы пишем как обычно (первая буква заглавная, а остальные строчными), то он так и переносится в другие формы. Захардкодить это в скрипте было бы неправильно, потому что в разных документах требования разные. Поэтому в map-файле появилась секция _format где для каждого поля можно указать свои параметры (upper переводит текст в верхний регистр, bold делает жирным, size задаёт размер шрифта, align выравнивание). Если форматирование явно не указано в map-файле, то применяются дефолтные значения. Работает одинаково и для побуквенных ячеек и для ContentControl-полей.

{ "_comment": "Маппинг для Ходатайства РР ВКС", "_format": { "inn": { "size": 8 }, "okato": { "size": 8 }, "passissue": { "upper": true, "bold": true, "size": 9, "align": "center" }, "polis_issued": { "upper": true, "size": 9 }," } }, "_dates": { "ogrn_date": { "day": [[13, 15], [13, 16]], "month": [[13, 17], [13, 18]], "year": [[0, 0], [0, 0], [13, 19], [13, 20]] } }, "inn": [[11, 1]], "ogrn": [[13, 1]], "okato": [[11, 12, true]], "company_phone": [[20, 1]] }

Ещё одна проблема, которую я не сразу предвидел: количество ячеек в форме не всегда совпадает с длиной текста. Поле ОКАТО это одиннадцать символов, а ячеек под него десять – скорее всего при разработке формы просто не посчитали. Первое время это решалось вручную и было неудобно. В итоге в формат записи map-файла добавился третий параметр (булев). Если стоит true и символов больше, чем ячеек, скрипт идёт с конца строки и добавляет последний символ в крайнюю ячейку. Выглядит это так: [11, 1, true] – таблица 11, начиная с ячейки 1, с переносом остатка в последнюю клетку. Скрипт берёт строку, нарезает её кусками нужной длины и раскладывает по ячейкам.

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

Реализацию скрипта я полностью отдал искусственному интеллекту (решил проверить на деле Claude Code). В процессе дебага и разработки нужно было лишь корректировать его и направлять в нужно русло. Конечно, задумка не доведена до идеала, но с ним моя команда уже сэкономила уйму времени и снизила вероятность человеческой ошибки при заполнении документов.

Что получилось и куда дальше

Хочется более унифицированного и масштабируемого решения, а не дублирования шаблонов и мастер-файла в каждый новый проект. В будущих планах отказаться от мастер-файла. Например, перейти на работу с библиотекой python-docx-template, которая умеет подставлять данные прямо в шаблоны на основе переменных. Или, что ещё лучше, сделать простое SPA-приложение, где можно создавать проекты, вбивать реквизиты сторон, выбирать нужные документы из каталога и одним кликом генерировать их. По сути, довести текущую идею до полноценного конструктора документов.

Но когда я начал об этом думать, быстро понял, что автоматизация заполнения форм – это только вершина айсберга. Да, мы научились делать массово нужные нам документы, но что происходит с ними дальше? Они либо уходят в архив на локальном диске, либо распечатываются и подшиваются в папки. А если через месяц нужно найти конкретный договор или проверить, не истёк ли срок действия доверенности? Без нормальной системы учёта начинается тот самый ад с Excel-табличками, который мы все так любим.

Поэтому следующим логичным шагом вижу не просто улучшение генератора, а создание полноценной системы учёта договоров и документооборота. Представьте: цифровой реестр договоров с удобными тегами и категориями, чтобы за пару кликов находить всё, что связано с конкретным клиентом или судебным процессом. Хранилище скан-копий с шифрованием, контроль версий документов (как в Git), автоматические напоминания о дедлайнах, шаблонизация и даже OCR с NLP-анализом текста, адаптированным под российское законодательство.

Пока что мои коллеги ведут документооборот по старинке: нумерация в Excel, а сканы просто лежат в папках с названиями вроде «договоры_2025». Если нужно что-то найти – начинается перебор. Хотелось бы, чтобы отечественная юриспруденция не отставала от технологий и предлагала удобные инструменты как для небольших команд, так и для крупных фирм. Короче, планов много. Начну, наверное, с прототипа на python-docx-template, а дальше видно будет.

Вывод

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

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

И вот тут я упираюсь в главную проблему. На данный момент для небольших юридических команд и юристов-предпринимателей практически нет готовых инструментов, которые закрывали бы повседневные потребности. Либо это монструозный 1С:Документооборот, рассчитанный на большой отдел, либо самописные Excel-таблицы, которые рано или поздно начинают сыпаться. Золотой середины, к сожалению, почти нет.

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

Промт для создания идентичного скрипта

--- Напиши Python скрипт `fill_documents.py` для автоматического заполнения Word-документов данными из мастер-файла с последующей конвертацией в PDF через LibreOffice headless. **Архитектура:** Есть папка проекта где лежит `master.docx` — Word-документ с ContentControl-полями (тег каждого поля это его идентификатор, например `company_name`, `inn`, `surname`). Рядом лежат подпапки с шаблонами документов. Скрипт читает данные из мастера и заполняет все найденные шаблоны, после чего конвертирует каждый в PDF и кладёт в подпапку `PDF/`. **Типы полей которые должны поддерживаться:** Первый тип — ContentControl (sdt). Скрипт находит их по тегу и заменяет значение. Перед заполнением необходимо разворачивать вложенные sdt — Word иногда создаёт sdt внутри sdt при копировании полей, и это делает итоговый файл невалидным. Второй тип — текстовые плейсхолдеры вида `[field_name]` прямо в тексте параграфов. Проблема в том что Word внутри XML может разбить строку `[company_name]` на несколько отдельных `<w:r>` элементов с разным форматированием. Поэтому нужно склеивать весь текст параграфа из всех ранов, делать замену и записывать результат в первый `<w:t>`, зануляя остальные. Третий тип — побуквенные таблицы. В некоторых госформах каждый символ пишется в отдельную ячейку таблицы. Для таких документов рядом с шаблоном кладётся файл `имя_документа_map.json` — если он найден, скрипт переключается в режим побуквенного заполнения. **Формат map.json:** Секция `_format` — форматирование для каждого поля: `upper` (bool), `bold` (bool), `size` (int, пункты), `align` (center/left/right). Если поле не указано в `_format` — применяются дефолтные значения `bold: true, size: 10, align: center, upper: false`. Форматирование применяется ко всем типам полей включая ContentControl. Секция `_computed` — вычисляемые поля по шаблону: `"company_full_name": "{org_form} \"{company_name}\""`. Скрипт вычисляет их из других полей данных перед заполнением. Секция `_dates` — для полей где дата разбита по отдельным ячейкам. Формат: отдельно перечисляются ячейки под день, месяц и год. Каждый элемент это конкретная ячейка `[таблица, ячейка]` — один элемент равно один символ. Дата в мастере хранится в формате `ДД.ММ.ГГГГ`. Секция `_text` — текст целиком в одну конкретную ячейку, без побуквенного разбиения. Обычные поля — побуквенное заполнение. Формат записи: целое число `49` означает всю таблицу с нулевой ячейки. Массив `[49, 1]` означает таблицу 49 начиная с ячейки 1. Массив `[49, 1, true]` означает таблицу 49 начиная с ячейки 1, и если символов больше чем ячеек — последний символ добавляется в крайнюю ячейку. **Конвертация в PDF:** Через LibreOffice headless: `soffice --headless --convert-to pdf`. Скрипт ищет LibreOffice по стандартным путям для macOS, Linux и Windows. LibreOffice создаёт PDF в директории источника — скрипт затем перемещает его в папку `PDF/`. **Вспомогательные утилиты:** `mark_tables.py` — принимает путь к docx, создаёт копию где в каждой пустой ячейке таблицы красным шрифтом размером 5pt написан индекс в формате `таблица:ячейка`. Используется для составления map.json вручную. **Зависимости:** только `python-docx` и `lxml`. LibreOffice должен быть установлен отдельно. **Обработка ошибок:** файл map.json читать с кодировкой `utf-8-sig` чтобы корректно обрабатывать BOM который добавляют Windows-редакторы. При ошибке конкретного файла скрипт логирует её и продолжает обработку остальных. ---

Источник

Отказ от ответственности: Статьи, размещенные на этом веб-сайте, взяты из общедоступных источников и предоставляются исключительно в информационных целях. Они не обязательно отражают точку зрения MEXC. Все права принадлежат первоисточникам. Если вы считаете, что какой-либо контент нарушает права третьих лиц, пожалуйста, обратитесь по адресу [email protected] для его удаления. MEXC не дает никаких гарантий в отношении точности, полноты или своевременности контента и не несет ответственности за любые действия, предпринятые на основе предоставленной информации. Контент не является финансовой, юридической или иной профессиональной консультацией и не должен рассматриваться как рекомендация или одобрение со стороны MEXC.

Вам также может быть интересно

[Перевод] Monday.com потеряла 80% своей стоимости. И ее CEO говорит, что именно поэтому он идет ва-банк

[Перевод] Monday.com потеряла 80% своей стоимости. И ее CEO говорит, что именно поэтому он идет ва-банк

Представьте себе картину: вы — со-CEO одной из самых успешных софтверных компаний Израиля. Через пять месяцев после IPO ваши акции пробили отметку в $450. Капит
Поделиться
ProBlockChain2026/03/07 23:21
Анализ Shiba Inu: резкий рост притока SHIB — достаточно ли уровня сжигания 53 000%?

Анализ Shiba Inu: резкий рост притока SHIB — достаточно ли уровня сжигания 53 000%?

SHIB сталкивается с новым давлением продавцов, поскольку 157 миллиардов токенов поступили на биржи. Может ли стремительно растущий уровень сжигания спасти Shiba Inu от зоны $0,0000050?
Поделиться
Crypto Ticker2026/03/08 03:00
Трамп поставил Ноэм в угол во время дебюта специального посланника «Щит Америки»

Трамп поставил Ноэм в угол во время дебюта специального посланника «Щит Америки»

Новоназначенная "Специальный посланник по Щиту Америк" Кристи Ноэм дебютировала в субботу утром во Флориде, чтобы стать свидетелем того, как Дональд Трамп продвигает свою новую "Безопасность
Поделиться
Rawstory2026/03/08 02:30