# mobile.de Scraper Сервис собирает объявления из mobile.de в PostgreSQL. Поиск и загрузка галерей разделены: основной worker сохраняет данные из Search, а отдельный worker получает только фотографии. ## Как работает 1. `worker` получает исходную ссылку из `MOBILEDE_FILTERED_SEARCH_URL`. 2. Если ссылка содержит несколько марок, она разделяется по маркам. 3. Каждая выдача делится по цене, году и пробегу до сегментов, которые не превышают лимит mobile.de: 50 страниц по 20 объявлений. 4. Данные карточек из Search сохраняются в `MOBILEDE_cars`; новые объявления ставятся в очередь галерей. 5. `worker-images` читает `mobilede_images`, загружает галерею объявления и сохраняет изображения в `MOBILEDE_images`. 6. Между полными проходами действует интервал `MOBILEDE_CONTINUOUS_SYNC_DELAY_SECONDS`. План сегментов сохраняется в volume `tokens_data`. Неполный или плотный план не публикуется для обхода, чтобы не терять объявления за пределами 50-й страницы. ## Сервисы | Сервис | Назначение | | --- | --- | | `postgres` | Автомобили, изображения, отметка `gallery_fetched_at` и история запусков | | `redis` | Брокер Celery, временные Detail claims/retry, runtime-состояние и лимит запросов | | `migrate` | Применяет Alembic-миграции перед запуском приложения | | `worker` | Планирование сегментов и импорт Search-выдачи | | `worker-images` | Загрузка галерей из очереди `mobilede_images` | | `beat` | Периодические задачи Celery | | `api` | FastAPI на порту `MOBILEDE_HOST_API_PORT` | ## Настройка Конфигурация контейнеров находится в `.env`, правила фильтрации — в `runtime_config.json`. Основные переменные: - `MOBILEDE_FILTERED_SEARCH_URL` — исходная ссылка mobile.de с нужной областью поиска; - `MOBILEDE_RESULTS_PER_PAGE=20` и `MOBILEDE_MAX_PAGE_NUMBER=50` — лимит одной выдачи; - `MOBILEDE_SEGMENT_TARGET_RESULTS=950` — целевой размер сегмента; - `MOBILEDE_DETAIL_WORKER_CONCURRENCY` — число процессов загрузки галерей; - `MOBILEDE_DETAIL_REQUEST_DELAY_SECONDS` — общий интервал между запросами галерей; - `MOBILEDE_CONTINUOUS_SYNC_DELAY_SECONDS` — пауза между полными проходами. `worker-images` использует единый Redis-лимитер и circuit breaker: при `403` или `429` новые gallery-запросы временно откладываются, а не повторяются одновременно всеми процессами. Detail-очередь не создаёт служебные строки в PostgreSQL. Redis хранит временный claim с TTL и счётчик ограниченных retry, а окончательным признаком успешно загруженной галереи служит `MOBILEDE_cars.gallery_fetched_at`. После потери Redis уже завершённые галереи не выбираются повторно. ## Запуск Подготовьте локальный файл настроек: ```bash copy .env.example .env ``` Укажите в `.env` `MOBILEDE_FILTERED_SEARCH_URL`, затем запустите стек: ```bash docker compose up -d --build ``` Проверить контейнеры и логи: ```bash docker compose ps docker compose logs -f worker worker-images ``` Миграции применяются контейнером `migrate` автоматически. Для полностью чистого тестового запуска удалите volumes PostgreSQL, Redis и `tokens_data` перед `docker compose up`. ## API После запуска доступны: - `GET /health` — состояние сервиса; - `GET /api/v1/cars` и `GET /api/v1/cars/{car_id}` — автомобили; - `GET /api/v1/stats` — агрегированная статистика; - `POST /api/v1/mobilede/tasks/sync-runtime-segments` — запуск прохода сегментов; - `POST /api/v1/mobilede/tasks/enrich-images` — постановка галерей в обработку; - `GET /api/v1/sync-runs` — история запусков. Интерактивная спецификация FastAPI доступна по `/docs`. ## Проверка ```bash pytest ``` Для просмотра текущего плана и прогресса используйте логи `worker`, Redis-ключи `mobilede:state:bootstrap_segments_total` и `mobilede:state:bootstrap_segments_done`, а также файл `/data/mobilede_runtime_segments.json` внутри volume `tokens_data`.