From 5ee8a20732ba270350e998fe34562f3953d33064 Mon Sep 17 00:00:00 2001 From: lekss361 Date: Sun, 24 May 2026 17:59:09 +0300 Subject: [PATCH] feat(tradein-sweep): --require-house-number filter (default on) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Yandex valuation endpoint resolves only to specific buildings; bare street names like 'Академическая улица' return 0 items. Filter to addresses with a house number (regex ', \d+') cuts the work pool from 583 to ~123 addresses that actually have history data. Toggle with --no-require-house-number to sweep everything. --- .../scripts/sweep-yandex-valuation-ekb.py | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/tradein-mvp/scripts/sweep-yandex-valuation-ekb.py b/tradein-mvp/scripts/sweep-yandex-valuation-ekb.py index 38fb366c..e2fea0bc 100644 --- a/tradein-mvp/scripts/sweep-yandex-valuation-ekb.py +++ b/tradein-mvp/scripts/sweep-yandex-valuation-ekb.py @@ -69,22 +69,34 @@ def _addresses_to_sweep( limit: int | None, skip_recent_days: int, single_address: str | None, + require_house_number: bool = True, ) -> list[str]: - """Pull unique active EKB yandex addresses, optionally skipping recently-cached ones.""" + """Pull unique active EKB yandex addresses, optionally skipping recently-cached ones. + + require_house_number: filter to addresses containing a house number. Yandex's + valuation endpoint needs a specific building — bare street names ('Академическая + улица') return 0 items. Heuristic: address must contain a digit after a comma + OR end with a digit token. Default True. + """ if single_address: return [single_address.strip()] + # Postgres regex for house-number tokens — used when require_house_number=True. + # Matches ", 12" / ", 12к3" / ", 5Б" anywhere in the address. + house_num_clause = " AND address ~ ',\\s*\\d+' " if require_house_number else "" + db = SessionLocal() try: if skip_recent_days > 0: sql = text( - """ + f""" SELECT DISTINCT l.address FROM listings l WHERE l.source = 'yandex' AND l.region_code = 66 AND l.is_active = TRUE AND l.address IS NOT NULL + {house_num_clause} AND NOT EXISTS ( SELECT 1 FROM external_valuations ev WHERE ev.source = 'yandex_valuation' @@ -97,13 +109,14 @@ def _addresses_to_sweep( rows = db.execute(sql, {"days": skip_recent_days}).mappings().all() else: sql = text( - """ + f""" SELECT DISTINCT address FROM listings WHERE source = 'yandex' AND region_code = 66 AND is_active = TRUE AND address IS NOT NULL + {house_num_clause} ORDER BY address """ ) @@ -213,9 +226,29 @@ async def main() -> None: default=None, help="Single address mode — sweep only this address", ) + p.add_argument( + "--require-house-number", + dest="require_house_number", + action="store_true", + default=True, + help="Skip addresses without a house number (default: True). " + "Yandex valuation endpoint needs a specific building; street-only addresses " + "return 0 items. Use --no-require-house-number to disable.", + ) + p.add_argument( + "--no-require-house-number", + dest="require_house_number", + action="store_false", + help="Include all addresses (sweep street-only entries too — most return 0).", + ) args = p.parse_args() - addresses = _addresses_to_sweep(args.limit, args.skip_recent_days, args.address) + addresses = _addresses_to_sweep( + args.limit, + args.skip_recent_days, + args.address, + require_house_number=args.require_house_number, + ) if not addresses: print("No addresses to sweep (all recently cached or none match query).", flush=True) return