Как автоматизировать поиск деревень на картах: инструкция для новичков

Если вам нужно обработать список из сотен деревень и определить, какие из них есть на картографических сервисах, ручной поиск – не вариант. Но есть хорошая новость: эту задачу можно автоматизировать за пару часов, даже если вы никогда не работали с картами как программист. Главное – разобраться в геокодинге (это процесс преобразования названия места в координаты).

Как работают геокодинговые сервисы

Представьте, что вы отправляете запрос «деревня Грибки, Ленинградская область» в систему вроде Google Maps – и получаете ответ с широтой и долготой. Именно так устроены API геокодинга. Они анализируют базы данных карт и возвращают координаты, если совпадение найдено.

Основные платформы для этого:

  • Google Maps Geocoding API (платный, но с бесплатным лимитом – 200$ в месяц хватит для 40 тыс. запросов);
  • OpenStreetMap Nominatim (бесплатный, но с ограничением 1 запрос/секунду);
  • Here Maps (гибридный тариф, подходит для больших объёмов).

Кстати, OSM-данные можно скачать целиком (это называется «дамп») и работать с ними локально – но это требует навыков обработки XML и много места на диске (около 100+ ГБ).

Практика: пишем скрипт для проверки деревень

Допустим, у вас есть файл villages.txt с названиями населённых пунктов. Вот как его обработать через Nominatim (OSM):

1. Установите библиотеки. Для Python:

pip install requests pandas

2. Напишите функцию геокодинга. Пример:

import requests  
import time  

def geocode_village(name):  
    url = "https://nominatim.openstreetmap.org/search"  
    params = {  
        'q': name,  
        'format': 'json',  
        'limit': 1  
    }  
    response = requests.get(url, params=params).json()  
    time.sleep(1)  # соблюдаем лимит запросов  
    return response[0]['lat'], response[0]['lon'] if response else None  

3. Обработайте файл. Добавьте обработку ошибок (например, если деревня не найдена):

import pandas as pd  

villages = pd.read_csv('villages.txt', header=None, names=['name'])  
results = []  
for village in villages['name']:  
    try:  
        coords = geocode_village(village)  
        results.append({'name': village, 'lat': coords[0], 'lon': coords[1]})  
    except:  
        results.append({'name': village, 'lat': None, 'lon': None})  

pd.DataFrame(results).to_csv('results.csv', index=False) 

Важные нюансы:

    • Всегда добавляйте задержку между запросами (у Nominatim – минимум 1 секунда), иначе сервер заблокирует IP;
    • Указывайте регион в запросе (например, «деревня Грибки, Ленобласть» вместо «Грибки»), чтобы уменьшить число ложных срабатываний;
    • Проверяйте ответы вручную для части данных – алгоритмы иногда находят «похожие» названия в других странах.

    Совет: Если скрипт работает слишком долго, распараллельте запросы через библиотеку asyncio, но не нарушайте лимиты сервиса.

    Что делать, если API не находит деревни

    Даже после автоматической проверки часть населённых пунктов может остаться без координат. В этом случае:

    1. Попробуйте альтернативные написания (например, «дер. Грибки» вместо «деревня Грибки»);
    2. Используйте комбинацию сервисов: сначала OSM, потом Google Maps – иногда базы различаются;
    3. Добавьте ручную проверку через QGIS (бесплатная GIS-программа) – импортируйте CSV с координатами и отфильтруйте пустые значения.

    Если задача кажется сложной, начните с малого – обработайте первые 50 деревень и посмотрите на процент успешных совпадений. Возможно, 80% населённых пунктов уже есть в OSM, и ручная доработка понадобится только для остатка.

    P.S. Когда я впервые столкнулся с подобной задачей, то потратил день на изучение документации – но сейчас весь процесс занимает 20 минут. Главное не бойтесь экспериментировать с параметрами запросов (и не забудьте получить API-ключ для Google, если решите его использовать).

    Новое
    Интересное