This commit is contained in:
Andras Schmelczer 2026-07-12 20:30:19 +01:00
parent 6df2812a4e
commit 9e4e65fa2a
35 changed files with 1172 additions and 70 deletions

View file

@ -10,8 +10,16 @@ from transform import map_property_type, normalize_postcode
log = logging.getLogger("rightmove")
def write_parquet(properties: list[dict], path: Path) -> None:
"""Write sale properties list to parquet with server-ready column names."""
def write_parquet(
properties: list[dict], path: Path, price_history: dict | None = None
) -> None:
"""Write sale properties list to parquet with server-ready column names.
``price_history`` is the persistent listing-id -> [{date, price, reason}]
store (see finder/price_history.py); each listing's accrued asking-price
series is embedded as a ``price_history`` list column. Absent id -> empty
list, so pre-instrumentation runs and tests simply write empty series.
"""
if not properties:
log.warning("No properties to write to %s", path)
return
@ -95,6 +103,14 @@ def write_parquet(properties: list[dict], path: Path) -> None:
asking_prices = [p["price"] if p["price"] > 0 else None for p in properties]
listing_statuses = ["For sale"] * len(properties)
# Accrued asking-price history per listing (oldest -> newest). Look up with
# the SAME normalisation the store keys on (str(id).strip(), matching
# price_history.update_history and scraper dedup); an unseen id -> empty.
history_lookup = price_history or {}
price_history_col = [
history_lookup.get(str(p.get("id")).strip(), []) for p in properties
]
df = pl.DataFrame(
{
"Bedrooms": [p["Bedrooms"] for p in properties],
@ -144,6 +160,7 @@ def write_parquet(properties: list[dict], path: Path) -> None:
"Listing date": listing_dates,
"Listing status": listing_statuses,
"Asking price": asking_prices,
"price_history": price_history_col,
},
schema={
"Bedrooms": pl.Int32,
@ -169,6 +186,11 @@ def write_parquet(properties: list[dict], path: Path) -> None:
"Listing date": pl.Datetime("us"),
"Listing status": pl.Utf8,
"Asking price": pl.Int64,
"price_history": pl.List(
pl.Struct(
{"date": pl.Utf8, "price": pl.Int64, "reason": pl.Utf8}
)
),
},
)