import os from pathlib import Path FINDER_DIR = Path(__file__).resolve().parent REPO_DIR = FINDER_DIR.parent DATA_DIR = Path(os.environ.get("DATA_DIR", str(FINDER_DIR / "data"))) ARCGIS_PATH = Path( os.environ.get("ARCGIS_PATH", str(REPO_DIR / "property-data" / "arcgis_data.parquet")) ) PAGE_SIZE = 24 DELAY_BETWEEN_PAGES = 0.3 DELAY_BETWEEN_OUTCODES = 0.5 MAX_RETRIES = 3 RETRY_BASE_DELAY = 2.0 GRID_CELL_SIZE = 0.01 # degrees for postcode spatial index MAX_BEDROOMS = 20 # sanity cap — values above this are almost certainly parsing errors TYPEAHEAD_URL = "https://los.rightmove.co.uk/typeahead" SEARCH_URL = "https://www.rightmove.co.uk/api/property-search/listing/search" RIGHTMOVE_BASE = "https://www.rightmove.co.uk" # home.co.uk HOMECOUK_BASE = "https://home.co.uk" HOMECOUK_API_BASE = f"{HOMECOUK_BASE}/api" HOMECOUK_PER_PAGE = 30 # max supported by the API # Zoopla ZOOPLA_BASE = "https://www.zoopla.co.uk" # Greater London-ish postcode areas. This intentionally uses broad area # prefixes so a manual scrape can include central/inner London plus common # outer-London and near-London outcodes without maintaining a long borough list. LONDON_OUTCODE_PREFIXES = { "E", "EC", "N", "NW", "SE", "SW", "W", "WC", "BR", "CR", "DA", "EN", "HA", "IG", "KT", "RM", "SM", "TW", "UB", "WD", } PROPERTY_TYPE_MAP = { "Detached": "Detached", "Semi-Detached": "Semi-Detached", "Terraced": "Terraced", "End of Terrace": "Terraced", "Mid Terrace": "Terraced", "Flat": "Flats/Maisonettes", "Maisonette": "Flats/Maisonettes", "Studio": "Flats/Maisonettes", "Apartment": "Flats/Maisonettes", "Penthouse": "Flats/Maisonettes", "Ground Flat": "Flats/Maisonettes", "Duplex": "Flats/Maisonettes", "Detached Bungalow": "Detached", "Semi-Detached Bungalow": "Semi-Detached", "Town House": "Terraced", "Link Detached": "Detached", "Link Detached House": "Detached", "Bungalow": "Other", "Cottage": "Other", "Park Home": "Other", "Mobile Home": "Other", "Caravan": "Other", "Lodge": "Other", "Land": "Other", "Farm / Barn": "Other", "Farm House": "Other", "House": "Detached", "House of Multiple Occupation": "Other", "House Share": "Other", "Not Specified": "Other", "Chalet": "Other", "Barn Conversion": "Other", "Coach House": "Other", "Character Property": "Other", "Cluster House": "Other", "Retirement Property": "Other", "Parking": "Other", "Plot": "Other", "Garages": "Other", "Mews": "Terraced", "Property": "Other", "Flat Share": "Other", "Block of Apartments": "Other", "Private Halls": "Other", "Terraced Bungalow": "Terraced", "Equestrian Facility": "Other", "Ground Maisonette": "Flats/Maisonettes", "Country House": "Detached", "Village House": "Detached", "Farm Land": "Other", "House Boat": "Other", "Barn": "Other", "Serviced Apartments": "Other", # Space-separated variants (from home.co.uk underscore/hyphen normalization) "Semi Detached": "Semi-Detached", "Semi Detached Bungalow": "Semi-Detached", "End Of Terrace": "Terraced", "End Terrace": "Terraced", "Block Of Apartments": "Other", # Lowercase variants (from home.co.uk / Rightmove APIs) "house": "Detached", "bungalow": "Other", "townhouse": "Terraced", "land": "Other", "other": "Other", "not-specified": "Other", "retirement-property": "Other", "equestrian-facility": "Other", "flat": "Flats/Maisonettes", "detached": "Detached", "semi-detached": "Semi-Detached", "terraced": "Terraced", "maisonette": "Flats/Maisonettes", "apartment": "Flats/Maisonettes", "studio": "Flats/Maisonettes", "penthouse": "Flats/Maisonettes", "cottage": "Other", "chalet": "Other", "farm_house": "Detached", "country house": "Detached", "village house": "Detached", } CHANNELS = [ {"channel": "BUY", "transactionType": "BUY", "sortType": "2"}, ]