This commit is contained in:
Andras Schmelczer 2026-07-03 18:28:56 +01:00
parent 909e241907
commit 1ee796b282
29 changed files with 250 additions and 126 deletions

View file

@ -149,7 +149,7 @@ def map_property_type(sub_type: str | None) -> str:
return "Terraced"
if "house" in lower or "cottage" in lower:
return "Detached"
log.warning("Unknown propertySubType: %r mapping to Other", sub_type)
log.warning("Unknown propertySubType: %r, mapping to Other", sub_type)
return "Other"
@ -267,7 +267,7 @@ def build_register_address(
property's own number or name (e.g. Zoopla detail pages expose
``propertyNumberOrName`` = "12" or "Martham Mill"), prepend it so the address
carries the house identifier that the EPC/Price-Paid register addresses also
use turning a fuzzy street match into a near-exact one. Falls back to the
use, turning a fuzzy street match into a near-exact one. Falls back to the
plain cleaned address when no number/name is available.
"""
cleaned = clean_listing_address(raw_address)
@ -282,6 +282,23 @@ def build_register_address(
return f"{number_or_name}, {cleaned}" if cleaned else number_or_name
def build_listing_url(property_url: str | None, is_new_build: bool) -> str:
"""Build the canonical Rightmove listing URL with an explicit channel marker.
The search API always echoes ``?channel=RES_BUY`` in ``propertyUrl`` even for
new-build developments (the request channel stays BUY), so the channel is
re-stamped here from the per-listing ``development`` flag: ``RES_NEW`` for new
builds, ``RES_BUY`` for ordinary resale. The map UI reads this marker to split
new vs non-new listings. Any channel/fragment already on ``propertyUrl`` is
stripped first so the result is deterministic.
"""
if not property_url:
return ""
base = property_url.split("#", 1)[0].split("?", 1)[0]
channel = "RES_NEW" if is_new_build else "RES_BUY"
return f"{RIGHTMOVE_BASE}{base}#/?channel={channel}"
def transform_property(
prop: dict,
outcode: str,
@ -337,7 +354,7 @@ def transform_property(
inferred_postcode = pc_index.nearest(lat, lng)
if not inferred_postcode:
log.debug("No England postcode for property at %.4f, %.4f skipping", lat, lng)
log.debug("No England postcode for property at %.4f, %.4f; skipping", lat, lng)
return None
raw_address = prop.get("displayAddress", "") or ""
extracted_postcode = extract_full_postcode(raw_address)
@ -391,7 +408,7 @@ def transform_property(
"price_frequency": "",
"Price qualifier": price_qualifier,
"Total floor area (sqm)": parse_display_size(prop.get("displaySize")),
"Listing URL": RIGHTMOVE_BASE + property_url if property_url else "",
"Listing URL": build_listing_url(property_url, bool(prop.get("development"))),
"Listing features": key_features,
"first_visible_date": prop.get("firstVisibleDate", ""),
}