scrape-helper
scrape-helper отвечает за автоматический сбор данных из внешних источников и публикацию raw-событий в транспортный контур.
Это не ETL “целиком”, а именно внешний collecting layer.
За что отвечает
- cron-расписание и ручной запуск источников;
- работа с внешними площадками;
- parser lifecycle для каждого адаптера;
- упаковка результата в
CollectedRawRecord; - публикация
source.raw.v1; - загрузка артефактов в MinIO/S3;
- quarantine для проблемных элементов;
- репортинг
SourceRunстатусов в backend; - runtime status и control API.
Поддерживаемые источники
| Код | Что собирает | Основной артефакт | Особенности |
|---|---|---|---|
easuz | закупки ЕАСУЗ | RAW_HTML | HTML-список и карточки |
eis | закупки ЕИС | RAW_HTML | relevance-фильтрация по атомному контуру |
eis_contracts | контракты 44-ФЗ | RAW_HTML | отдельный поток договоров |
eis_contracts_223 | договоры 223-ФЗ | RAW_HTML | отдельный поток 223-ФЗ |
rnp | РНП | RAW_HTML | поиск по нескольким режимам |
fedresurs | риск-сигналы и банкротные сообщения | RAW_JSON или RAW_HTML | production-режим теперь через API |
fns | профили компаний | RAW_JSON и опциональный PDF | может скачивать выписку |
gistorgi | лоты ГИС Торги | RAW_JSON | API-like JSON source |
Как устроен жизненный цикл
1. Инициализация
При старте сервис:
- читает env;
- резолвит
ENABLED_SOURCES; - создаёт список адаптеров;
- поднимает control API;
- планирует cron;
- подключается к RabbitMQ и MinIO.
2. Запуск адаптера
Каждый источник оформлен как SourceAdapter:
export interface SourceAdapter {
code: string;
name: string;
collect(context: SourceRunContext): Promise<CollectedRawRecord[]>;
}Это позволяет добавлять и сопровождать новые источники без переписывания всего пайплайна.
3. Что возвращает адаптер
Адаптер возвращает не доменную сущность, а CollectedRawRecord.
Внутри обычно есть:
urlrawmetadataartifacts
То есть парсер обязан сохранить максимум трассировки до первоисточника.
4. Публикация raw-событий
После collect() сервис:
- загружает артефакты в MinIO/S3;
- строит
RawSourceEvent; - валидирует его по
contracts; - публикует в RabbitMQ;
- при ошибке пытается отправить запись в quarantine queue.
5. Репортинг по SourceRun
До и после запуска scrape-helper отправляет в backend статусы:
RUNNINGSUCCESSFAILED
Именно по ним UI потом показывает:
- историю запусков;
- health источников;
- publication efficiency;
- operational risk level.
Почему scrape-helper не должен писать в Postgres
Это архитектурно важная граница.
Если бы парсер писал доменные сущности напрямую:
- любая смена HTML ломала бы бизнес-слой;
- было бы труднее воспроизводить инциденты;
- пропала бы граница между transport- и domain-level логикой;
- UI и backend сильнее зависели бы от деталей площадки.
Control API
У сервиса есть лёгкий HTTP control-plane:
| Метод | URL | Назначение |
|---|---|---|
GET | /health | health endpoint |
POST | /api/source-runs | ручной запуск источников |
GET | /api/runtime-config | текущее расписание |
PUT | /api/runtime-config | обновление расписания и auto-run |
GET | /api/runtime-status | runtime status, loaded sources, circuit states |
Пример ручного запуска:
curl -X POST http://localhost:3001/api/source-runs \
-H 'content-type: application/json' \
-d '{"sourceCodes":["eis","fns"]}'Важные env-переменные
Общие
RABBITMQ_URLQUEUE_RAW_EVENTQUEUE_QUARANTINE_EVENTSCRAPE_SCHEDULEREQUEST_TIMEOUT_MSRETRY_ATTEMPTSRETRY_BASE_DELAY_MSCIRCUIT_BREAKER_FAILURE_THRESHOLDCIRCUIT_BREAKER_OPEN_MSS3_*HTTP_PROXYHTTPS_PROXYNO_PROXYENABLED_SOURCES
Source-specific
EIS_*EASUZ_*RNP_*FEDRESURS_*FNS_*GISTORGI_*
Что важно знать про внешние площадки
zakupki.gov.ru
Может:
- отдавать нестабильный HTML;
- требовать более “браузерный” профиль запроса;
- резать автоматизированный трафик;
- зависеть от правильного proxy-маршрута.
Fedresurs
Production-режим нужно строить на официальном API.
То есть для стабильного сбора понадобятся:
FEDRESURS_API_URLFEDRESURS_API_LOGINFEDRESURS_API_PASSWORD
Ожидать, что старый HTML-список будет вечно надёжным, уже не стоит.
Когда менять именно этот репозиторий
Он нужен, если:
- изменилась внешняя разметка площадки;
- нужно увеличить глубину или лимиты сбора;
- нужно расширить список поисковых запросов;
- появился новый источник;
- нужно добавить новый артефакт;
- SourceRun теперь должен репортить больше деталей.
Качество
npm run check
npm run test
npm run build