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

153 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenLane Scraper
Парсер автомобилей с [OpenLane marketplace](https://app.openlane.com). Забирает данные через 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)
### Быстрый старт
```bash
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
```
### Запуск
```bash
# Терминал 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:
```bash
openlane scrape-openlane --limit 20
```
## Docker
```bash
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)
```bash
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` — история запусков
## Структура
```text
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`).
```bash
alembic upgrade head
alembic revision --autogenerate -m "add_column_x"
```
## Тесты
```bash
pytest -q
```
Тесты работают на SQLite in-memory, без внешних зависимостей.
## Runtime-фильтры
Файл `runtime_config.json` управляет runtime-поведением sync и фильтрацией автомобилей.