...

среда, 4 декабря 2013 г.

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

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


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


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


Коллизии


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


PS


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


Сырой дамп загружает:

234 страны

3721 регионов

1896563 городов


Скачать можно по ссылке (23 мб):

http://yadi.sk/d/olTnfCV_Dn4wy

https://drive.google.com/file/d/0BwgW554ipNgbV09ya3N6ZGtuWUU


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


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers.


Комментариев нет:

Отправить комментарий