Некоторое время назад я рассказывал об использовании Яндекс.Карт и сервиса IPLoc, который позволяет определить географические координаты посетителя по его IP адресу.
К сожалению, этот сервис сейчас практически все время недоступен. И эта ситуация наглядно показывает, насколько опасно полностью полагаться на сторонние сервисы.
Конечно, проблемы бывают у всех. Но если не работает собственный ресурс, можно попытаться что-то сделать, а тут остается только ждать.
Кроме того, есть ещё одна отрицательная сторона использования сторонних сервисов – время отклика. На отправку запроса и получение ответа (даже очень короткого) уйдет некоторое время, и оно наверняка будет больше чем обращение к локальным ресурсам.
В общем, глядя на сложившуюся ситуацию, я начал искать локальную альтернативу IPLoc, т.е. готовую базу данных. Т.к. платные варианты меня не устраивали, то искать пришлось довольно долго 🙂
В результате я остановился на сервисе WIPmania.com. Он предоставляет и API для получения данных, и базу данных.
Правда полноценной заменой IPLoc его считать нельзя, т.к. он позволяет определить только страну посетителя, а географические координаты (широта и долгота) отсутствуют. Тем не менее, более полные базы я видел только в платных вариантах.
Ограничения WIPmania.
Версия базы данных для скачивания обновляется один раз в два месяца.
Если вы используете API, то всегда работаете с самой новой версией, но существует ограничение на количество запросов в месяц.
Т.к. использование API практически не отличается от IPLoc, в этой статье я расскажу только о работе с БД.
1) Загружаем базу данных с официального сайта, тут же можно скачать архив с флагами стран.
Я выбрал архив с SQL версией базы.
Нам нужны 2 файла worldip.sql
и worldip.lands.ru.sql
. Создаем базу данных и импортируем их.
В результате будут созданы две таблицы:
worldip_land
и worldip
В первой таблице хранятся диапазоны IP адресов и двухбуквенные коды соответствующих им стран.
Во второй таблице – двухбуквенные коды и полные названия стран.
Я использовал таблицу с русскими названиями, но в дистрибутив также входят переводы на английский, немецкий и испанский.
Есть несколько нюансов при импортировании таблиц.
Во-первых, импортирование я выполнял с помощью команды
mysql --user=имя --password=пароль название_базы < имя_файла
Во-вторых, практически весь Файл worldip.sql занимает один SQL запрос, размер которого больше 1 МБ. И при попытке импорта возникала ошибка «MySQL server has gone away».
Чтобы её исправить добавьте в конфигурационный файл (my.ini) строку
max_allowed_packet = 4M
(в раздел [mysqld]).
2) Получение данных
Как не сложно догадаться, в большинстве случаев нам нужно будет определять название страны по известному IP. Кроме того, для того, чтобы показать флаг страны, нужен её двухбуквенный код.
Выполнить эту операцию можно с помощью следующего SQL запроса.
SELECT wl.code, wl.country FROM worldip w LEFT JOIN worldip_land wl ON (w.code=wl.code) WHERE w.start<=ip and w.end>=ip
Чтобы понять, как работает запрос нужно представлять структуру таблиц в базе.
Таблица worldip_land
содержит 2 поля:
code
– двухбуквенный код страны;
country
– название страны.
Таблица worldip
содержит 3 поля:
start
– начало диапазона IP адресов;
end
– конец диапазона IP адресов;
code
– двухбуквенный код страны.
Думаю вы догадались, что для связи между таблицами используется поле code
.
Теперь разберем запрос. Сначала будет выполнен поиск в таблице worldip
диапазона адресов, в который входит заданный ip
. Затем его результаты используются для поиска названия страны в таблице worldip_land
.
Примечание. На этой странице вы найдете примеры наиболее распространенных запросов.
И в заключение приведу пример небольшого скрипта, который выводит IP адрес посетителя, название страны и её флаг.
<?php //определяем IP посетителя $visitorIP = $_SERVER['REMOTE_ADDR']; //подключение к БД $dbHost = 'localhost'; $dbName = 'db_name'; $dbUser = 'db_user'; $dbPass = 'db_pass'; try { $dbh = new PDO('mysql:host='.$dbHost.';dbname='.$dbName, $dbUser, $dbPass); //преобразовываем IP в целое число $ip = ip2long($visitorIP); if ($ip !== FALSE) { //определяем в какой стране находится посетитель и получаем $stmt = $dbh->prepare('SELECT wl.code, wl.country FROM worldip w LEFT JOIN worldip_land wl ON (w.code=wl.code) WHERE w.start<=? and w.end>=?'); $stmt->bindParam(1, $ip); $stmt->bindParam(2, $ip); $stmt->execute(); $res = $stmt->fetch(PDO::FETCH_ASSOC); if ($res === FALSE) { $errMes = 'Местоположение данного IP неизвестно'; } } $dbh = null; } catch (PDOException $e) { $errMes = 'Ошибка: '.$e->getMessage(); } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru"> <head> <title>WIPmania</title> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <meta http-equiv="Content-Style-Type" content="text/css" /> </head> <body> <p>Ваш IP адрес: <?php echo $visitorIP; ?></p> <p> <?php if (isset($errMes)) { echo $errMes; } else { //вставляем название страны и рисунок с флагом ?> <img src="flags/<?php echo $res['code']; ?>.png" title="флаг" /> <?php echo $res['country']; } ?> </p> </body> </html>
Общий алгоритм работы скрипта следующий.
1) Определяем IP адрес. И преобразуем его в целочисленную форму (с помощью функции ip2long
, строка 14).
2) Отправляем запрос. В этом примере я использовал PDO, но, естественно, вы можете использовать любую другую библиотеку. О принципе работы запроса я уже рассказал.
3) Формируем страницу и показываем на ней:
— IP адрес посетителя (строка 43);
— сообщение об ошибке (если она возникла);
— флаг страны (строка 52);
— и её название (строка 54).
Обратите внимание на вставку рисунка с флагом. Я распаковал архив в папку flags
. Имена файлов совпадают с двухбуквенными кодами стран. К ним нужно только добавить расширение (.png).
Если есть желание поэкспериментировать со скриптом – качайте архив с примером.
И в заключение маленькое замечание – адрес 127.0.0.1 в базе отсутствует 😉
До встречи!