diff --git a/pyproject.toml b/pyproject.toml index f422258..eb3cf93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "scrapebadger" -version = "0.13.1" +version = "0.14.0" description = "Official Python SDK for ScrapeBadger - Async web scraping APIs for Twitter and more" readme = "README.md" license = { text = "MIT" } diff --git a/src/scrapebadger/google/flights.py b/src/scrapebadger/google/flights.py index a4e235a..a87c8b3 100644 --- a/src/scrapebadger/google/flights.py +++ b/src/scrapebadger/google/flights.py @@ -83,7 +83,11 @@ async def search( Returns: Response with `best_flights[]`, `other_flights[]`, - `price_insights`, `airports[]`, and trip-type metadata. + `price_insights`, `airports[]`, a `search_url`, and trip-type + metadata. Each offer carries a `booking_url` (deep link that + pre-selects the flight) and a `selection_token` for + :meth:`booking_options`; each leg carries the flight number, + departure/arrival times, airport names, and aircraft. """ params: dict[str, Any] = { "departure_id": departure_id, @@ -105,3 +109,53 @@ async def search( if max_price is not None: params["max_price"] = max_price return await self._client.get("/v1/google/flights/search", params=params) + + async def booking_options( + self, + selection_token: str, + *, + currency: str = "USD", + gl: str = "us", + hl: str = "en", + ) -> dict[str, Any]: + """Retrieve the provider booking list for a selected itinerary. + + Given the ``selection_token`` from a :meth:`search` offer (one-way or + fully-selected itinerary), returns the airline/OTA providers that can + book it. This renders the Google Flights booking page, so it is slower + than :meth:`search`. The actual per-provider booking links open from + the returned ``booking_url``. + + Args: + selection_token: ``selection_token`` from a search offer. + currency: ISO-4217 currency code (default "USD"). + gl: Country code. + hl: Language for the returned ``booking_url``. + + Returns: + Response with ``booking_options[]`` (each ``book_with``, ``price``, + ``currency``, ``type``), a ``booking_url``, and ``currency``. + + Example: + ```python + flights = await client.google.flights.search( + departure_id="CNF", arrival_id="GRU", + outbound_date="2026-06-25", trip_type="one_way", currency="BRL", + ) + token = flights["best_flights"][0]["selection_token"] + options = await client.google.flights.booking_options( + token, currency="BRL", gl="br", + ) + for opt in options["booking_options"]: + print(opt["book_with"], opt["price"], opt["currency"]) + ``` + """ + return await self._client.get( + "/v1/google/flights/booking_options", + params={ + "selection_token": selection_token, + "currency": currency, + "gl": gl, + "hl": hl, + }, + ) diff --git a/tests/test_google.py b/tests/test_google.py index 6d37169..4852cbb 100644 --- a/tests/test_google.py +++ b/tests/test_google.py @@ -193,6 +193,33 @@ async def test_details(self, google: GoogleClient, mock_base_client: MagicMock) assert kwargs["params"]["property_token"] == "PTOKEN" +class TestFlightsClient: + @pytest.mark.asyncio + async def test_search(self, google: GoogleClient, mock_base_client: MagicMock) -> None: + await google.flights.search( + "CNF", + "GRU", + "2026-06-25", + trip_type="one_way", + currency="BRL", + gl="br", + hl="pt-BR", + ) + args, kwargs = mock_base_client.get.call_args + assert args[0] == "/v1/google/flights/search" + assert kwargs["params"]["departure_id"] == "CNF" + assert kwargs["params"]["trip_type"] == "one_way" + assert kwargs["params"]["currency"] == "BRL" + + @pytest.mark.asyncio + async def test_booking_options(self, google: GoogleClient, mock_base_client: MagicMock) -> None: + await google.flights.booking_options("CBwQAhxx", currency="BRL", gl="br") + args, kwargs = mock_base_client.get.call_args + assert args[0] == "/v1/google/flights/booking_options" + assert kwargs["params"]["selection_token"] == "CBwQAhxx" + assert kwargs["params"]["currency"] == "BRL" + + class TestTrendsClient: @pytest.mark.asyncio async def test_interest(self, google: GoogleClient, mock_base_client: MagicMock) -> None: diff --git a/uv.lock b/uv.lock index 7aee908..b38c922 100644 --- a/uv.lock +++ b/uv.lock @@ -752,7 +752,7 @@ wheels = [ [[package]] name = "scrapebadger" -version = "0.13.0" +version = "0.14.0" source = { editable = "." } dependencies = [ { name = "httpx" },