Files
Openlane/README.md
2026-04-21 23:48:20 +03:00

5.5 KiB
Raw Blame History

OpenLane Scraper

Парсер автомобилей с OpenLane marketplace. Забирает данные через API (GET /api/v4/search), сохраняет в PostgreSQL. Работает через Playwright (для авторизации), FastAPI, Celery и Docker.

Архитектура

  • Авторизация: Okta OAuth2 PKCE через okta.iam.karglobal.com. Сессия сохраняется в storage_state.json и переиспользуется между запусками.
  • Сбор данных: API-запросы с заголовками x-rbz-user-id, x-rbz-dealership-id (извлекаются из JWT access_token).
  • Защита аккаунта: throttle 25s между запросами, jitter 0120s перед стартом, circuit breaker (2 ошибки подряд → стоп), 403→немедленный стоп, 429→backoff×3.
  • Anti-detection: блокировка ресурсов (bugsnag, intercom, pusher, analytics), stealth patches.

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

Требования

  • Python 3.11+
  • PostgreSQL и Redis (для Celery)

Быстрый старт

git clone <repo-url>
cd openlane_scraper_project
pip install -e .
playwright install chromium

cp .env.example .env
# Заполнить OPENLANE_USERNAME, OPENLANE_PASSWORD в .env

alembic upgrade head

Запуск

# Терминал 1 — API
uvicorn openlane_scraper.api.app:app --reload --port 8000

# Терминал 2 — Celery Worker
celery -A openlane_scraper.worker.celery_app worker --loglevel=info --concurrency=1 --pool=solo -Q scraping

# Терминал 3 — Celery Beat (каждый час)
celery -A openlane_scraper.worker.celery_app beat --loglevel=info

CLI:

openlane scrape-openlane --limit 20

Docker

cp .env.example .env
docker compose up -d

Сервисы: postgres, redis, migrate, api, worker, beat.

  • beat запускает сбор раз в 1 час (CELERY_BEAT_SYNC_INTERVAL_MINUTES=60)
  • Лимит по умолчанию: 20 машин (OPENLANE_MAX_CARS_LIMIT=20)

API (Docker): http://localhost:58000 · Swagger: http://localhost:58000/docs

Первый логин (storage state)

docker compose run --rm --service-ports openlane-auth openlane openlane-login
# Войти вручную в браузере — storage state сохранится в volume

API

  • GET /health — статус сервиса
  • GET /api/v1/stats — статистика (машины, картинки, топ брендов)
  • GET /api/v1/cars — список с пагинацией
  • GET /api/v1/cars/{id} — карточка с картинками
  • POST /api/v1/tasks/sync-listing — запустить сбор
  • GET /api/v1/sync-runs — история запусков

Структура

openlane_scraper/
  scraper.py              — оркестратор: circuit breaker, batched upsert, early-stop
  cli.py                  — CLI-команды (scrape-openlane, openlane-login)

  browser/
    factory.py            — создание браузера, stealth-инъекции, resource blocking

  openlane/
    auth.py               — авторизация через storage_state / Okta PKCE
    client.py             — запросы к /api/v4/search с JWT-заголовками
    checkpoint.py         — checkpoint/resume по страницам
    writer.py             — JSONL + aggregated JSON
    runner.py             — orchestration, retry/backoff, progress

  storage/
    models.py             — SQLAlchemy: Car, Image, SyncRun
    schemas.py            — Pydantic: CarRecord, ImageRecord, CarRead
    enums.py              — enum-значения (drive, gearbox, body_type, ...)
    db.py                 — PersistenceService: upsert, sync runs, статистика

  api/
    app.py                — FastAPI factory
    deps.py               — dependency injection
    routes/               — health, cars, tasks

  worker/
    celery_app.py         — конфиг Celery, beat-расписание
    tasks.py              — sync_listing_task с jitter и lock

  core/
    config.py             — Settings (dataclass), env-переменные
    logs.py               — логирование с trace_id
    retry.py              — @retryable с exponential backoff
    runtime_config.py     — runtime-конфиг
    utils.py              — утилиты

Конфигурация

Всё через env-переменные (полный список в .env.example):

  • OpenLane: OPENLANE_USERNAME, OPENLANE_PASSWORD, OPENLANE_MAX_CARS_LIMIT
  • БД: OPENLANE_DATABASE_URL, OPENLANE_DATABASE_POOL_SIZE
  • Redis: OPENLANE_REDIS_URL
  • Celery: CELERY_BROKER_URL, CELERY_BEAT_SYNC_INTERVAL_MINUTES
  • Прокси: OPENLANE_PROXY_SERVER, OPENLANE_PROXY_USERNAME, OPENLANE_PROXY_PASSWORD

Миграции

В Docker миграции выполняются сервисом migrate (alembic upgrade head).

alembic upgrade head
alembic revision --autogenerate -m "add_column_x"

Тесты

pytest -q

Тесты работают на SQLite in-memory, без внешних зависимостей.

Runtime-фильтры

Файл runtime_config.json управляет runtime-поведением sync и фильтрацией автомобилей.