feat(avito): dedicated newbuilding (novostroyka) citywide sweep #1747
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#1747
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/avito-newbuilding-sweep"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What & why
Avito new-builds are currently only scraped incidentally from the general search (≈20 rows in
listings). Avito has a dedicated novostroyka-filtered SERP that returns 100% new-build cards. Verified live through the prod transport (camoufox+apw via the per-source pool): fetching…/ekaterinburg/kvartiry/prodam/novostroyka-ASgBAgICAkSSA8YQ5geOUg?s=104&p=1and parsing with the existing_parse_htmlreturnedtotal=23 novostroyki=23withnewbuilding_idpopulated (e.g.meridian-ekaterinburg). Paginating yields hundreds.Change
Mirrors the existing citywide-sweep machinery:
avito.py:NOVOSTROYKA_SLUGconstant (EKB novostroyka filter),_build_newbuilding_url(page)(same param shape as_build_citywide_url: s=104, p),fetch_newbuildings(pages=30). The shared paginated loop is factored into a private_paginate_sweep(pages, url_builder, *, label, delay_override_sec)that bothfetch_city_wideandfetch_newbuildingsdelegate to.fetch_city_widebehavior is preserved — identical control flow (exception handling, dedup, break-on-empty, sleep gating) and the sameavito fetch_city_wide pages=… total_lots=…summary log; per-page log renders identically for citywide. The parser already classifies novostroyki by the developer marker and fillsnewbuilding_id/newbuilding_url, so no parser change.scrape_pipeline.py:run_avito_newbuilding_sweep(...)— a slim citywide sweep (fetch → save_listings → scrape_runs counters/mark_done/mark_failed/mark_banned), NOT anchor/houses/detail/IMV phases (novostroyka URL is citywide). Both new symbols exported.scheduler.py:trigger_avito_newbuilding_sweep_run+ dispatchelif source == "avito_newbuilding_sweep"+ import + header doc.data/sql/123_avito_newbuilding_sweep_schedule.sql: idempotent seed (BEGIN/COMMIT,ON CONFLICT (source) DO NOTHING),enabled=true, window 2–5 UTC,default_params {"pages":20,"request_delay_sec":8}.next_run_at= tomorrow 02:00 UTC so it does NOT fire at deploy time (an enabled row with NULL next_run_at is treated as immediately due, and_claim_rundoesn't gate on the window) — follows the existing cian/106 seed convention.Tests
test_avito_newbuilding_sweep.py(13 tests) +fixtures/avito_serp_novostroyka.html: URL builder (novostroyka-,p=2), novostroyka fixture →listing_segment=="novostroyki"+newbuilding_idset, break-on-empty/dedup, counters, pipeline wiring smoke.pytest -q(2 standard deselects) → 1922 passed, 2 deselected. ruff clean, pre-commit green.Post-merge
Migration auto-applies (
_schema_migrations, strict); schedule goes liveenabled=true, first sweep next 02:00 UTC. I'll trigger a run manually post-deploy for immediate fill (current 20 → hundreds), then verify the rows land aslisting_segment='novostroyki'withnewbuilding_id.Fragility note
NOVOSTROYKA_SLUGis hardcoded (same class as the existing citywide/room slugs) — if Avito rotates the EKB novostroyka filter slug it needs updating.