diff --git a/tradein-mvp/backend/app/api/v1/admin.py b/tradein-mvp/backend/app/api/v1/admin.py index 6512c09e..a2e1fbbc 100644 --- a/tradein-mvp/backend/app/api/v1/admin.py +++ b/tradein-mvp/backend/app/api/v1/admin.py @@ -19,15 +19,13 @@ from pydantic import BaseModel, Field, field_validator # scraper_kit-миграция (#2305, Group A): debug run-parser роуты этого файла переключены # на scraper_kit.providers.* эквиваленты (парность доказана tests/scrapers/parity — см. -# vault Scraper_Kit_Legacy_Dependency_Audit_0703). ИСКЛЮЧЕНИЯ (остаются на legacy, -# намеренно НЕ мигрированы): YandexNewbuildingScraper.fetch_jk и cian_newbuilding -# .fetch_newbuilding — их kit-эквиваленты (providers/yandex/newbuilding.py, -# providers/cian/newbuilding.py) внутри себя строят BrowserFetcher(source=...) БЕЗ -# обязательного kwarg'а endpoint → TypeError / silently-swallowed exception при любом -# вызове, независимо от DI на стороне caller'а. Это баг в scraper_kit provider-коде -# (endpoint не прокинут через config, в отличие от SERP-классов и BaseScraper.__aenter__ -# соседних провайдеров) — вне scope этой задачи (см. "только consume, не трогать -# scraper_kit provider-логику"), фиксируем как follow-up. +# vault Scraper_Kit_Legacy_Dependency_Audit_0703). YandexNewbuildingScraper.fetch_jk и +# cian_newbuilding.fetch_newbuilding были временно исключены — их kit-эквиваленты +# (providers/yandex/newbuilding.py, providers/cian/newbuilding.py) строили +# BrowserFetcher(source=...) без обязательного kwarg'а endpoint → TypeError на любом +# вызове. Исправлено в #2322 (endpoint пробрасывается через ScraperConfig, +# config=RealScraperConfig() передаётся явно) — оба debug-роута этого файла +# (#2397 Part D4) теперь тоже на kit. # # scraper_kit-миграция (#2397 slice A, эпик #2277): 5 debug city-sweep/full-load # роутов (avito-city-sweep, cian-city-sweep, cian-full-load, yandex-city-sweep, @@ -61,6 +59,7 @@ from scraper_kit.providers.avito.imv import ( from scraper_kit.providers.avito.serp import AvitoScraper from scraper_kit.providers.cian.serp import CianScraper from scraper_kit.providers.yandex.detail import YandexDetailScraper +from scraper_kit.providers.yandex.newbuilding import YandexNewbuildingScraper from scraper_kit.providers.yandex.serp import YandexRealtyScraper from scraper_kit.providers.yandex.valuation import YandexValuationScraper from sqlalchemy import text @@ -80,7 +79,6 @@ from app.services.scraper_adapters import ( RealScraperConfig, ) from app.services.scraper_settings import get_scraper_delay, invalidate_cache -from app.services.scrapers.yandex_newbuilding import YandexNewbuildingScraper from app.tasks.avito_detail_backfill import run_avito_detail_backfill from app.tasks.geocode_missing import GeocodeBackfillResult, geocode_missing_listings @@ -1542,8 +1540,9 @@ async def scrape_yandex_newbuilding( URL: /{city}/kupit/novostrojka/-/ """ - # fetch_jk использует внутренний BrowserFetcher, httpx-клиент BaseScraper не нужен - scraper = YandexNewbuildingScraper() + # fetch_jk использует внутренний BrowserFetcher, httpx-клиент BaseScraper не нужен. + # config= обязателен (#2322 fix) — иначе BrowserFetcher строится без endpoint=. + scraper = YandexNewbuildingScraper(config=RealScraperConfig()) result = await scraper.fetch_jk(jk_slug=slug, jk_id=id, city=city) if result is None: raise HTTPException(404, f"Could not parse Yandex JK: {slug}-{id} in {city}") @@ -1756,18 +1755,20 @@ async def scrape_cian_newbuilding( Without it → debug-only (no DB write). """ _assert_allowed_url(zhk_url) - from app.services.scrapers.cian_newbuilding import ( + from scraper_kit.providers.cian.newbuilding import ( fetch_newbuilding, save_newbuilding_enrichment, ) - enrichment = await fetch_newbuilding(zhk_url) + enrichment = await fetch_newbuilding(zhk_url, config=RealScraperConfig()) if enrichment is None: raise HTTPException(404, f"Could not parse Cian newbuilding page: {zhk_url}") saved = False if house_id is not None: - await save_newbuilding_enrichment(db, house_id, enrichment) + # save_newbuilding_enrichment — sync (def, returns None); await на sync-функции + # раньше поднимал TypeError на любом вызове с house_id. + save_newbuilding_enrichment(db, house_id, enrichment) saved = True return CianNewbuildingTriggerResp(