Show Eurostar Standard prices and total journey cost on results page
Fetches prices via the site-api.eurostar.com GraphQL gateway (NewBookingSearch operation, discovered with Playwright). Adds fetch_prices() to scraper/eurostar.py using requests, caches results, annotates each trip with eurostar_price and total_price, and shows an ES Std column plus total cost (duration + price) in the results table. The Transfer column is hidden on small screens for mobile usability. Closes #4 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
804fcedfad
commit
0dee942e16
4 changed files with 191 additions and 12 deletions
29
app.py
29
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],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue