Получить базу данных стран, регионов, населенных пунктов с переводом названий и связями бесплатно и без регистрации? Это реально!
При разработке небольшого стартап-проекта с большими амбициями столкнулся с необходимостью в базе данных стран, регионов и городов, с переводом названий хотя бы на самые распространенные языки (английский, русский, испанский, немецкий и т. д.). Готовое решение найдено не было, поэтому стал искать источники, из которых можно спарсить необходимые данные. На ум сразу пришли известные социальные сети. В этой статье уже описывалось получение данных из ВКонтакте, но покопавшись в документации 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®ion_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 . '®ion_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
Как оказалось, на украинский язык названия населенных пунктов не переведены (разве что за исключением больших городов)