Блог AST-SoftPro
Как мы строим автоматический мониторинг судебных дел: проект CourtWatcher
Введение
Каждый юрист, работающий с судебными спорами, знает эту рутину: открыть портал суда, вбить номер дела или фамилию стороны, дождаться загрузки страницы и вручную сверить, что изменилось. Если дел много — это часы каждый день, а пропущенное заседание или новая дата разбирательства могут стоить клиенту денег и репутации компании.
В этой статье я расскажу о проекте CourtWatcher — внутреннем сервисе мониторинга судебных дел, который мы разрабатываем для реального заказчика из юридической сферы. Мы покажем, как устроен парсинг открытых порталов судов Москвы, почему «наивный» скрейпинг быстро ломается и что нужно учесть при проектировании подобной системы. Статья не будет учебником по копированию кода — фокус на архитектурных решениях, типичных ловушках и планах развития сервиса в мультипользовательский продукт с уведомлениями и ботами.
Зачем нужен автоматический мониторинг судебных дел
Ручное отслеживание дел имеет несколько системных проблем:
-
Повторяемость. Один и тот же поиск выполняется десятки раз в день по каждому делу.
-
Человеческий фактор. Легко пропустить новую строку в истории состояний или перепутать дату заседания.
-
Масштабируемость. Юридическая служба, ведущая 50–500 дел, физически не может проверять каждое вручную несколько раз в сутки.
-
Скорость реакции. Уведомление о новом заседании или изменении статуса должно прийти до того, как наступит дедлайн.
Автоматизация решает все четыре пункта: планировщик сам обходит порталы по заданным запросам, сохраняет изменения в базу данных и может уведомлять ответственных людей. Для бизнеса это прямая экономия рабочего времени юристов и снижение рисков пропустить важный процессуальный срок.
💡 При оценке целесообразности автоматизации стоит прикинуть простой показатель: сколько часов в неделю команда тратит на ручную проверку порталов × средняя стоимость часа юриста. Обычно окупаемость такого сервиса наступает в течение первых месяцев работы.
Общая архитектура CourtWatcher
Проект построен по классической трёхслойной схеме, которая хорошо масштабируется и упрощает поддержку:
Слой 1 — Парсер. Отдельный модуль знает про каждый портал (его URL, структуру HTML, особенности поиска) и умеет возвращать нормализованные данные: номер дела, стороны, суд, заседания, историю состояний. Парсер не знает о базе данных и не общается с пользователем.
Слой 2 — Хранилище. SQLite в режиме WAL + SQLAlchemy (асинхронный). Четыре основные сущности: дело, заседание, аудит-журнал изменений и журнал запусков парсера. Все изменения записываются транзакционно, что позволяет отследить историю по каждому полю дела.
Слой 3 — Веб-слой. FastAPI-приложение с двумя API: внутренним (для SPA-интерфейса) и внешним /v1 (для интеграции с другими системами заказчика). Интерфейс — одностраничное приложение на ванильном JavaScript с роутингом по hash, без тяжёлых фреймворков.
Дополнительно внутри процесса работает планировщик задач (APScheduler), который по заданному интервалу запускает парсинг для каждого источника. Всё это упаковано в Docker-контейнер и разворачивается на сервере заказчика.
Почему такой стек? Python + FastAPI — быстрый путь к REST API с асинхронностью «из коробки», SQLite достаточно для одного процесса и десятков тысяч записей, а отсутствие фронтенд-фреймворка упрощает сборку и деплой. Для сервисов такого масштаба избыточная абстракция только замедляет разработку.
Как устроен парсинг порталов судов Москвы
Сервис работает с двумя порталами: mos-gorsud.ru (районные суды и Московский городской суд) и mos-sud.ru (мировые судьи). У каждого — своя структура выдачи и свои особенности, поэтому в проекте два независимых парсера.
Поиск дел
На mos-gorsud.ru поиск ведётся по HTML-странице с параметрами запроса и пагинации. Важная особенность: портал отдаёт дела отсортированными по номеру, то есть самые свежие — сверху. Это позволяет обходить страницы по 500 записей и останавливаться, когда собрано нужное количество релевантных дел.
Но есть нюанс: свежие дела первой инстанции не всегда видны в общей выдаче по запросу «наименование участника». Поэтому парсер дополнительно проходит по списку районных судов с фильтром по конкретному суду. Дедупликация выполняется по URL-ключу дела, а не по номеру — номера могут совпадать между разными судами.
На mos-sud.ru механизм проще: поиск по участнику с пагинацией по ~15 дел на страницу. Но карточки здесь требуют заголовок Referer со страницы поиска, иначе портал отвечает 403. Такие мелочи обнаруживаются только при живой отладке и не описаны ни в одном публичном руководстве.
Загрузка карточек дела
После сбора списка парсер загружает карточки дел параллельно (ограниченная конкурентность, по умолчанию 5 одновременных запросов). Из карточки извлекаются: стороны с ролями, судья, категория дела, дата поступления, текущее состояние, таблица «История состояний» и таблица «Судебные заседания».
Разбор выполняется через BeautifulSoup4. Ключевые блоки определяются по CSS-классам и текстовым подписям («Стороны», «Судья», «История состояний»). Если вёрстка изменилась — парсер пишет предупреждение в лог, а не падает. Это важно: сервис должен пережить редизайн портала и продолжить работу с деградацией, а не остановиться полностью.
⚠️ Главный риск любого HTML-парсера — привязка к конкретной разметке. При проектировании стоит заложить мониторинг качества разбора (например, доля карточек, из которых удалось извлечь хотя бы стороны и заседания) и алерты при её падении.
Борьба с rate-limit
Порталы судов чувствительны к частоте запросов: слишком активный клиент получает HTTP 202 (soft-лимит), 429 или таймауты. В CourtWatcher это решается на нескольких уровнях:
-
Таймауты и ретраи. Каждый запрос имеет ограниченный таймаут; при «мягких» ошибках выполняется до трёх повторных попыток с нарастающей паузой.
-
Паузы между страницами. Отдельные настройки для обхода выдачи и для прохода по судам — разные режимы требуют разных интервалов.
-
Ограниченная параллельность карточек. Число одновременных запросов к карточкам настраивается; при частых 429 его снижают до 2–3.
-
Все значения вынесены в настройки, которые можно менять из админки без перезапуска сервиса. Это критично: после деплоя часто приходится «подкручивать» режим под текущую отзывчивость порталов.
💡 Если строить подобный сервис с нуля, заложите с первого дня механизм адаптивной нагрузки: фиксированный интервал между запросами + экспоненциальная пауза при ошибках + возможность динамической настройки из админки. Это сэкономит недели ручной отладки на проде.
Хранение данных и отслеживание изменений
База данных проектировалась вокруг принципа «всё, что меняется, — фиксируется». Четыре основные сущности:
| Сущность | Назначение |
|---|---|
| Дело | Номер, источник, суд, судья, статус, стадия, категория, стороны (JSON), URL, дата регистрации |
| Заседание | Привязка к делу: дата-время, зал, тип/стадия, результат |
| Аудит | История изменений полей дела: кто/когда/что изменилось |
| Журнал запусков | Каждый цикл парсера: время, источник, запрос, сколько найдено/добавлено/обновлено, успех или ошибка |
Сопоставление найденных дел с базой выполняется по URL-ключу. Новое дело — вставка; существующее — обновление изменённых полей и синхронизация списка заседаний (новые заседания добавляются, существующие обновляются). Аудит-журнал позволяет ответить на вопрос «когда именно судья назначил новое заседание» без перебора логов.
SQLite выбран сознательно: один процесс, одна машина, десятки тысяч записей — это его комфортная зона. Режим WAL даёт читаемость во время записи, что важно при одновременной работе парсера и веб-интерфейса. При росте нагрузки (мультипользовательский режим) база легко мигрируется на PostgreSQL без переписывания модели данных.
Веб-интерфейс и API
Интерфейс разделён на шесть экранов: дашборд со статистикой, журнал дел с фильтрами, поиск по порталу с возможностью «найти и сохранить», карточка дела, диагностика (логи парсера) и админка настроек. Всё это — SPA без серверного рендеринга; данные приходят через внутреннее REST API.
Внешний API /v1 защищён ключом и предназначен для интеграции с другими системами заказчика: CRM, внутренние сервисы, боты. Он отдаёт дела, заседания, суды и позволяет выполнять поиск и импорт. Разделение внутреннего и внешнего API — осознанное решение: внешнему потребителю не нужно видеть логи парсера или настройки, а внутренним инструментам не нужен ключевой доступ.
Планы развития: от внутреннего инструмента к сервису
Сейчас CourtWatcher работает как «однопользовательский» сервис для конкретного заказчика. Дальнейшее развитие — превращение в мультипользовательскую платформу мониторинга судебных дел для юридических служб разного размера. Основные направления:
Мультиарендность и персональные поиски
Каждый пользователь (юридическая фирма, корпоративный отдел, частный юрист) получит собственный набор отслеживаемых запросов: свои контрагенты, свои категории дел, свои суды. Технически это добавление уровня «аккаунт» в модель данных и фильтрация всех запросов по нему. Планировщик при этом остаётся общим — он обрабатывает задачи всех пользователей в очереди с учётом лимитов нагрузки на порталы.
Уведомления
Самый востребованный функционал для юристов. События, которые должны генерировать уведомления:
-
Новое заседание назначено или перенесено
-
Изменилось состояние дела (решение вынесено, дело приостановлено и т.д.)
-
Появилось новое дело по отслеживаемому запросу
-
Прошло заседание — результат зафиксирован
Каналы доставки: e-mail как базовый, плюс мессенджеры. Архитектурно уведомления вынесутся в отдельную очередь событий: парсер пишет событие в БД, а независимый диспетчер доставляет его по каналам. Это изолирует сбои в доставке от основного цикла парсинга.
Telegram-бот и бот для MAX
Telegram-бот — естественный канал для юридических команд: уведомление «по делу N назначено заседание на 14.09, зал 305» приходит прямо в рабочий чат. Бот позволит не только получать уведомления, но и выполнять действия: посмотреть статус дела, список ближайших заседаний, добавить новый запрос на отслеживание.
Бот для мессенджера MAX — ответ на требования локализации коммуникации. Для юридических служб, работающих с государственными структурами, наличие канала в российском мессенджере становится всё более значимым требованием. Технически это отдельный адаптер доставки поверх той же очереди событий: интерфейс диспетчера каналов не меняется, добавляется новый драйвер.
💡 При проектировании ботов для юридических сервисов важно с первого дня заложить привязку уведомлений к конкретному делу и пользователю: в чате фирмы несколько юристов следят за разными делами, и «шум» чужих уведомлений снижает ценность канала до нуля.
Расширение на другие суды и регионы
Сейчас сервис работает с двумя порталами Москвы. Логичное расширение — арбитражные суды (картотека kad.arbitr.ru) и региональные порталы общей юрисдикции. Каждый новый источник — это отдельный парсер, но общая модель данных и планировщик остаются неизменными. Именно поэтому архитектура изначально разделяла «знание о портале» и «знание о деле».
Отчёты и аналитика
Для юридических департаментов ценны сводные отчёты: динамика по категориям дел, загрузка судей, среднее время рассмотрения, распределение исковых требований. Данные уже хранятся в структурированном виде — остаётся добавить слой агрегации и экспорт (PDF/Excel).
Что стоит учесть при построении подобных систем
Если вы планируете аналогичный сервис для своей юридической практики или как продукт, вот ключевые уроки, которые мы усвоили:
-
Начинайте с одного портала. Два источника сразу — двойная отладка. Протестируйте полный цикл (поиск → карточка → БД → интерфейс) на одном портале, затем добавляйте второй.
-
Заложите адаптивность нагрузки с первого дня. Фиксированные таймауты и паузы, вынесенные в настройки, — не «оптимизация на потом», а базовое требование для работы с государственными порталами.
-
Дедупликация по URL, а не по номеру дела. Номера пересекаются между судами; это классический источник дублей.
-
Мониторьте качество разбора. Доля успешно распарсенных карточек — главный индикатор того, что портал не изменил вёрстку. Без этого сервис может «тихо» собирать мусор неделями.
-
Разделяйте парсинг, хранение и доставку уведомлений. Три независимых контура с чёткими интерфейсами между ними упрощают отладку и позволяют развивать каждый слой отдельно.
-
Планируйте мультиарендность заранее. Добавление уровня «пользователь» в готовую систему — это миграция данных и переработка планировщика; заложенный с начала уровень аккаунта экономит месяцы работы.
⚠️ Важно понимать: автоматизация мониторинга — это не «написать скрипт и забыть». Порталы судов периодически меняют вёрстку, ужесточают лимиты нагрузки, обновляют сертификаты. Сервис требует постоянного сопровождения: мониторинг качества разбора, оперативная реакция на изменения порталов, тюнинг интервалов. Команды, которые доверяют критичные задачи такого рода опытным разработчикам с опытом работы с реальными государственными порталами, экономят значительное время на предотвращении скрытых сбоев — тех, которые проявляются не в день релиза, а через месяц-два эксплуатации.
Заключение
CourtWatcher — пример того, как относительно компактная система (один Python-процесс, SQLite, один контейнер) решает реальную бизнес-задачу: экономит часы ручного труда юристов и снижает риск пропустить процессуальный срок. Архитектурные решения — разделение парсеров по порталам, адаптивная нагрузка, аудит изменений, изоляция внешнего API — делают систему устойчивой к изменениям внешней среды и готовой к развитию в мультипользовательский сервис.
Планы на ближайшую перспективу: мультиарендность с персональными наборами поисков, система уведомлений (e-mail, Telegram, MAX), расширение на арбитражные суды и региональные порталы, аналитические отчёты. Каждый из этих блоков проектируется поверх уже работающего фундамента, что снижает риск и ускоряет доставку ценности заказчику.
Если ваша юридическая служба тратит заметное время на ручную проверку судебных порталов — автоматизация мониторинга стоит рассмотрения как инвестиция с понятной окупаемостью. А если вы хотите обсудить реализацию подобной системы под свои процессы — мы открыты к диалогу: от прототипа до промышленного сервиса с поддержкой.