Получаем i18n список стран, регионов, населенных пунктов из ВКонтакте

в 17:47, , рубрики: web-разработка, Вконтакте API, географические наименования, Геоинформационные сервисы, метки: , ,

Получить базу данных стран, регионов, населенных пунктов с переводом названий и связями бесплатно и без регистрации? Это реально!

При разработке небольшого стартап-проекта с большими амбициями столкнулся с необходимостью в базе данных стран, регионов и городов, с переводом названий хотя бы на самые распространенные языки (английский, русский, испанский, немецкий и т. д.). Готовое решение найдено не было, поэтому стал искать источники, из которых можно спарсить необходимые данные. На ум сразу пришли известные социальные сети. В этой статье уже описывалось получение данных из ВКонтакте, но покопавшись в документации API ВКонтакте, был приятно удивлен, найдя открытые документированные методы получения геоданных:

database.getCountries — Возвращает список стран.

database.getRegions — Возвращает список регионов.

database.getCities — Возвращает список населенных пунктов.

database.getCountriesById — Возвращает информацию о странах по их идентификаторам

database.getCitiesById — Возвращает информацию о городах по их идентификаторам.

Это основные, интересные нам методы, к тому же не требующие авторизации и использования токенов. Больше методов можно посмотреть в разделе документации.

Пример url для обращения к методу получения списка стран представлен ниже (аналогично происходит обращение по протоколу https):
http://api.vk.com/method/database.getCountries?v=5.5&need_all=1&count=10

Посмотреть результат

{"response":{"count":234,"items":[{"id":19,"title":"Австралия"},{"id":20,"title":"Австрия"},{"id":5,"title":"Азербайджан"},{"id":21,"title":"Албания"},{"id":22,"title":"Алжир"},{"id":23,"title":"Американское Самоа"},{"id":24,"title":"Ангилья"},{"id":25,"title":"Ангола"},{"id":26,"title":"Андорра"},{"id":27,"title":"Антигуа и Барбуда"}]}}

Параметры:
v — указывает на версию API. В разных версиях структура JSON будет разной. Например, начиная с версии 5.0 добавлено значение count, которое содержит общее количество элементов в выборке и при совместном использовании с параметром offset поможет получить все значения. По умолчанию данные возвращаются в старой версии (видимо для совместимости со старыми приложениями).
count — максимальное количество значений, возвращаемых методом. Максимальное значение параметра, которое можно задать, составляет 1000 элементов. Минимальное и значение по умолчанию для каждого метода может отличаться и следует сверяться с документацией.
need_all — необязательный параметр, по умолчанию равен «0», указывает на то, что не следует производить выборку небольших регионов/стран/населенных пунктов
Остальные параметры для каждой функции расписывать нет смысла, так они есть в официальной документации, перейдем же к неофициальным возможностям:

Получаем список стран для различных языков

<?php

    $lang = 0; // russian
    $headerOptions = array(
        'http' => array(
            'method' => "GET",
            'header' => "Accept-language: enrn" .
            "Cookie: remixlang=$langrn"
        )
    );
    $methodUrl = 'http://api.vk.com/method/database.getCountries?v=5.5&need_all=1&count=1000';
    $streamContext = stream_context_create($headerOptions);
    $json = file_get_contents($methodUrl, false, $streamContext);
    $arr = json_decode($json, true);
    echo 'Total countries count: ' . $arr['response']['count'] . ' loaded: ' . count($arr['response']['items']);
    print_r($arr['response']['items']); 

Стоит обратить внимание, что метод пытается вернуть данные на языке, указанном в cookie параметре remixlang. Поэтому подставив числовое значение необходимого языка, получим данные на необходимом языке, если присутствует перевод. Страны переведены все, вроде бы на все языки, доступные в социальной сети. Для регионов и городов: если перевод отсутствует (мелкие населенные пункты, регионы небольших стран), то получим значение на популярном в данном регионе языке например в африканских странах, на английском, для стран СНГ — русском.

Вот краткий список идентификаторов языков:

Язык Значение remixlang
Русский 0
Украинский 1
Английский 3
Испанский 4
Португальский 12
Немецкий 6
Французский 16
Итальянский 7

Получаем список регионов для различных языков

Пример url для обращения к методу получения списка регионов для страны заданной, параметром country_id (обязательный параметр):
http://api.vk.com/method/database.getRegions?v=5.5&need_all=1&offset=0&count=1000&country_id=

<?php
    $countryId = 1; // Russia
    $lang = 0; // russian
    $headerOptions = array(
        'http' => array(
            'method' => "GET",
            'header' => "Accept-language: enrn" . // Вероятно этот параметр ни на что не влияет
            "Cookie: remixlang=$langrn"
        )
    );
    $methodUrl = 'http://api.vk.com/method/database.getRegions?v=5.5&need_all=1&offset=0&count=1000&country_id=' . $countryId;
    $streamContext = stream_context_create($headerOptions);
    $json = file_get_contents($methodUrl, false, $streamContext);
    $arr = json_decode($json, true);
    echo 'Total regions count: ' . $arr['response']['count'] . ' loaded: ' . count($arr['response']['items']);
    print_r($arr['response']['items']); 

Перечень параметров, для метода и описание можно посмотреть в документации. Однако стоит заметить, что возвращенный JSON может быть пустым, т. е. не для всех стран могут быть заданы регионы, в таком случае, при получении списка городов параметр region_id можно опустить.

Получаем список населенных пунктов

Пример url для обращения к методу получения списка городов для страны заданной, параметром country_id (обязательный параметр) и региона region_id (необязательный параметр):
http://api.vk.com/method/database.getCities?v=5.5&country_id=1&region_id=1045244&offset=0&need_all=1&count=1000

<?php
    $regionId = 1045244;
    $countryId = 1; // Russia
    $lang = 0;
    $headerOptions = array(
        'http' => array(
            'method' => "GET",
            'header' => "Accept-language: enrn" .
            "Cookie: remixlang=$langrn"
        )
    );
    $methodUrl = 'http://api.vk.com/method/database.getCities?v=5.5&country_id=' . $countryId . '&region_id=' . $regionId . '&offset=0&need_all=1&count=1000';
    $streamContext = stream_context_create($headerOptions);
    $json = file_get_contents($methodUrl, false, $streamContext);
    $arr = json_decode($json, true);
    echo 'Total cities count: ' . $arr['response']['count'] . ' loaded: ' . count($arr['response']['items']);
    print_r($arr['response']['items']); 

Возвращаемые данные для каждого населенного пункта могут также содержать следующие параметры:
area — название района (провинции и т. д.)
important равное «1» — обозначение крупных городов, появляется только при использовании параметра need_all

Внимание! Некоторые регионы могут не содержать населенных пунктов (или сами являться населенными пунктами, как я понял).

Коллизии

Некоторые полученные значения могут содержать спецсимволы, теги (например <b> и <br>).

PS

На данный момент все нюансы, которые заметил при получении данных описал в статье. Получил сырой дамп, наспех написанным парсером с ошибкой (в дампе не выгружены города, не относящиеся ни к одному из регионов). Процесс выгрузки занял 4 часа. При импорте в Postgres вылетали ошибки, возникающие из за недостаточного экранирования некоторых символов. Через несколько дней планирую переписать парсер и сформировать более «чистый» дамп + сделать дампы в нескольких форматах.

Сырой дамп загружает:
234 страны
3721 регионов
1896563 городов

Скачать можно по ссылке (23 мб):
http://yadi.sk/d/olTnfCV_Dn4wy
https://drive.google.com/file/d/0BwgW554ipNgbV09ya3N6ZGtuWUU

Переводы: Русский, Украинский, Английский, Испанский, Португальский, Немецкий, Французский, Итальянский

Автор: x88

Источник


  1. Виктор:

    Как оказалось, на украинский язык названия населенных пунктов не переведены (разве что за исключением больших городов)

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js