update readme and env
This commit is contained in:
39
.env.example
39
.env.example
@@ -1,4 +1,4 @@
|
|||||||
IAAI_HEADLESS=false
|
IAAI_HEADLESS=true
|
||||||
IAAI_RAW_OUTPUT_JSON=iaai_raw_network.json
|
IAAI_RAW_OUTPUT_JSON=iaai_raw_network.json
|
||||||
IAAI_LOG_LEVEL=INFO
|
IAAI_LOG_LEVEL=INFO
|
||||||
# IAAI_LOG_FILE=iaai_scraper.log
|
# IAAI_LOG_FILE=iaai_scraper.log
|
||||||
@@ -13,11 +13,11 @@ IAAI_POST_OPEN_IDLE_MS=3500
|
|||||||
|
|
||||||
# Sequential listing-first mode.
|
# Sequential listing-first mode.
|
||||||
IAAI_CARS_LISTING_URL=https://www.iaai.com/Vehiclelisting/Cars
|
IAAI_CARS_LISTING_URL=https://www.iaai.com/Vehiclelisting/Cars
|
||||||
IAAI_MAX_PAGES_PER_RUN=1
|
IAAI_MAX_PAGES_PER_RUN=10
|
||||||
IAAI_MAX_VEHICLES_PER_RUN=10
|
IAAI_MAX_VEHICLES_PER_RUN=30
|
||||||
IAAI_PAGE_LINK_LIMIT=20
|
IAAI_PAGE_LINK_LIMIT=100
|
||||||
IAAI_INCLUDE_PAGINATION=false
|
IAAI_INCLUDE_PAGINATION=true
|
||||||
IAAI_COLLECT_CURRENT_PAGE_ONLY=true
|
IAAI_COLLECT_CURRENT_PAGE_ONLY=false
|
||||||
|
|
||||||
# Human-like pacing.
|
# Human-like pacing.
|
||||||
IAAI_HUMAN_PACE_ENABLED=true
|
IAAI_HUMAN_PACE_ENABLED=true
|
||||||
@@ -25,15 +25,30 @@ IAAI_AFTER_LISTING_OPEN_MIN_S=2.5
|
|||||||
IAAI_AFTER_LISTING_OPEN_MAX_S=4.5
|
IAAI_AFTER_LISTING_OPEN_MAX_S=4.5
|
||||||
IAAI_AFTER_FILTER_ACTION_MIN_S=2.0
|
IAAI_AFTER_FILTER_ACTION_MIN_S=2.0
|
||||||
IAAI_AFTER_FILTER_ACTION_MAX_S=4.0
|
IAAI_AFTER_FILTER_ACTION_MAX_S=4.0
|
||||||
IAAI_BEFORE_VEHICLE_OPEN_MIN_S=2.5
|
IAAI_BEFORE_VEHICLE_OPEN_MIN_S=1.5
|
||||||
IAAI_BEFORE_VEHICLE_OPEN_MAX_S=5.5
|
IAAI_BEFORE_VEHICLE_OPEN_MAX_S=3.0
|
||||||
IAAI_AFTER_VEHICLE_OPEN_MIN_S=5.0
|
IAAI_AFTER_VEHICLE_OPEN_MIN_S=1.0
|
||||||
IAAI_AFTER_VEHICLE_OPEN_MAX_S=9.0
|
IAAI_AFTER_VEHICLE_OPEN_MAX_S=2.5
|
||||||
IAAI_BETWEEN_VEHICLES_MIN_S=8.0
|
IAAI_BETWEEN_VEHICLES_MIN_S=2.0
|
||||||
IAAI_BETWEEN_VEHICLES_MAX_S=18.0
|
IAAI_BETWEEN_VEHICLES_MAX_S=4.0
|
||||||
IAAI_AFTER_PAGE_CHANGE_MIN_S=3.0
|
IAAI_AFTER_PAGE_CHANGE_MIN_S=3.0
|
||||||
IAAI_AFTER_PAGE_CHANGE_MAX_S=6.0
|
IAAI_AFTER_PAGE_CHANGE_MAX_S=6.0
|
||||||
|
|
||||||
|
# Scheduler (default once per hour)
|
||||||
|
IAAI_SCHEDULER_INTERVAL_MINUTES=60
|
||||||
|
|
||||||
|
# Retry / backoff
|
||||||
|
IAAI_RETRY_DELAY_SECONDS=2.5
|
||||||
|
IAAI_RETRY_BACKOFF_MULTIPLIER=2.0
|
||||||
|
IAAI_RETRY_JITTER_SECONDS=0.25
|
||||||
|
|
||||||
|
# Proxy (HTTP/HTTPS preferred for Playwright)
|
||||||
|
# Chromium does not support SOCKS5 proxy authentication directly.
|
||||||
|
# Use residential or mobile USA proxy.
|
||||||
|
# IAAI_PROXY_SERVER=http://proxy.example.com:8080
|
||||||
|
# IAAI_PROXY_USERNAME=
|
||||||
|
# IAAI_PROXY_PASSWORD=
|
||||||
|
|
||||||
# Database.
|
# Database.
|
||||||
IAAI_DATABASE_URL=sqlite:///iaai_scraper.db
|
IAAI_DATABASE_URL=sqlite:///iaai_scraper.db
|
||||||
IAAI_DATABASE_ECHO=false
|
IAAI_DATABASE_ECHO=false
|
||||||
|
|||||||
@@ -9,5 +9,7 @@ COPY requirements.txt ./
|
|||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
RUN chmod +x entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["./entrypoint.sh"]
|
||||||
CMD ["python", "main.py", "--help"]
|
CMD ["python", "main.py", "--help"]
|
||||||
|
|||||||
76
README.md
76
README.md
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
Скрапер публичного листинга автомобилей с сайта IAAI.
|
Скрапер публичного листинга автомобилей с сайта IAAI.
|
||||||
Собирает данные карточек через Playwright, парсит HTML и перехваченные JSON ответы,
|
Собирает данные карточек через Playwright, парсит HTML и перехваченные JSON ответы,
|
||||||
нормализует и сохраняет в SQLite (или другую БД через SQLAlchemy).
|
нормализует и сохраняет в PostgreSQL или SQLite через SQLAlchemy.
|
||||||
|
|
||||||
Работает последовательно одна машина за раз, с паузами между запросами.
|
По умолчанию работает последовательно одна машина за раз, с паузами между запросами.
|
||||||
|
|
||||||
## Что делает
|
## Что делает
|
||||||
|
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
2. Переходит на каждую карточку, перехватывает XHR/fetch JSON-ответы.
|
2. Переходит на каждую карточку, перехватывает XHR/fetch JSON-ответы.
|
||||||
3. Парсит DOM-текст, `<title>`, встроенные `<script>` с JSON, сетевые payload'ы.
|
3. Парсит DOM-текст, `<title>`, встроенные `<script>` с JSON, сетевые payload'ы.
|
||||||
4. Маппит всё в единую структуру `CarRecord` (pydantic) с нормализацией полей.
|
4. Маппит всё в единую структуру `CarRecord` (pydantic) с нормализацией полей.
|
||||||
5. Делает upsert в БД по `origin_id`, сравнивая `content_hash` чтобы не перезаписывать одинаковые данные.
|
5. Делает upsert в БД по `origin_id`, сравнивая `content_hash`, чтобы пропускать неизменившиеся записи.
|
||||||
|
6. Защищён от дублей: `origin_id` уникален, одинаковые записи пропускаются, а повторные картинки заменяются безопасно.
|
||||||
|
|
||||||
## Структура проекта
|
## Структура проекта
|
||||||
|
|
||||||
@@ -53,10 +54,61 @@ python -m playwright install chromium
|
|||||||
|
|
||||||
```env
|
```env
|
||||||
IAAI_HEADLESS=true
|
IAAI_HEADLESS=true
|
||||||
IAAI_DATABASE_URL=sqlite:///iaai_scraper.db
|
IAAI_DATABASE_URL=postgresql+psycopg://postgres:postgres@localhost:5432/iaai_scraper
|
||||||
```
|
```
|
||||||
|
|
||||||
Все настройки (pacing, лимиты, gentle mode) задаются через переменные окружения `.env.example`.
|
Все настройки (pacing, лимиты, gentle mode, retry/backoff, scheduler) задаются через переменные окружения в `.env.example`.
|
||||||
|
|
||||||
|
### БД для рабочего сайта
|
||||||
|
|
||||||
|
Для рабочего запуска нужно **PostgreSQL**.
|
||||||
|
|
||||||
|
Пример:
|
||||||
|
|
||||||
|
```env
|
||||||
|
IAAI_DATABASE_URL=postgresql+psycopg://postgres:postgres@localhost:5432/iaai_scraper
|
||||||
|
```
|
||||||
|
|
||||||
|
SQLite подходит для локальной отладки, но не для production-сценария сайта.
|
||||||
|
|
||||||
|
### Scheduler по умолчанию
|
||||||
|
|
||||||
|
Режим :
|
||||||
|
|
||||||
|
- запуск раз в **1 час**
|
||||||
|
- лимит **30 машин за цикл**
|
||||||
|
|
||||||
|
Это уже отражено в актуальных env-настройках.
|
||||||
|
|
||||||
|
### Прокси и anti-bot
|
||||||
|
|
||||||
|
IAAI использует anti-bot / fraud protection.
|
||||||
|
|
||||||
|
Что важно:
|
||||||
|
|
||||||
|
- предпочтительно использовать **USA residential** или **USA mobile** прокси
|
||||||
|
- для Playwright лучше использовать **HTTP/HTTPS proxy**
|
||||||
|
- Chromium **не поддерживает SOCKS5 с аутентификацией напрямую**
|
||||||
|
- поэтому для production желательно покупать прокси, который отдаёт именно HTTP/HTTPS доступ
|
||||||
|
|
||||||
|
Пример:
|
||||||
|
|
||||||
|
```env
|
||||||
|
IAAI_PROXY_SERVER=http://proxy.example.com:8080
|
||||||
|
IAAI_PROXY_USERNAME=username
|
||||||
|
IAAI_PROXY_PASSWORD=password
|
||||||
|
```
|
||||||
|
|
||||||
|
### Captcha / anti-bot detection
|
||||||
|
|
||||||
|
В парсере добавлены признаки для определения возможной captcha / anti-bot страницы:
|
||||||
|
|
||||||
|
- `possible_captcha`
|
||||||
|
- `possible_antibot`
|
||||||
|
- `dom_hints.has_captcha_text`
|
||||||
|
- `dom_hints.has_antibot_text`
|
||||||
|
|
||||||
|
Если сайт начнёт отдавать защитную страницу, это можно увидеть в результате scrape.
|
||||||
|
|
||||||
## Команды
|
## Команды
|
||||||
|
|
||||||
@@ -74,7 +126,7 @@ python main.py scrape-vehicle "https://www.iaai.com/VehicleDetail/41180634~US" -
|
|||||||
python main.py sync-vehicle "https://www.iaai.com/VehicleDetail/41180634~US" --lane iaai
|
python main.py sync-vehicle "https://www.iaai.com/VehicleDetail/41180634~US" --lane iaai
|
||||||
|
|
||||||
# массовая синхронизация листинга
|
# массовая синхронизация листинга
|
||||||
python main.py sync-listing --make Toyota --model Camry --lane iaai_cars
|
python main.py sync-listing --make Toyota --model Camry --lane iaai_cars --limit 30
|
||||||
|
|
||||||
# daemon-режим (цикл каждые N минут)
|
# daemon-режим (цикл каждые N минут)
|
||||||
python main.py run-daemon --interval 60
|
python main.py run-daemon --interval 60
|
||||||
@@ -93,4 +145,16 @@ docker compose build
|
|||||||
docker compose run --rm iaai-scraper python main.py --help
|
docker compose run --rm iaai-scraper python main.py --help
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Для Docker прокси также задаются через `.env`.
|
||||||
|
|
||||||
|
## Защита от дублей
|
||||||
|
|
||||||
|
Система защищена от дублей на нескольких уровнях:
|
||||||
|
|
||||||
|
- `origin_id` уникален в БД
|
||||||
|
- при совпадении `content_hash` запись **пропускается** (`skipped`)
|
||||||
|
- при обновлении запись не дублируется, а обновляется
|
||||||
|
- изображения пересобираются без накопления дублей
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
4
entrypoint.sh
Normal file
4
entrypoint.sh
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
Reference in New Issue
Block a user