Поиск авиабилетов
Готовые к запуску примеры поиска цен на авиабилеты: самые дешёвые и самые быстрые варианты, полные детали маршрута и сравнение для нескольких пассажиров. Определения полей см. в справочнике Авиабилеты. Используются коды IATA (не ICAO). Результаты кэшируются на 1 час — цены ориентировочные и могут измениться в момент бронирования.
| # | Вопрос | Используемые данные |
|---|---|---|
| 1 | Найти самые дешёвые и самые быстрые варианты для JFK → LAX | GET /tickets/search |
| 2 | Показать полный маршрут с деталями пересадок для LHR → JFK | GET /tickets/search |
| 3 | Поиск для 2 пассажиров LHR → CDG — сравнить все варианты | GET /tickets/search |
Требования
x-api-key в каждом запросе (прямая подписка). Подробнее →Установка
Приведённые ниже скрипты используют requests для вызовов API и rich для вывода в терминал. Установите один раз:
pip install requests rich1. Самый дешёвый и самый быстрый: JFK → LAX
Вопрос: какие варианты билетов на маршруте JFK–LAX самые дешёвые и самые быстрые?
API возвращает результаты, отсортированные от самых дешёвых. Самый быстрый вариант найдите, просмотрев total_duration_min.
import os
import requests
from rich.console import Console
from rich.panel import Panel
console = Console()
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
def fetch_tickets(
origin: str,
destination: str,
date: str | None = None,
passengers: int = 1,
) -> dict | None:
params: dict[str, str | int] = {
"origin": origin,
"destination": destination,
"passengers": passengers,
}
if date:
params["date"] = date
r = requests.get(
f"{BASE}/tickets/search",
headers=HEADERS,
params=params,
timeout=(10, 15),
)
if r.status_code == 404:
return None
r.raise_for_status()
return r.json()
def fmt_mins(minutes: int | None) -> str:
if minutes is None:
return "—"
return f"{minutes // 60}h {minutes % 60:02d}m"
def stops_label(stops: int) -> str:
return "Nonstop" if stops == 0 else f"{stops} stop(s)"
def flight_summary(flight: dict) -> str:
legs = flight.get("legs", [])
first_leg = legs[0] if legs else {}
return (
f"${flight.get('price_usd', 0):.2f} · "
f"{stops_label(flight.get('stops', 0))} · "
f"{fmt_mins(flight.get('total_duration_min'))} · "
f"{first_leg.get('flight_number', '—')} ({first_leg.get('airline', '—')})"
)
def main() -> None:
data = fetch_tickets("JFK", "LAX")
if not data:
console.print("[red]No ticket data returned.[/red]")
return
flights = data.get("flights", [])
if not flights:
console.print("[yellow]No flights available for JFK → LAX.[/yellow]")
return
cheapest = flights[0]
fastest = min(flights, key=lambda f: f.get("total_duration_min") or 99999)
console.print(
Panel(
f"[bold green]Cheapest[/bold green]\n{flight_summary(cheapest)}",
title="JFK → LAX",
style="green",
)
)
if fastest is not cheapest:
console.print(
Panel(
f"[bold cyan]Fastest[/bold cyan]\n{flight_summary(fastest)}",
title="JFK → LAX",
style="cyan",
)
)
else:
console.print("[dim]Cheapest option is also the fastest.[/dim]")
if __name__ == "__main__":
main()Результат: две панели — самый дешёвый и самый быстрый вариант, — в каждой показаны цена, количество пересадок, общая продолжительность, а также номер рейса и авиакомпания первого сегмента. Если самый дешёвый вариант совпадает с самым быстрым, показывается только одна панель.
2. Полный маршрут с деталями пересадок: LHR → JFK
Вопрос: как выглядит маршрут с пересадкой, включая каждый сегмент и время ожидания на пересадках?
Найдите в результатах первый вариант с пересадкой и выведите каждый сегмент отдельной строкой, затем перечислите пункты пересадок со временем ожидания.
import os
import requests
from rich.console import Console
from rich.panel import Panel
from rich.table import Table
console = Console()
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
def fetch_tickets(origin: str, destination: str) -> dict | None:
r = requests.get(
f"{BASE}/tickets/search",
headers=HEADERS,
params={"origin": origin, "destination": destination, "passengers": 1},
timeout=(10, 15),
)
if r.status_code == 404:
return None
r.raise_for_status()
return r.json()
def fmt_mins(minutes: int | None) -> str:
if minutes is None:
return "—"
return f"{minutes // 60}h {minutes % 60:02d}m"
def print_itinerary(flight: dict, label: str) -> None:
console.print(
Panel(
f"[bold]{label}[/bold] · ${flight.get('price_usd', 0):.2f} · "
f"{fmt_mins(flight.get('total_duration_min'))}",
style="blue",
)
)
legs_table = Table(show_header=True, show_lines=True)
legs_table.add_column("Airline", style="cyan")
legs_table.add_column("Flight")
legs_table.add_column("From")
legs_table.add_column("To")
legs_table.add_column("Departs")
legs_table.add_column("Arrives")
legs_table.add_column("Duration")
for leg in flight.get("legs", []):
legs_table.add_row(
leg.get("airline", "—"),
leg.get("flight_number", "—"),
f"{leg.get('departure_airport', '—')} ({leg.get('departure_airport_name', '—')[:20]})",
f"{leg.get('arrival_airport', '—')} ({leg.get('arrival_airport_name', '—')[:20]})",
leg.get("departure_time", "—"),
leg.get("arrival_time", "—"),
fmt_mins(leg.get("duration_min")),
)
console.print(legs_table)
layovers = flight.get("layovers", [])
if layovers:
console.print("[bold]Layovers[/bold]")
for lw in layovers:
console.print(
f" {lw.get('airport', '—')} {lw.get('airport_name', '—')} "
f"[yellow]{fmt_mins(lw.get('duration_min'))} wait[/yellow]"
)
def main() -> None:
data = fetch_tickets("LHR", "JFK")
if not data:
console.print("[red]No ticket data returned.[/red]")
return
flights = data.get("flights", [])
if not flights:
console.print("[yellow]No flights available for LHR → JFK.[/yellow]")
return
connecting = next((f for f in flights if f.get("stops", 0) > 0), None)
if connecting:
print_itinerary(connecting, "Connecting Itinerary — LHR → JFK")
else:
console.print("[dim]No connecting flights in results — showing cheapest nonstop.[/dim]")
print_itinerary(flights[0], "Nonstop — LHR → JFK")
if __name__ == "__main__":
main()Результат: карточка маршрута с каждым сегментом (авиакомпания, номер рейса, аэропорты, время вылета и прилёта, продолжительность), за которой следует список пересадок со временем ожидания в каждом пункте. Если вариантов с пересадкой нет, выводится самый дешёвый беспересадочный рейс.
3. Все варианты для 2 пассажиров: LHR → CDG
Вопрос: какие варианты билетов доступны для 2 пассажиров на маршруте LHR–CDG?
Выведите все возвращённые варианты в виде сравнительной таблицы. Показывайте исходную валюту, если она отличается от USD.
import os
import requests
from rich.console import Console
from rich.table import Table
console = Console()
HEADERS = {
"X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
"X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"
def fetch_tickets(
origin: str, destination: str, passengers: int
) -> dict | None:
r = requests.get(
f"{BASE}/tickets/search",
headers=HEADERS,
params={
"origin": origin,
"destination": destination,
"passengers": passengers,
},
timeout=(10, 15),
)
if r.status_code == 404:
return None
r.raise_for_status()
return r.json()
def fmt_mins(minutes: int | None) -> str:
if minutes is None:
return "—"
return f"{minutes // 60}h {minutes % 60:02d}m"
def stops_label(stops: int) -> str:
return "Nonstop" if stops == 0 else f"{stops} stop(s)"
def main() -> None:
passengers = 2
data = fetch_tickets("LHR", "CDG", passengers=passengers)
if not data:
console.print("[red]No ticket data returned.[/red]")
return
flights = data.get("flights", [])
if not flights:
console.print("[yellow]No flights available for LHR → CDG.[/yellow]")
return
table = Table(
title=f"LHR → CDG — {len(flights)} option(s) for {passengers} passengers",
show_lines=True,
)
table.add_column("#", justify="right", style="dim")
table.add_column("Price (USD)", justify="right", style="bold green")
table.add_column("Price/pax", justify="right")
table.add_column("Duration", justify="center")
table.add_column("Stops", justify="center")
table.add_column("First Flight")
for i, flight in enumerate(flights, start=1):
price = flight.get("price_usd", 0.0)
per_pax = price / passengers if passengers else price
orig_price = flight.get("original_price")
orig_currency = flight.get("original_currency", "USD")
price_cell = f"${price:.2f}"
if orig_currency and orig_currency != "USD" and orig_price:
price_cell += f"\n[dim]({orig_price:.0f} {orig_currency})[/dim]"
legs = flight.get("legs", [])
first = legs[0] if legs else {}
first_flight = (
f"{first.get('flight_number', '—')} {first.get('airline', '—')}"
)
table.add_row(
str(i),
price_cell,
f"${per_pax:.2f}",
fmt_mins(flight.get("total_duration_min")),
stops_label(flight.get("stops", 0)),
first_flight,
)
console.print(table)
console.print(
"[dim]Prices are market snapshots — confirm at booking. "
"Results cached for 1 hour.[/dim]"
)
if __name__ == "__main__":
main()Результат: таблица со всеми доступными вариантами: общая цена, цена на одного пассажира, продолжительность, количество пересадок и номер рейса первого сегмента. Если исходная валюта отличается от USD, она показывается под ценой в USD.