Pull to refresh

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

Reading time 5 min
Views 63K

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


При разработке небольшого стартап-проекта с большими амбициями столкнулся с необходимостью в базе данных стран, регионов и городов, с переводом названий хотя бы на самые распространенные языки (английский, русский, испанский, немецкий и т. д.). Готовое решение найдено не было, поэтому стал искать источники, из которых можно спарсить необходимые данные. На ум сразу пришли известные социальные сети. В этой статье уже описывалось получение данных из ВКонтакте, но покопавшись в документации 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: en\r\n" .
            "Cookie: remixlang=$lang\r\n"
        )
    );
    $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: en\r\n" . // Вероятно этот параметр ни на что не влияет
            "Cookie: remixlang=$lang\r\n"
        )
    );
    $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: en\r\n" .
            "Cookie: remixlang=$lang\r\n"
        )
    );
    $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

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

Коллизии


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

Updated


Не обязательно использовать хак cookie, для получения результата. Как подсказал пользователь uh_zuh, документирован параметр lang ( например lang=ru).

Updated 2


Практика показала, что параметр lang не функционирует для многих языков.

Updated 3


Как и обещал, полный дамп:
Актуальные версии на GitHub

SQL дамп в формате PostgreSql
Yandex Disk
Google Drive
SQL дамп в формате MySql
Yandex Disk
Google Drive
Дамп в формате CSV
Разделитель - точка с запятой (;), с заголовком столбца, данные в двойных кавычках(")
Yandex Disk
Google Drive
Разделитель - запятая (,), с заголовком столбца, данные в двойных кавычках(")
Yandex Disk
Google Drive

Названия переведены на: Русский, Украiнский, Белорусский, Английский, Испанский, Португальский, Немецкий, Французский, Итальянский, Польский, Японский, Литовский, Латышский, Чешский
234 страны
3 721 регион
2 246 813 населенных пункта
Tags:
Hubs:
+13
Comments 12
Comments Comments 12

Articles