Save up to 17% with yearly billing

See pricing

Поиск воздушных судов

Готовые к запуску примеры получения метаданных воздушного судна по бортовому номеру и шестнадцатеричному коду ICAO. Определения полей и структура ответа описаны в полном справочнике Поиск воздушных судов.

#ВопросИспользуемые данные
1Какой тип ВС и какой эксплуатант у бортового номера N636JB?/aircraft/registration/{registration}
2Получить фото воздушного судна по бортовому номеру для отображения флота/aircraft/registration/{registration} с photos=true
3Пакетно определить типы и эксплуатантов для трёх бортовых номеров/aircraft/registration/{registration}

Требования

Авторизация
x-api-key в каждом запросе (прямая подписка). Подробнее →

Установка

Приведённые ниже скрипты используют requests для вызовов API и rich для вывода в терминал. Установите один раз:

pip install requests rich

1. Определение типа ВС и эксплуатанта по бортовому номеру

Вопрос: Какого типа воздушное судно N636JB и кто его эксплуатирует?

Поиск по реестру — отправная точка для анализа состава флота, отображения фотографий и последующих запросов характеристик. Поле found однозначно сообщает, есть ли регистрационный номер в реестре воздушных судов SkyLink.

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"

REGISTRATION = "N636JB"


def fetch_aircraft(registration: str) -> dict | None:
    r = requests.get(
        f"{BASE}/aircraft/registration/{registration}",
        headers=HEADERS,
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return None
    r.raise_for_status()
    return r.json()


def main() -> None:
    data = fetch_aircraft(REGISTRATION)

    if data is None or not data.get("found"):
        console.print(f"[yellow]⚠ Registration {REGISTRATION} not found in registry.[/yellow]")
        return

    ac = data["aircraft"]
    lines = [
        f"[bold]Registration:[/bold]  {ac['registration']}",
        f"[bold]ICAO24:[/bold]        {ac['icao24']}",
        f"[bold]ICAO Type:[/bold]     {ac['icao_type']}",
        f"[bold]Full Name:[/bold]     {ac['type_name']}",
        f"[bold]Operator:[/bold]      {ac['owner_operator']}",
    ]
    console.print(Panel("\n".join(lines), title=f"Aircraft — {REGISTRATION}", border_style="cyan"))


if __name__ == "__main__":
    main()

Результат: Панель с регистрационным номером, шестнадцатеричным кодом, кодом типа ICAO, полным названием типа и эксплуатантом.

Совет: кэшируйте ответы реестра на срок до 24 часов — регистрационные данные воздушных судов меняются редко, а повторные запросы одного и того же бортового номера впустую расходуют квоту.


2. Получение фото воздушного судна по бортовому номеру

Вопрос: Есть ли у N636JB фотография от сообщества, которую можно показать в карточке флота?

Передайте photos=true, чтобы включить в ответ массив photos. Фотографии предоставляет сообщество, и они есть не всегда — проверяйте длину массива перед отрисовкой.

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"

REGISTRATION = "N636JB"


def fetch_aircraft_with_photos(registration: str) -> dict | None:
    r = requests.get(
        f"{BASE}/aircraft/registration/{registration}",
        headers=HEADERS,
        params={"photos": "true"},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return None
    r.raise_for_status()
    return r.json()


def main() -> None:
    data = fetch_aircraft_with_photos(REGISTRATION)

    if data is None or not data.get("found"):
        console.print(f"[yellow]⚠ Registration {REGISTRATION} not found.[/yellow]")
        return

    ac = data["aircraft"]
    photos = ac.get("photos") or []

    if not photos:
        console.print(f"[yellow]No photos available for {REGISTRATION}.[/yellow]")
        console.print("Photos are community-sourced and may not be present for every aircraft.")
        return

    first_photo = photos[0]["image"]
    icao_type = ac["icao_type"]

    lines = [
        f"[bold]Registration:[/bold]  {ac['registration']}",
        f"[bold]Type:[/bold]          {ac['type_name']}",
        f"[bold]Operator:[/bold]      {ac['owner_operator']}",
        f"[bold]Photo URL:[/bold]     [link={first_photo}]{first_photo}[/link]",
        f"[bold]Total photos:[/bold]  {len(photos)}",
    ]
    console.print(Panel("\n".join(lines), title="Fleet Card", border_style="blue"))
    console.print(
        f"\n[dim]Chain to /aircraft/performance/{icao_type} for performance specs.[/dim]"
    )


if __name__ == "__main__":
    main()

Результат: Панель с URL первой фотографии, типом и эксплуатантом. Если фотографий нет, выводится предупреждение.

Следующий шаг: используйте поле icao_type для запроса к /aircraft/performance/{icao_type}, чтобы получить лётно-технические характеристики вместе с фотографией.


3. Пакетный поиск: определение типов для нескольких бортовых номеров

Вопрос: Какие типы и эксплуатанты соответствуют списку бортовых номеров из разных реестров?

Используйте ThreadPoolExecutor для параллельного получения данных по регистрационным номерам. Корректно обрабатывайте found=false для незарегистрированных или неизвестных воздушных судов.

import os
from concurrent.futures import ThreadPoolExecutor, as_completed

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"

REGISTRATIONS = ["N636JB", "G-EUUU", "D-AIBL"]


def fetch_aircraft(registration: str) -> tuple[str, dict | None]:
    r = requests.get(
        f"{BASE}/aircraft/registration/{registration}",
        headers=HEADERS,
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return registration, None
    r.raise_for_status()
    return registration, r.json()


def main() -> None:
    results: dict[str, dict | None] = {}

    with ThreadPoolExecutor(max_workers=5) as pool:
        futures = {pool.submit(fetch_aircraft, reg): reg for reg in REGISTRATIONS}
        for future in as_completed(futures):
            reg, data = future.result()
            results[reg] = data

    table = Table(title="Batch Aircraft Lookup", border_style="cyan")
    table.add_column("Registration", style="bold")
    table.add_column("Found", justify="center")
    table.add_column("ICAO Type")
    table.add_column("Full Name")
    table.add_column("Operator")

    for reg in REGISTRATIONS:
        data = results.get(reg)
        if data is None or not data.get("found"):
            table.add_row(reg, "[red]✗[/red]", "—", "—", "—")
        else:
            ac = data["aircraft"]
            table.add_row(
                ac["registration"],
                "[green]✓[/green]",
                ac["icao_type"],
                ac["type_name"],
                ac["owner_operator"],
            )

    console.print(table)


if __name__ == "__main__":
    main()

Результат: Таблица с одной строкой на каждый регистрационный номер: Регистрационный номер | Найден | Тип ICAO | Полное название | Эксплуатант. Для ненайденных номеров отображаются ✗ и прочерки.