backend/app/services/scrapers/objective.py: ObjectiveClient — GetToken (Bearer cached в Redis 25 min TTL) + GetReport v2 с UseDdu/UseDkp. 4 высокоуровневых метода: report_corpuses_summary, report_lots_summary, report_corpuses_per_flat, report_lots_per_flat. Retry 401/429/5xx, rate-limit 500ms, brotli. backend/app/workers/tasks/scrape_objective.py: Celery task sync_objective_group — еженедельно тянет 4 канон. отчёта по группе, raw payload в objective_raw_reports. celery_app.py: +include + beat «0 5 * * mon». data/sql/68_schema_objective.sql: 6 таблиц — runs, raw_reports (jsonb), oks (готовые ТЭП + escrow/debt), lots, lots_history (per-flat per-day), complex_mapping (Objective ↔ domrf_kn_objects, is_reviewed workflow). data/sql/69_objective_smoke.py: stand-alone GetToken + 4 отчёта → data/raw/objective_smoke/<ts>/. Используется один раз чтобы понять реальную схему payload перед написанием parser-слоя. config: OBJECTIVE_API_KEY, OBJECTIVE_DEFAULT_GROUP=Екатеринбург, OBJECTIVE_SYNC_CRON='0 5 * * mon'.
65 lines
3.8 KiB
Python
65 lines
3.8 KiB
Python
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||
|
||
|
||
class Settings(BaseSettings):
|
||
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
|
||
|
||
database_url: str = "postgresql+psycopg://gendesign:gendesign@localhost:5432/gendesign"
|
||
redis_url: str = "redis://localhost:6379/0"
|
||
cors_origins: list[str] = ["http://localhost:3000"]
|
||
sentry_dsn: str | None = None
|
||
# Release tag для Sentry — обычно git short sha, проставляется
|
||
# deploy.yml в backend/.env.runtime (см. workflow). Локально оставляем
|
||
# пустым — Sentry припишет 'unknown'.
|
||
sentry_release: str | None = None
|
||
environment: str = "dev"
|
||
|
||
# External APIs (Stage 2)
|
||
rosreestr_pkk_base_url: str = "https://pkk.rosreestr.ru/api/features/1"
|
||
overpass_url: str = "https://overpass-api.de/api/interpreter"
|
||
|
||
# Scraper schedule (наш.дом.рф kn-API).
|
||
# Crontab format: "minute hour day_of_month month day_of_week" (Celery crontab).
|
||
# Default: каждый понедельник в окне 04:00–05:00 по МСК.
|
||
scrape_kn_cron: str = "15 4 * * mon"
|
||
# Random delay window in seconds added on top of scheduled start so the worker
|
||
# does not hit DOM.РФ at exactly the same minute every cycle. 0 = disabled.
|
||
scrape_kn_jitter_seconds: int = 1800
|
||
# Default region(s) for scheduled sweeps. Comma-separated.
|
||
scrape_kn_default_regions: str = "66"
|
||
# Path to a pre-captured Playwright storage_state.json (committed in repo,
|
||
# used by worker to skip cold-start WAF challenge).
|
||
scrape_kn_state_path: str = "data/playwright_state.json"
|
||
# Token to authorize ad-hoc /api/v1/admin/scrape/* trigger calls.
|
||
# Empty string = endpoint disabled.
|
||
scrape_admin_token: str = ""
|
||
|
||
# NSPD-scraper schedule (кадастровые кварталы / здания).
|
||
# По умолчанию: 20-е число февраля/мая/августа/ноября в 03:30 МСК
|
||
# (после квартальных публикаций rosreestr_deals).
|
||
scrape_nspd_cron: str = "30 3 20 2,5,8,11 *"
|
||
# Регионы для NSPD-sweep (comma-separated rosreestr region codes).
|
||
scrape_nspd_default_regions: str = "66"
|
||
# Пауза между NSPD-запросами в мс. <600мс — высокий риск WAF 403.
|
||
scrape_nspd_rate_ms: int = 600
|
||
|
||
# Objective.ru API (api.objctv.ru) — платная аналитика первички/вторички.
|
||
# Лежит наряду с DOM.РФ kn + rosreestr CSV как 3-й источник истины с
|
||
# самой богатой моделью (per-flat per-day, escrow/банк-долг, ЕГРН-ИНН).
|
||
# Получить ключ: личный закрытый ApiKey от Объектива (тариф per-территория).
|
||
# Tank-схема:
|
||
# 1. GET /Users/User/GetToken?apiKey=<KEY> → JSON с Bearer-токеном
|
||
# 2. GET /v2/Report/GetReport?... + Authorization: Bearer <token>
|
||
objective_api_key: str | None = None
|
||
objective_base_url: str = "https://api.objctv.ru"
|
||
# Группа = «настройка территории» внутри Объектива. Чаще всего совпадает с
|
||
# городом/областью. Доступные группы определяются тарифом ключа.
|
||
objective_default_group: str = "Екатеринбург"
|
||
# Токен Bearer короткоживущий (предположительно 30 мин — уточнить).
|
||
# Кешируем в Redis с этим TTL (с запасом 5 мин).
|
||
objective_token_ttl_seconds: int = 25 * 60
|
||
# Расписание sync — еженедельно по понедельникам в 05:00 МСК (после kn-sweep).
|
||
objective_sync_cron: str = "0 5 * * mon"
|
||
|
||
|
||
settings = Settings()
|