Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Cетевой анализ с использованием внешних API

В предыдущем разделе мы выполняли сетевой анализ, используя локально построенный граф и библиотеку networkx.

В этом разделе мы рассмотрим альтернативу — внешние API сервисы маршрутизации. Вычисления будут происходить на стороне сервисов, а необходимые данные будем получать по запросу.

Чтобы работать с такими сервисами, необходимо понимать, как устроены API: как формируются запросы, какие параметры в них передаются и как обрабатывать полученные ответы.

В начале раздела мы разберём базовые принципы работы с API. Затем поработаем с несколькими сервисами для сетевого анализа: OSRM, OpenRouteService, GraphHopper.

0. Импорт библиотек

import requests
import geopandas as gpd
  • Requests (requests) — библиотека Python для отправки HTTP-запросов и работы с веб-сервисами (API). Позволяет получать данные с серверов (GET), отправлять данные (POST) и обрабатывать ответы, в том числе в формате JSON. Упрощает взаимодействие с внешними API и широко используется для загрузки и обмена данными через интернет.

1. Application Programming Interface (API)

API (Application Programming Interface) — это интерфейс, который позволяет программам взаимодействовать друг с другом.

В нашем случае API — это веб-сервис, к которому мы отправляем запрос с параметрами (например, координатами), а в ответ получаем данные (например, маршрут или расстояние).

Такой запрос называется HTTP-запросом — это стандартный способ обмена данными между клиентом (нашей программой) и сервером.

1.1. Как устроен запрос к API

Запрос к API обычно состоит из:

  • URL — адрес сервиса (например, https://api.service.com/route);

  • параметров — входные данные (координаты, тип транспорта и т.д.);

  • заголовков (headers) — дополнительная информация (например, API-ключ или формат данных).

1.2. Типы запросов

В HTTP существует несколько типов запросов (методов), каждый из которых используется для определённого типа операций:

  • GET — используется для получения данных с сервера. Параметры передаются в URL.

  • POST — используется для отправки данных на сервер. Параметры передаются в теле запроса. Часто применяется для выполнения вычислений.

  • PUT — используется для полного обновления существующего ресурса на сервере.

  • PATCH — используется для частичного обновления ресурса (изменения только отдельных полей).

  • DELETE — используется для удаления ресурса с сервера.

Для наших задач мы будем использовать в основном GET и POST запросы. Конкретный тип запроса для каждой операции всегда указан в документации соответствующего сервиса, поэтому при работе с API важно внимательно изучать описание каждого метода.

1.3. Работа с документацией

Каждый API имеет свою документацию, в которой описано:

  • какие есть методы (например, маршрут, матрица, изохроны);

  • какие параметры нужно передавать;

  • какой тип запроса использовать (GET, POST и др.);

  • в каком формате возвращается ответ.

Многие сервисы требуют API-ключ — уникальный идентификатор пользователя. Он нужен для контроля доступа к сервису, ограничения количества запросов (rate limits) и учёта использования API.

1.4. Библиотека requests

Для отправки запросов в Python мы будем использовать библиотеку requests.

После отправки запроса сервер возвращает ответ, который содержит:

  • status code — код ответа (например, 200 — успешно, 400 — ошибка запроса, 401 — ошибка авторизации);

  • тело ответа — данные, чаще всего в формате JSON;

  • заголовки ответа — дополнительная информация о результате запроса.

1.5. Проверка ответа сервера

После отправки запроса важно убедиться, что сервер обработал его успешно.

Для этого используют атрибут .status_code, который содержит HTTP-код ответа.

Наиболее часто встречаются следующие варианты:

  • 200 — запрос выполнен успешно, можно переходить к обработке ответа;

  • 4xx — ошибка на стороне клиента, например неверный URL, параметры запроса или API-ключ;

  • 5xx — ошибка на стороне сервера.

Если код ответа не равен 200, значит мы не можем переходить к обработке результата. Сначала нужно посмотреть, что именно сообщает сервер: код ответа и тело ответа часто помогают понять причину ошибки.

P.S.

Во многих сервисах маршрутизации доступны готовые Python-библиотеки, однако в этом разделе мы будем работать напрямую с API, чтобы лучше понять логику запросов.

2. API в сетевом анализе

В этом разделе мы рассмотрим несколько популярных API и научимся решать с их помощью основные задачи сетевого анализа:

  • находить кратчайшие маршруты;

  • получать расстояние и время в пути;

  • строить зоны доступности (изохроны);

  • рассчитывать матрицы расстояний.

Каждый сервис имеет свои особенности: формат запросов, набор доступных функций и ограничения по количеству запросов. Чтобы разобраться в них, мы будем обращаться к документации.

Для каждого сервиса мы разберём один или несколько примеров и последовательно пройдём весь процесс работы с API — от формирования запроса до обработки ответа и визуализации результата.

2.1. Open Source Routing Machine (OSRM)

OSRM (Open Source Routing Machine) — это быстрый и простой сервис маршрутизации с открытым исходным кодом, построенный на данных OpenStreetMap.

OSRM не требует API-ключа и позволяет выполнять запросы напрямую.

Документация

2.1.1 Кратчайшее расстояние

В документации OSRM описано, как формировать запрос для получения маршрута между двумя точками.

Для этого используется endpoint:

/route/v1/{profile}/{coordinates}

где:

  • profile — тип транспорта (например, driving);

  • coordinates — список точек в формате долгота,широта, разделённых ;.

Также в параметрах запроса можно указать дополнительные опции, например overview=full, чтобы получить геометрию маршрута.

2.1.1.1 Формирование URL запроса

Сформируем полный URL для обращения к API. Для этого зададим координаты начальной и конечной точки и приведём их к формату, ожидаемому сервисом.

base_url_osrm = "http://router.project-osrm.org/route/v1/driving/"

# Координаты (долгота, широта)
start_coords_osrm = [30.3521, 59.9446]
end_coords_osrm = [30.2865, 59.9240]

# Преобразуем координаты в строку
start = f"{start_coords_osrm[0]},{start_coords_osrm[1]}"
end = f"{end_coords_osrm[0]},{end_coords_osrm[1]}"

# Формируем полный URL
url_osrm = f"{base_url_osrm}{start};{end}?overview=full"

Важно: разные API могут использовать разный порядок координат. В одних сервисах координаты передаются как долгота, широта, в других — как широта, долгота. Поэтому перед отправкой запроса всегда нужно сверяться с документацией.

2.1.1.2 Отправка запроса

Отправим HTTP-запрос к API с помощью библиотеки requests.

response_osrm = requests.get(url_osrm)
2.1.1.3. Проверка статуса запроса

Перед обработкой ответа важно убедиться, что запрос выполнен успешно.

response_osrm.status_code
200

Если статус равен 200, можно переходить к обработке результата. Если код отличается от 200, стоит посмотреть, какую информацию сервер вернул в ответе, чтобы понять причину ошибки.

2.1.1.4. Обработка ответа

Ответ сервера приходит в формате JSON и может быть преобразован в Python-словарь с помощью метода .json()

data_osrm = response_osrm.json()

Посмотрим, какие ключи содержит JSON-объект, чтобы понять структуру данных и найти нужную информацию. Подробное описание структуры ответа можно найти в документации API.

data_osrm.keys()
dict_keys(['code', 'routes', 'waypoints'])

Основная информация о маршруте содержится в ключе routes, которое представляет собой список объектов. В нашем случае запрос был выполнен для одного маршрута, поэтому достаточно обратиться к первому элементу списка и изучить его структуру.

route_osrm = data_osrm["routes"][0]

route_osrm.keys()
dict_keys(['legs', 'weight_name', 'geometry', 'weight', 'duration', 'distance'])

Извлечём основные характеристики маршрута из ответа API.

distance_osrm = route_osrm["distance"]
duration_osrm = route_osrm["duration"]
geometry_osrm = route_osrm["geometry"]

print(f"Расстояние (метры): {distance_osrm}")
print(f"Время (секунды): {duration_osrm}")
print(f"Геометрия: {geometry_osrm[:50]}...")
Расстояние (метры): 5444.5
Время (секунды): 509.5
Геометрия: c|zlJuagxDBCLOV_@Z?L?F?H?BiF?c@?QN@n@@J@v@BL@?j@GH...

Геометрия маршрута возвращается в закодированном виде (формат polyline), чтобы уменьшить объём передаваемых данных. Для дальнейшей работы (например, визуализации) её необходимо декодировать и преобразовать в набор координат.

2.1.1.5. Обработка геометрии

Декодируем геометрию маршрута из закодированного формата (polyline) в набор координат с помощью метода decode() из библиотеки polyline

import polyline

decoded_route_osrm = polyline.decode(geometry_osrm)

В результате декодирования получаем список координат, описывающих маршрут. Поскольку таких точек может быть много, выведем только первые несколько:

decoded_route_osrm[:5]
[(59.9445, 30.35179), (59.94448, 30.35181), (59.94441, 30.35189), (59.94429, 30.35205), (59.94415, 30.35205)]

Каждая точка маршрута представлена в виде пары координат (широта, долгота), так как polyline.decode() возвращает координаты в таком формате.

Однако перед созданием геометрии необходимо поменять их порядок, так как библиотека shapely ожидает координаты в формате (долгота, широта).

from shapely.geometry import LineString

route_line_osrm = LineString([(lat, lon) for lon, lat in decoded_route_osrm])
2.1.1.6. Создание GeoDataFrame

Создадим GeoDataFrame, чтобы можно было визуализировать маршрут на карте

route_gdf_osrm = gpd.GeoDataFrame(
    {"name": ["Route"]},
    geometry=[route_line_osrm],
    crs="EPSG:4326"
)

Создадим GeoDataFrame также для координат точек старта и финиша:

points_gdf_osrm = gpd.GeoDataFrame(
    {"name": ["Start", "End"]},
    geometry=gpd.points_from_xy(
        [start_coords_osrm[0], end_coords_osrm[0]], 
        [start_coords_osrm[1], end_coords_osrm[1]]
    ),
    crs="EPSG:4326"
)
2.1.1.7. Визуализация результата

Визуализируем маршрут и начальную/конечную точки на интерактивной карте.

m = route_gdf_osrm.explore(
    tiles="cartodbpositron",
    color="#FCDD9D",
    style_kwds={"weight": 5},
    tooltip="name"
)

points_gdf_osrm.explore(
    m=m,
    color="#A3B565",
    marker_kwds={"radius": 6},
    tooltip="name"
)
Loading...

В этом примере мы рассмотрели базовый сценарий работы с OSRM — получение маршрута между двумя точками. Однако сервис поддерживает и другие возможности, например построение матриц расстояний. О них можно почитать в документации

2.2. OpenRouteService

OpenRouteService (ORS) — это сервис маршрутизации и пространственного анализа, построенный на данных OpenStreetMap. Он поддерживает несколько типов задач сетевого анализа, включая построение маршрутов, изохрон и матриц расстояний.

Для работы с OpenRouteService требуется API-ключ, который можно получить после регистрации на сайте сервиса.

Документация

Примечание: результаты запросов в этом разделе не будут отображаться автоматически, так как для выполнения кода требуется личный API-ключ. Вы можете получить его в своём личном кабинете OpenRouteService и запустить код локально. Место, куда нужно вставить ключ, обозначено как your_ors_key.

2.2.0. Сохранение API-ключа

Перед началом работы необходимо получить API-ключ для сервиса OpenRouteService. Для этого нужно зарегистрироваться на официальном сайте сервиса и скопировать ключ из личного кабинета (Dashboard).

После этого сохраним полученный ключ в переменную, чтобы использовать его в запросах к API.

ors_api_key = "your_ors_key"

2.2.1. Кратчайший маршрут

OpenRouteService также позволяет получать маршрут между двумя точками.

Для этого используется endpoint:

/v2/directions/{profile}

где:

  • profile — тип транспорта (например, driving-car);

  • начальная и конечная точки передаются как параметры запроса.

2.2.1.1. Формируем параметры запроса

Сформируем параметры запроса к API OpenRouteService согласно документации

Сначала зададим адрес API для расчёта маршрута.

url_directions_ors = "https://api.openrouteservice.org/v2/directions/driving-car"

Зададим параметры запроса — координаты начальной и конечной точки маршрута.

# Координаты (долгота, широта)
start_coords_ors = [30.2940, 59.9253]
end_coords_ors = [30.3361, 59.9317]

# Формируем параметры запроса на основе координат
params_directions_ors = {
    "start": f"{start_coords_ors[0]},{start_coords_ors[1]}",
    "end": f"{end_coords_ors[0]},{end_coords_ors[1]}"
}

Добавим заголовки запроса. В них передаётся API-ключ, необходимый для аутентификации.

headers_directions_ors = {
    "Authorization": ors_api_key
}
2.2.1.2. Отправка запроса

Для получения маршрута отправим HTTP-запрос к API с помощью метода GET.

response_directions_ors = requests.get(url_directions_ors, params=params_directions_ors, headers=headers_directions_ors)
2.2.1.3. Проверка статуса запроса

Перед обработкой ответа важно убедиться, что запрос выполнен успешно.

response_directions_ors.status_code

Если статус равен 200, можно переходить к обработке результата. Если код отличается от 200, стоит посмотреть, какую информацию сервер вернул в ответе, чтобы понять причину ошибки.

2.2.1.4. Обработка ответа

Ответ сервера приходит в формате GeoJSON

data_directions_ors = response_directions_ors.json()

Посмотрим, какие ключи содержит GeoJSON-объект, чтобы понять структуру данных и найти нужную информацию. Подробное описание структуры ответа также можно найти в документации API.

data_directions_ors.keys()

Основная информация о маршруте содержится в ключе features.

В нашем случае запрос был выполнен для одного маршрута, поэтому достаточно обратиться к первому элементу списка и изучить его структуру.

route_ors = data_directions_ors["features"][0]

route_ors.keys()

Давайте посмотрим, какая информация содержится в properties

properties_ors = route_ors["properties"]

properties_ors.keys()

В ключе summary содержится общая информация о маршруте (например, его длина и время в пути), а в segments — более детализированное описание отдельных участков маршрута.

Извлечём информацию о протяженности и времени маршрута.

distance_ors = properties_ors["summary"]["distance"]
duration_ors  = properties_ors["summary"]["duration"]


print(f"Расстояние (метры): {distance_ors}")
print(f"Время (секунды): {duration_ors}")
2.2.1.5. Создание GeoDataFrame

Создадим GeoDataFrame, чтобы можно было визуализировать маршрут на карте

Поскольку ответ приходит в формате GeoJSON, маршрут можно сразу преобразовать в GeoDataFrame без дополнительной обработки геометрии

route_gdf_ors = gpd.GeoDataFrame.from_features(
    data_directions_ors["features"], crs="EPSG:4326"
)

Создадим GeoDataFrame также для координат точек старта и финиша:

points_gdf_ors = gpd.GeoDataFrame(
    {"name": ["Start", "End"]},
    geometry=gpd.points_from_xy(
        [start_coords_ors[0], end_coords_ors[0]],
        [start_coords_ors[1], end_coords_ors[1]]
    ),
    crs="EPSG:4326"
)
2.2.1.6. Визуализация результата

Визуализируем маршрут и начальную/конечную точки на интерактивной карте.

m = route_gdf_ors.explore(
    tiles="cartodbpositron",
    color="#FCDD9D",
    style_kwds={"weight": 5},
)

points_gdf_ors.explore(
    m=m,
    color="#C4C3E3",
    marker_kwds={"radius": 6},
    tooltip="name"
)

2.2.2. Матрица расстояний

Матрица расстояний позволяет получить расстояния и время в пути между несколькими точками.

Для этого используется endpoint:

/v2/matrix/{profile}

где:

  • profile — тип транспорта;

  • locations — список координат точек;

  • metrics — какие показатели нужно вернуть (distance, duration).

2.2.2.1. Формируем параметры запроса

Сначала зададим адрес API для расчёта матрицы расстояний.

url_matrix_ors = "https://api.openrouteservice.org/v2/matrix/driving-car"

Зададим список точек. OpenRouteService ожидает координаты в формате [долгота, широта].

locations_coords_ors = [
    [30.3521, 59.9446],
    [30.2865, 59.9240],
    [30.2940, 59.9253],
    [30.3361, 59.9317]
]

Подготовим тело запроса: сформируем данные, которые будут отправлены на сервер вместе с POST-запросом согласно документации:

  • locations — список координат точек, между которыми будет рассчитана матрица;

  • metrics — список показателей, которые нужно вернуть.

data_matrix_ors = {
    "locations": locations_coords_ors,
    "metrics": ["distance"]
}
2.2.2.2. Заголовки запроса

Для обращения к OpenRouteService необходимо передать API-ключ в заголовке.

headers_matrix_ors = {
    "Authorization": ors_api_key,
    "Content-Type": "application/json"
}
2.2.2.3. Отправка запроса

Для расчёта матрицы расстояний используем POST-запрос (согласно документации).

response_matrix_ors = requests.post(url_matrix_ors, json=data_matrix_ors, headers=headers_matrix_ors)
2.2.2.4. Проверка статуса запроса

Перед обработкой ответа важно убедиться, что запрос выполнен успешно.

response_matrix_ors.status_code

Если статус равен 200, можно переходить к обработке результата. Если код отличается от 200, стоит посмотреть, какую информацию сервер вернул в ответе, чтобы понять причину ошибки.

2.2.2.5. Обработка ответа

Ответ сервера приходит в формате JSON и может быть преобразован в Python-словарь для дальнейшей работы с помощью метода .json().

matrix = response_matrix_ors.json()

Посмотрим, какие ключи содержит JSON-объект, чтобы понять структуру данных и найти нужную информацию.

matrix.keys()

Основные данные находятся в ключе distances — матрица расстояний в метрах;

2.2.2.6. Извлечение данных

Извлечём матрицу расстояний из ответа API.

distances_matrix_ors = matrix["distances"]

print(distances_matrix_ors)

Полученные данные представлены в виде вложенных списков (матриц)

2.2.3. Изохроны

OpenRouteService позволяет строить изохроны — зоны, достижимые от заданной точки за определённое время или расстояние.

Для этого используется endpoint:

/v2/isochrones/{profile}

где:

  • profile — тип передвижения (например, foot-walking, driving-car);

  • в теле запроса передаются координаты исходной точки и интервалы времени или расстояния.

В нашем примере построим пешеходные изохроны на 5, 10 и 15 минут.

2.2.3.1. Формируем параметры запроса

Сначала зададим адрес API:

url_isochrones_ors = "https://api.openrouteservice.org/v2/isochrones/foot-walking"

Подготовим тело запроса.

start_coords_isochrones_ors = [30.2907, 59.9307]

params_isochrones_ors = {
    "locations": [start_coords_isochrones_ors],
    "range": [300, 600, 900]
}

Здесь:

  • locations — список точек, от которых строятся изохроны;

  • range — интервалы времени в секундах:

    • 300 = 5 минут,

    • 600 = 10 минут,

    • 900 = 15 минут.

Добавим заголовки запроса. В них передаётся API-ключ, необходимый для аутентификации.

headers_isochrones_ors = {
    "Authorization": ors_api_key,
    "Content-Type": "application/json"
}
2.2.3.2. Отправка запроса

Для построения изохрон используем POST-запрос

response_isochrones_ors = requests.post(url_isochrones_ors, json=params_isochrones_ors, headers=headers_isochrones_ors)
2.2.3.3. Проверка статуса запроса

Перед обработкой ответа важно убедиться, что запрос выполнен успешно.

response_isochrones_ors.status_code

Если статус равен 200, можно переходить к обработке результата. Если код отличается от 200, стоит посмотреть, какую информацию сервер вернул в ответе, чтобы понять причину ошибки.

2.2.3.4. Обработка ответа

Ответ сервера приходит в формате GeoJSON.

isochrones = response_isochrones_ors.json()

Посмотрим, какие ключи содержит объект:

isochrones.keys()

Основная информация находится в ключе features, где каждая изохрона представлена как отдельный геометрический объект.

isochrones["features"]

Каждый объект содержит:

  • геометрию (полигон изохроны);

  • свойства (properties), включая значение времени, для которого построена зона.

2.2.3.5. Преобразование в GeoDataFrame

Так как ответ уже имеет формат GeoJSON, его удобно сразу преобразовать в GeoDataFrame.

isochrones_gdf_ors = gpd.GeoDataFrame.from_features(
    isochrones["features"], crs="EPSG:4326"
)
2.2.3.6. Визуализация результата

Визуализируем изохроны на интерактивной карте.

isochrones_gdf_ors.explore(tiles="cartodbpositron")

В этом подразделе мы рассмотрели лишь несколько примеров работы с OpenRouteService: построение маршрута, матрицы расстояний и изохрон. Однако API сервиса поддерживает и другие функции, а также дополнительные параметры запросов. Рекомендуем почитать документацию и посмотреть, какие ещё возможности доступны.

2.3. GraphHopper

GraphHopper — это сервис маршрутизации и сетевого анализа, работающий на данных OpenStreetMap. Он поддерживает построение маршрутов, расчёт матриц расстояний и другие задачи, связанные с анализом транспортной сети.

Для работы с GraphHopper требуется API-ключ, который можно получить после регистрации на сайте сервиса.

Документация

Примечание: результаты запросов в этом разделе не будут отображаться автоматически, так как для выполнения кода требуется личный API-ключ. Вы можете получить его в своём личном кабинете GraphHopper и запустить код локально. Место, куда нужно вставить ключ, обозначено как your_graph_key.

2.3.0. Сохранение API-ключа

Перед началом работы необходимо получить API-ключ для сервиса GraphHopper. Для этого нужно зарегистрироваться на официальном сайте сервиса и скопировать ключ из личного кабинета (Dashboard).

После этого сохраним полученный ключ в переменную.

graphhopper_api_key = "your_graph_key"

2.3.1. Кратчайший маршрут

GraphHopper позволяет получить маршрут между двумя и более точками.

Для этого используется endpoint:

/api/1/route

В запросе передаются:

  • point — точки маршрута в формате широта,долгота;

  • vehicle — тип транспорта (например, car);

  • key — API-ключ пользователя.

2.3.1.1. Формируем параметры запроса

Сначала зададим адрес API:

url_directions_graph = "https://graphhopper.com/api/1/route"

Зададим начальную и конечную точки маршрута:

# Координаты (долгота, широта)
start_coords_graph = [30.3146, 59.9633]
end_coords_graph = [30.3671, 59.9440]

# Преобразуем координаты в строку (широта, долгота)
start_graph = f"{start_coords_graph[1]},{start_coords_graph[0]}"
end_graph = f"{end_coords_graph[1]},{end_coords_graph[0]}"

params_directions_graph = {
    "point": [start_graph, end_graph],
    "vehicle": "car",
    "key": graphhopper_api_key
}

Обратите внимание: в GraphHopper координаты в параметре point передаются в формате широта,долгота, что отличается от некоторых других сервисов.

2.3.1.2. Отправка запроса

Отправляем GET-запрос к API.

response_directions_graph = requests.get(url_directions_graph, params=params_directions_graph)

2.3.1.3. Проверка статуса запроса

Перед обработкой ответа важно убедиться, что запрос выполнен успешно.

response_directions_graph.status_code

Если статус равен 200, можно переходить к обработке результата. Если код отличается от 200, стоит посмотреть, какую информацию сервер вернул в ответе, чтобы понять причину ошибки.

2.3.1.4. Обработка ответа

Ответ сервера приходит в формате JSON:

data_directions_graph = response_directions_graph.json()

Посмотрим, какие ключи содержит ответ:

data_directions_graph.keys()

Основная информация о маршруте находится в ключе paths. Это список маршрутов. В нашем случае маршрут один, поэтому будем обращаться к первому элементу списка.

route_graph = data_directions_graph["paths"][0]

route_graph.keys()
  • distance — длина маршрута в метрах;

  • time — время в пути в миллисекундах;

  • points — геометрия маршрута в виде закодированной polyline.

Извлечём основные характеристики маршрута из ответа API.

distance_graph = route_graph["distance"]
duration_graph = route_graph["time"] / 1000
geometry_graph = route_graph["points"]

print(f"Расстояние (метры): {distance_graph}")
print(f"Время (секунды): {duration_graph}")
print(f"Геометрия: {geometry_graph[:50]}...")

Геометрия маршрута возвращается в закодированном виде (формат polyline), чтобы уменьшить объём передаваемых данных. Для дальнейшей работы (например, визуализации) её необходимо декодировать и преобразовать в набор координат.

2.3.1.5. Обработка геометрии

Декодируем геометрию маршрута из закодированного формата (polyline) в набор координат с помощью метода decode() из библиотеки polyline

decoded_route_graph = polyline.decode(geometry_graph)

В результате декодирования получаем список координат, описывающих маршрут. Поскольку таких точек может быть много, выведем только первые несколько:

decoded_route_graph[:5]

Каждая точка маршрута представлена в виде пары координат (широта, долгота), так как polyline.decode() возвращает координаты в таком формате.

Однако перед созданием геометрии необходимо поменять их порядок, так как библиотека shapely ожидает координаты в формате (долгота, широта).

route_line_graph = LineString([(lat, lon) for lon, lat in decoded_route_graph])
2.3.1.6. Создание GeoDataFrame

Создадим GeoDataFrame, чтобы можно было визуализировать маршрут на карте

route_gdf_graph = gpd.GeoDataFrame(
    {"name": ["Route"]},
    geometry=[route_line_graph],
    crs="EPSG:4326"
)

Создадим GeoDataFrame также для координат точек старта и финиша:

points_gdf_graph = gpd.GeoDataFrame(
    {"name": ["Start", "End"]},
    geometry=gpd.points_from_xy(
        [start_coords_graph[0], end_coords_graph[0]],
        [start_coords_graph[1], end_coords_graph[1]]
    ),
    crs="EPSG:4326"
)
2.3.1.7. Визуализация результата

Визуализируем маршрут и начальную/конечную точки на интерактивной карте.

m = route_gdf_graph.explore(
    tiles="cartodbpositron",
    color="#FCDD9D",
    style_kwds={"weight": 5},
    tooltip="name"
)

points_gdf_graph.explore(
    m=m,
    color="#504E76",
    marker_kwds={"radius": 6},
    tooltip="name"
)

В этом примере мы познакомились с базовым использованием GraphHopper для построения маршрута. Однако сервис поддерживает и другие методы сетевого анализа, включая расчёт матриц расстояний. О них можно узнать в документации GraphHopper.

Итог

В этом разделе мы познакомились с основами сетевого анализа с использованием внешних API.

Мы узнали:

  • что такое API и как устроены запросы к веб-сервисам;

  • как читать документацию и находить в ней нужные параметры запросов;

  • как отправлять запросы из Python с помощью библиотеки requests;

  • как обрабатывать ответы и преобразовывать результаты API-запросов в GeoDataFrame для дальнейшего анализа и визуализации;

Внешние API удобны тем, что позволяют выполнять сетевой анализ без предварительной загрузки и подготовки графа.

При этом важно помнить, что разные сервисы отличаются по формату запросов, доступным функциям, ограничениям и требованиям к авторизации. Поэтому при работе с любым API ключевую роль играет внимательное чтение документации и понимание структуры ответа.