diff --git a/app.py b/app.py index db0eeb0..aa61d15 100644 --- a/app.py +++ b/app.py @@ -8,6 +8,7 @@ from cache import get_cached, set_cached import scraper.eurostar as eurostar_scraper import scraper.realtime_trains as rtt_scraper from trip_planner import combine_trips, find_unreachable_morning_eurostars +from scraper.eurostar import fetch_prices as fetch_eurostar_prices RTT_PADDINGTON_URL = ( "https://www.realtimetrains.co.uk/search/detailed/" @@ -80,10 +81,12 @@ def results(slug, travel_date): rtt_cache_key = f"rtt_{travel_date}" es_cache_key = f"eurostar_{travel_date}_{destination}" + prices_cache_key = f"eurostar_prices_{travel_date}_{destination}" cached_rtt = get_cached(rtt_cache_key) cached_es = get_cached(es_cache_key) - from_cache = bool(cached_rtt and cached_es) + cached_prices = get_cached(prices_cache_key) + from_cache = bool(cached_rtt and cached_es and cached_prices) error = None @@ -108,7 +111,28 @@ def results(slug, travel_date): msg = f"Could not fetch Eurostar times: {e}" error = f"{error}; {msg}" if error else msg + if cached_prices: + eurostar_prices = cached_prices + else: + try: + eurostar_prices = fetch_eurostar_prices(destination, travel_date) + set_cached(prices_cache_key, eurostar_prices) + except Exception as e: + eurostar_prices = {} + msg = f"Could not fetch Eurostar prices: {e}" + error = f"{error}; {msg}" if error else msg + trips = combine_trips(gwr_trains, eurostar_trains, travel_date, min_connection, max_connection) + + # Annotate each trip with Eurostar Standard price and total cost + for trip in trips: + es_price = eurostar_prices.get(trip['depart_st_pancras']) + trip['eurostar_price'] = es_price + if es_price is not None: + trip['total_price'] = trip['ticket_price'] + es_price + else: + trip['total_price'] = None + unreachable_morning_services = find_unreachable_morning_eurostars( gwr_trains, eurostar_trains, @@ -116,6 +140,9 @@ def results(slug, travel_date): min_connection, max_connection, ) + for svc in unreachable_morning_services: + svc['eurostar_price'] = eurostar_prices.get(svc['depart_st_pancras']) + result_rows = sorted( [{'row_type': 'trip', **trip} for trip in trips] + [{'row_type': 'unreachable', **service} for service in unreachable_morning_services], diff --git a/scraper/eurostar.py b/scraper/eurostar.py index 7e9f3e7..8ae5129 100644 --- a/scraper/eurostar.py +++ b/scraper/eurostar.py @@ -1,7 +1,7 @@ """ -Scrape Eurostar timetable via httpx. +Scrape Eurostar timetable via httpx and fetch prices via the GraphQL API. -The route-specific timetable pages are Next.js SSR — all departure data is +Timetable: route-specific pages are Next.js SSR — all departure data is embedded in