fix(tradein/scraper): per-city SERP location for oblast city-sweep (#12) #2525

Merged
bot-reviewer merged 1 commit from fix/scraper-city-location-leak into main 2026-07-13 21:41:08 +00:00
Owner

Проблема

get_city_anchors('nizhniy_tagil') возвращает корректный anchor, НО провайдеры хардкодили локацию ЕКБ мимо anchor'а → city-sweep oblast-города фактически скрейпил Екатеринбург, n_analogs=0.

Провайдер Хардкод ЕКБ Правка
avito /ekaterinburg/ в пути URL (4 билдера) target_city_slug (avito_slug) → в путь URL, не только фильтр #2487
cian region=4743 (город ЕКБ) city_region_idregion= (subdomain ekb.cian.ru общий для Свердловской обл., не меняется)
yandex rgid=559132, lat/lon явно игнорит city_rgidrgid=

Тот же класс, что domclick (EKB через GUID). Анкоры oblast-городов (CITY_ANCHORS, #B1/#2487) уже были, не хватало per-provider локации SERP-запроса.

Изменения

  • pipeline.pyCityLocation dataclass + CITY_LOCATIONS (5 городов Свердловской обл., ID проверены сверкой с гео-API сайтов, откалибровано на эталоне ЕКБ) + get_city_location(); прокинуто в run_{avito,cian,yandex}_city_sweep.
  • avito/serp.py — хелпер _city_seg(), city-slug в путь всех 4 URL-билдеров.
  • cian/serp.py — kw city_region_idregion= в _build_url. base_url не тронут.
  • yandex/serp.py — kw city_rgidrgid= в _build_url.
  • scheduler.pycity_slug=city в cian/yandex jobs (avito уже был).

Данные CITY_LOCATIONS: avito_slug у Каменска = kamensk-uralskiy (дефис! underscore→404), В.Пышма = verhnyaya_pyshma (kh→h) — берётся явный avito_slug, не сырой city_slug. cian region_id = город (parentId 4612 = область). yandex rgid = город.

Back-compat

Все новые параметры default None → ЕКБ-поведение byte-identical. run_avito_pipeline / *_full_load / обычный ЕКБ-sweep создают скрейперы без новых kw → дефолты (ekaterinburg / 4743 / 559132). Не тронуты domclick, estimator, geocoder.

Тесты

+9 URL-builder тестов (test_serp_city_location_urls.py): city-slug vs None-дефолт для avito path / cian region / yandex rgid. Полный backend-suite: 2514 passed (1 pre-existing fail в test_search_api.py — env-isolation, не связан).

Verify (после merge+deploy)

UPDATE scrape_schedules SET enabled=true, next_run_at=now() WHERE source='yandex_city_sweep_nizhniy_tagil';
-- ≤60с подхват (scheduler в tradein-scraper) →
SELECT count(*) FROM listings WHERE scraped_at>now()-interval '20 min'
  AND lat BETWEEN 57.6 AND 58.2 AND lon BETWEEN 59.6 AND 60.4;  -- ожидается >0

Затем cian/avito Тагила + geocode_missing_listings + re-smoke оценки Н.Тагила (n_analogs>0).

⚠️ В.Пышма yandex rgid=166366 может тянуть агломерацию ЕКБ (~16k listings) — при её включении проверить bbox отдельно.

Closes #12.

## Проблема `get_city_anchors('nizhniy_tagil')` возвращает корректный anchor, НО провайдеры хардкодили локацию ЕКБ **мимо** anchor'а → city-sweep oblast-города фактически скрейпил Екатеринбург, `n_analogs=0`. | Провайдер | Хардкод ЕКБ | Правка | |---|---|---| | avito | `/ekaterinburg/` в пути URL (4 билдера) | `target_city_slug` (avito_slug) → в путь URL, не только фильтр #2487 | | cian | `region=4743` (город ЕКБ) | `city_region_id` → `region=` (subdomain `ekb.cian.ru` общий для Свердловской обл., не меняется) | | yandex | `rgid=559132`, lat/lon явно игнорит | `city_rgid` → `rgid=` | Тот же класс, что domclick (EKB через GUID). Анкоры oblast-городов (`CITY_ANCHORS`, #B1/#2487) уже были, не хватало per-provider локации SERP-запроса. ## Изменения - **pipeline.py** — `CityLocation` dataclass + `CITY_LOCATIONS` (5 городов Свердловской обл., ID проверены сверкой с гео-API сайтов, откалибровано на эталоне ЕКБ) + `get_city_location()`; прокинуто в `run_{avito,cian,yandex}_city_sweep`. - **avito/serp.py** — хелпер `_city_seg()`, city-slug в путь всех 4 URL-билдеров. - **cian/serp.py** — kw `city_region_id` → `region=` в `_build_url`. base_url не тронут. - **yandex/serp.py** — kw `city_rgid` → `rgid=` в `_build_url`. - **scheduler.py** — `city_slug=city` в cian/yandex jobs (avito уже был). **Данные CITY_LOCATIONS:** avito_slug у Каменска = `kamensk-uralskiy` (дефис! underscore→404), В.Пышма = `verhnyaya_pyshma` (kh→h) — берётся явный avito_slug, не сырой city_slug. cian region_id = город (parentId 4612 = область). yandex rgid = город. ## Back-compat Все новые параметры default `None` → ЕКБ-поведение byte-identical. `run_avito_pipeline` / `*_full_load` / обычный ЕКБ-sweep создают скрейперы без новых kw → дефолты (`ekaterinburg` / `4743` / `559132`). Не тронуты domclick, estimator, geocoder. ## Тесты +9 URL-builder тестов (`test_serp_city_location_urls.py`): city-slug vs None-дефолт для avito path / cian region / yandex rgid. Полный backend-suite: 2514 passed (1 pre-existing fail в `test_search_api.py` — env-isolation, не связан). ## Verify (после merge+deploy) ```sql UPDATE scrape_schedules SET enabled=true, next_run_at=now() WHERE source='yandex_city_sweep_nizhniy_tagil'; -- ≤60с подхват (scheduler в tradein-scraper) → SELECT count(*) FROM listings WHERE scraped_at>now()-interval '20 min' AND lat BETWEEN 57.6 AND 58.2 AND lon BETWEEN 59.6 AND 60.4; -- ожидается >0 ``` Затем cian/avito Тагила + geocode_missing_listings + re-smoke оценки Н.Тагила (`n_analogs>0`). ⚠️ В.Пышма yandex `rgid=166366` может тянуть агломерацию ЕКБ (~16k listings) — при её включении проверить bbox отдельно. Closes #12.
lekss361 added 1 commit 2026-07-13 21:34:39 +00:00
fix(tradein/scraper): per-city SERP location for oblast city-sweep (#12)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m55s
0817178efa
avito/cian/yandex хардкодили ЕКБ (path /ekaterinburg/, region 4743, rgid 559132)
мимо anchor'а oblast-города → city-sweep целевого города скрейпил ЕКБ, n_analogs=0.

- pipeline: CityLocation + CITY_LOCATIONS (5 городов Свердловской обл.) + get_city_location;
  прокинуто в run_{avito,cian,yandex}_city_sweep
- avito: target_city_slug (avito_slug) теперь в ПУТЬ URL (4 билдера), не только фильтр #2487
- cian: city_region_id → region= (subdomain ekb.cian.ru общий для области, не меняется)
- yandex: city_rgid → rgid=
- scheduler: city_slug прокинут в cian/yandex jobs (avito уже был)

Все новые параметры default None → ЕКБ-поведение byte-identical (back-compat).
Tests: +9 URL-builder тестов; full backend suite 2514 passed.
bot-reviewer merged commit 698576e77b into main 2026-07-13 21:41:08 +00:00
bot-reviewer deleted branch fix/scraper-city-location-leak 2026-07-13 21:41:08 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#2525
No description provided.