Skip to content

Instantly share code, notes, and snippets.

@Romern
Last active December 17, 2024 07:22
Show Gist options
  • Save Romern/3387f971f5717054e7cee6e018c4ce7e to your computer and use it in GitHub Desktop.
Save Romern/3387f971f5717054e7cee6e018c4ce7e to your computer and use it in GitHub Desktop.
Retrieve blablacar results for multiple days

Example:

$ python3 blablacar.py Hamburg Ulm 2024-12-16 2024-12-23
                           BlaBlaCar Trips from Hamburg to Ulm on 2024-12-16 to 2024-12-23
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Departure Time            ┃ From Location                    ┃ To Location                               ┃ Price   ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ 2024-12-18T08:00:00+01:00 │ Hamburg, Massaquoipassage 2      │ Elchingen, Pendlerparkplatz Oberelchingen │ 46,99 € │
│ 2024-12-18T09:30:00+01:00 │ Hamburg, Steintorwall 18-20      │ Ulm, Am Lederhof 1                        │ 32,19 € │
│ 2024-12-18T11:00:00+01:00 │ Hamburg, Burgstraße              │ Neu-Ulm, Harzweg 2                        │ 49,59 € │
│ 2024-12-19T16:00:00+01:00 │ Hamburg, Reeperbahn 71           │ Neu-Ulm, Memminger Str. 58                │ 61,89 € │
│ 2024-12-19T18:00:00+01:00 │ Hamburg, Theodor-Heuss-Platz 1   │ Ulm, Eberhard-Finckh-Straße 38            │ 43,39 € │
│ 2024-12-21T09:00:00+01:00 │ Hamburg, Hamburg-Altona          │ Aalen, Bahnhof 1                          │ 37,19 € │
│ 2024-12-21T09:20:00+01:00 │ Hamburg, Salzbrenner Imbiss      │ Neu-Ulm, Aral - Otto-Renner-Straße 1      │ 54,49 € │
│ 2024-12-21T11:30:00+01:00 │ Hamburg, Bahrenfelder Marktplatz │ Aalen, Thurn-und-Taxis-Straße 52          │ 32,19 € │
│ 2024-12-21T13:00:00+01:00 │ Hamburg, Woltmanstraße 24        │ Ulm, K9906 21                             │ 69,39 € │
└───────────────────────────┴──────────────────────────────────┴───────────────────────────────────────────┴─────────┘
import requests
import datetime
import click
import tqdm
import uuid
from rich.console import Console
from rich.table import Table
search_url = "https://edge.blablacar.de/trip/search/v7"
location_get_url = 'https://edge.blablacar.de/location/suggestions'
cookie_get_url = "https://www.blablacar.de/secure-user"
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0",
"Accept": "application/json",
"Accept-Language": "de-DE",
"Content-Type": "application/json",
"x-client": "SPA|1.0.0",
"x-currency": "EUR",
"x-locale": "de_DE",
"x-visitor-id": str(uuid.uuid4())
}
def search(from_place_id: str, to_place_id: str, departure_date: datetime.date, requested_seats = 1):
url_params = {
"from_place_id": from_place_id,
"to_place_id": to_place_id,
"departure_date": departure_date.isoformat(),
"search_uuid": str(uuid.uuid4()),
"requested_seats":"1",
"search_origin":"SEARCH"
}
return requests.get(search_url, params=url_params, headers=headers).json()
def get_location(location_name: str) -> str:
url_params = {
"with_user_history": "true",
"locale": "de_DE",
"query": location_name
}
return requests.get(location_get_url, params=url_params, headers=headers).json()[0]['id']
def prepare_session():
resp = requests.get(cookie_get_url, headers=headers)
headers["Authorization"] = "Bearer " + resp.cookies.get("app_token")
def print_search_range(from_location: str, to_location: str, from_date: datetime.date, to_date: datetime.date, requested_seats = 1):
table = Table(title=f"BlaBlaCar Trips from {from_location} to {to_location} on {from_date.isoformat()} to {to_date.isoformat()}")
table.add_column("Departure Time")
table.add_column("From Location")
table.add_column("To Location")
table.add_column("Price")
prepare_session()
from_place_id = get_location(from_location)
to_place_id = get_location(to_location)
for day in tqdm.trange((to_date - from_date).days + 1, desc="Retrieving trips for days", leave=False):
search_results = search(from_place_id, to_place_id, from_date + datetime.timedelta(days=day), requested_seats)
for trip in search_results['trips']:
table.add_row(trip['waypoints'][0]['departure_datetime'],
f"{trip['waypoints'][0]['place']['city']}, {trip['waypoints'][0]['place']['address']}",
f"{trip['waypoints'][-1]['place']['city']}, {trip['waypoints'][-1]['place']['address']}",
trip['price_details']['price'])
console = Console()
console.print(table)
@click.command()
@click.argument('from_location')
@click.argument('to_location')
@click.argument('from_date')
@click.argument('to_date')
@click.option("--requestedseats", default=1)
def main(from_location: str, to_location: str, from_date: str, to_date: str, requestedseats):
print_search_range(from_location, to_location, datetime.date.fromisoformat(from_date), datetime.date.fromisoformat(to_date), requested_seats=requestedseats)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment