Files
dubizzle/README.md
2026-04-24 21:00:28 +03:00

6.6 KiB
Raw Blame History

Dubizzle scraper

Сервис для сбора объявлений с dubizzle.com.

Основной сценарий работы:

  • discovery списка машин через Algolia
  • при необходимости fallback на сайт
  • нормализация полей автомобиля
  • upsert в PostgreSQL
  • периодический запуск через Celery Beat

Что делает проект

Проект:

  • собирает все доступные машины из каталога Dubizzle
  • использует Algolia как основной источник discovery
  • обходит лимит одного запроса через сегментацию каталога
  • сохраняет автомобили и изображения в PostgreSQL
  • отдает API для просмотра данных и запуска задач
  • поддерживает hourly/full scan через Celery

Текущая архитектура

Сейчас проект настроен под Dubizzle.

Ключевые особенности:

  • пакет проекта: dubizzle_scraper
  • режим discovery по умолчанию: algolia
  • full scan включен по умолчанию
  • авто-сегментация: DUBIZZLE_LISTING_SEGMENTS=auto
  • параллельный запуск сегментов: CELERY_PARALLEL_SEGMENTS=true

Как собирается весь каталог

Один широкий запрос в Algolia упирается примерно в лимит 10{,}000 доступных результатов. Поэтому проект использует сегментацию по годам.

Авто-сегменты (auto) сейчас разбивают каталог на 8 диапазонов по году:

  • 1900-2012
  • 2013-2015
  • 2016-2017
  • 2018-2019
  • 2020-2021
  • 2022-2023
  • 2024-2025
  • 2026-2027

Если сегмент все равно слишком большой, discovery дополнительно режет его по id-диапазонам.

Стек

  • Python 3.11+
  • Playwright
  • FastAPI
  • Celery
  • Redis
  • PostgreSQL
  • SQLAlchemy
  • Alembic
  • Docker Compose

Быстрый старт через Docker

Это основной рекомендуемый способ запуска.

1. Подготовить окружение

cp .env.example .env

Если нужно, отредактируй .env.

2. Запустить стек

docker compose up -d

Поднимутся сервисы:

  • postgres
  • redis
  • migrate
  • api
  • worker
  • beat

3. Проверить статус

docker compose ps

API будет доступен по адресу:

  • http://localhost:18000
  • Swagger: http://localhost:18000/docs

Порт пробрасывается как ${DUBIZZLE_API_HOST_PORT:-18000}:8000.

Полный сброс и чистый старт

Если нужен запуск с нуля с чистой БД и чистым Redis:

docker compose down -v --remove-orphans
docker compose up -d --build

Важно:

  • docker compose down не удаляет volume
  • docker compose down -v удаляет данные PostgreSQL и Redis

Основные Docker-сервисы

postgres

PostgreSQL база проекта.

По умолчанию:

  • DB: dubizzle_scraper
  • user: dubizzle
  • password: dubizzle
  • host port: 15432

redis

Используется как:

  • broker для Celery
  • backend для task state
  • хранилище progress/state ключей

По умолчанию host port: 16379

migrate

Отдельный сервис, который выполняет:

alembic upgrade head

api

Запускает:

uvicorn dubizzle_scraper.api.app:app --host 0.0.0.0 --port 8000

worker

Запускает Celery worker и выполняет scraping-задачи.

beat

Планировщик periodic tasks.

По умолчанию проект настроен на запуск каждые 60 минут.

Ручной запуск задач в Docker

Разовый sync listing

docker compose run --rm --profile manual sync

По умолчанию это запустит:

dubizzle sync-listing --limit 100 --output /app/artifacts/json/docker_sync_listing.json

Результат будет на хосте в:

  • artifacts/json/docker_sync_listing.json

Запуск с другим лимитом

docker compose run --rm --profile manual -e DUBIZZLE_SYNC_LISTING_LIMIT=500 sync

Запуск непрерывного режима

docker compose up -d api worker beat

Локальный запуск без Docker

Локальный запуск возможен, но проект в первую очередь ориентирован на PostgreSQL + Redis.

Установка

pip install -e .
playwright install chromium

Миграции

alembic upgrade head

Запуск API

uvicorn dubizzle_scraper.api.app:app --reload --port 8000

Запуск worker

celery -A dubizzle_scraper.worker.celery_app worker --loglevel=info --concurrency=1 --pool=solo -Q scraping

Запуск beat

celery -A dubizzle_scraper.worker.celery_app beat --loglevel=info

Полный sync листинга

dubizzle sync-listing --limit 100

Если включена сегментация и не переданы make, model, limit, CLI автоматически пойдет в segmented sync.

API

Базовые роуты:

Health

  • GET /health

Машины

  • GET /api/v1/cars
  • GET /api/v1/cars/{car_id}
  • GET /api/v1/cars/by-origin/{origin_id}
  • GET /api/v1/stats

Задачи

  • POST /api/v1/tasks/sync-vehicle
  • POST /api/v1/tasks/sync-listing
  • GET /api/v1/tasks/{task_id}
  • GET /api/v1/sync-runs

Пример запуска sync vehicle

curl -X POST http://localhost:18000/api/v1/tasks/sync-vehicle \
  -H "Content-Type: application/json" \
  -d '{"vehicle_url": "https://www.dubizzle.com/VehicleDetail/45089484~US"}'

Пример запуска sync listing

curl -X POST http://localhost:18000/api/v1/tasks/sync-listing \
  -H "Content-Type: application/json" \
  -d '{"limit": 100, "only_new": false}'

Тесты

pytest -q

Тесты покрывают:

  • mapper
  • parser
  • listing
  • scraper
  • worker tasks
  • resilience
  • self-heal
  • db