Не секрет, что диапазоны IP адресов распределены между странами мира, то есть зная IP можно достаточно точно определить, в какой стране находится пользователь. Иногда даже можно определить его город и координаты (но вот на точность этих данных полагаться уже не стоит).

Существует множество способов определить страну по IP. Это либо базы адресов, развертываемые прямо на сервере, либо онлайн-сервисы, возвращающие информацию об адресе в структурированном формате. Большинство этих сервисов, конечно, имеют ограничения, и для использования в крупных проектах требуют покупки лицензии или подписки, но попробовать их можно и бесплатно.

MaxMind

GeoIP2 сервис, практически монополист на рынке, предлагающий платные услуги по определению страны, города и других параметров.

Достоинство - самые актуальные базы и различные подходы к повышению точности определения.

Недостаток - услуга использования онлайн-сервиса платная, 0,0001 $ за запрос, причем платить нужно вперед. Однако, можно скачать бесплатную версию баз GeoLite2 Country или GeoLite2 City, разместить ее на сервере (для этого нужно иметь доступ к файловой системе), и использовать в C#, Java или php проекте (список поддерживаемых API).

Рассматривать этот сервис подробно не будем, перейдем к более простым решениям.

ip2nation.com

Это MySQL база данных с информацией о соответствии адреса стране. Скачать для размещения ее на собственном сервере можно .

Пример на php, позволяющий вывести полное название страны:

geoPlugin

Онлайн-сервис определения страны и города подключается к сайту следующим образом:

< script src= "http://www.geoplugin.net/javascript.gp" type= "text/javascript" >

После подключения можно вызывать следующие методы:

geoplugin_request() - IP
geoplugin_status() - статус (200б 4040 и т. д.)
geoplugin_credit() - благодарности сервису MaxMind, упомянутому чуть выше.
geoplugin_city() - город
geoplugin_region() - область или регион
geoplugin_areaCode() - код зоны
geoplugin_dmaCode() - американский код из трех цифр, определяющий набор поддерживаемых телеканалов
geoplugin_regionCode() - код региона
geoplugin_regionName() - название региона
geoplugin_countryCode() - двухбуквенный код страны
geoplugin_countryName() - название страны на английском языке
geoplugin_continentCode() - код континента (например EU - Европа)
geoplugin_latitude() - широта
geoplugin_longitude() - долгота
geoplugin_currencyCode() - трехбуквенный код валюты страны
geoplugin_currencySymbol() - символ валюты страны

Также можно не подключать библиотеку, а использовать JSONP:

$.getJSON ("http://www.geoplugin.net/json.gp?jsoncallback=?" , function (response) { for (var i in response) { document.write ("response[" + i + "] = " + response[ i] + "
" ) ; } } ) ;

$.getJSON("http://www.geoplugin.net/json.gp?jsoncallback=?", function (response) { for (var i in response) { document.write("response[" + i + "] = " + response[i]+ "
"); } });

Достоинство - кроме страны можно получить информацию о валюте и ее код (₴, €, ₽).

Недостаток - запросы по HTTPS платные, подписка стоит €12 в год.

ipinfo.io

Открытый сервис, позволяющий бесплатно делать до 1000 запросов в сутки .

Чтобы вызвать его в js используется код

$.getJSON ("http://ipinfo.io" , function (response) { console.log (response) ; } )

$.getJSON("http://ipinfo.io", function(response){ console.log(response); })

В ответе вы получите:

"ip" - IP адрес пользователя
"hostname" - обратный IP
"city" - предположительный город, в котором находится пользователь
"region" - регион (область, район)
"country" - страна в виде двухбуквенного кода
"loc" - координаты широты и долготы
"org" - информация о провайдере

Сервис поддерживает HTTPS, можно использовать его на сайтах с поддеpжкой HTTPS. Чтобы избежать проблем с кросс-доменными запросами, которые Chrome ограничивает, можно воспользоваться поддержкой JSONP:

$.get("https://ipinfo.io?callback=?", function(response) { $("body").text(response.ip+ " from " +response.country); // вывести IP и страну посетителя. }, "jsonp")

Практически полный клон ipinfo - сервис ipapi.co . Также ограничивает бесплатное использование 1000 запросов в сутки .

freegeoip.net

Сервис, предлагающий открытый HTTP и HTTPS API, позволяющий получить информацию в форматах CSV, XML или JSON.

Сервис также поддеживает JSONP:

$.getJSON ("https://freegeoip.net/json/?callback=" , function (response) { $("body" ) .text (response.country_name ) ; } } ) ;

$.getJSON("https://freegeoip.net/json/?callback=", function (response) { $("body").text(response.country_name); } });

Возвращаемые параметры:

"ip" - непосредственно IP адрес
"country_code" - двухбуквенный код страны
"country_name" - название страны на английском языке
"region_code" - код региона
"region_name" - название региона
"city" - город
"zip_code" - почтовый код (США)
"time_zone" - временная зона
"latitude"- широта
"longitude" - долгота
"metro_code" - метро

Вместо выводов

По результатам наблюдений все приведенные сервисы (кроме MaxMind, который в испытаниях не участвовал, и вообще приведен в статье лишь для полноты картины) правильно определили страну и код страны, geoPlugin сумел правильно определить валюту. Только сервис ipinfo правильно определил область, но промахнулся с городом, а ни один другой сервис город и область не определили совсем (вернули null, 0 или пустое значение).

В которой упоминался мой «велосипед» отличающийся высокой скоростью работы. Одним из популярных вопросов стала возможность определения города по IP.

И вот несколько месяцев спустя, проект начинавшийся, как «for fun» перерос в самостоятельный проект.
Открыт отдельный сайт посвященный проекту Sypex Geo , на котором можно скачать свежие версии API и баз данных, а также ознакомиться с документацией.

Для желающих скорее протестировать правильность определения города по IP - вот ссылка на демо-страницу . А под хабракатом, я опишу некоторые технические подробности и приведу результаты небольшого тестирования.

Формат Sypex Geo 2.1 С момента публикации последней статьи, формат Sypex Geo (сокращенно SxGeo) был оптимизирован, а также добавлена возможность включения в БД двух справочников - городов и регионов.

При создании нового формата, ставились следующие приоритеты:

  • высокая скорость
  • низкое потребление ресурсов
  • открытость (спецификации формата бинарного файла БД и API открыты)
  • универсальность (возможность создания баз данных с любыми наборами данных)
Формат позволяет хранить данные в разной кодировке. После выхода из беты, будут опубликованы скрипты для конвертирования базы данных из MySQL в бинарный файл БД.

В БД хранится следующая информация:

  • ID страны
  • Код страны ISO 3166-1 (двухсимвольный)
  • Код региона FIPS 10-4 (двухсимвольный)
  • Название региона (опционально)
  • Город
  • Широта
  • Долгота
  • Timezone (опционально)
Этот список может быть изменен и/или расширен при необходимости. Более подробную информацию о формате SxGeo 2.1 можно найти на сайте. Собственная база данных После весьма близкого знакомства с популярной системой геолокации GeoLite City от MaxMind, было принято решение о создании собственной базы данных. Проблема заключается в том, что в GeoLite City очень много неточностей, мусора, городов дубликатов, излишнего дробления диапазонов, а также проблем с городами бывшего СССР (например, вместо городов взяты названия фирм или имена ответственных из Whois).

В данный момент база основана на GeoLite City, но уже содержит полностью переработанное покрытие России, Украины и Беларуси. Постепенно будут уточняться другие страны, в первую очередь СНГ и Европа. База данных Sypex Geo City содержит названия городов и регионов на русском языке в UTF-8 (встречаются еще не переведенные названия), а также timezone.

Кроме того на сайте доступны другие базы данных преобразованные в формат SxGeo 2.1.

Использование Использование Sypex Geo API максимально упрощено.
1. Скопировать SxGeo.php и SxGeoCity.dat (или другие базы) на сервер 2. Подключить файл SxGeo.php в свой скрипт, добавив строку include("SxGeo.php"); 3. Создать объект SxGeo //$SxGeo = new SxGeo(); // Режим по умолчанию, файл бд SxGeo.dat $SxGeo = new SxGeo("SxGeoCity.dat", SXGEO_BATCH | SXGEO_MEMORY); // Самый быстрый режим 4. Определяем город (SxGeo City, GeoLite City, IpGeoBase) $SxGeo->get($ip); (возвращает информацию о городе, без названия региона и временной зоны) // $SxGeo->getCityFull($ip); (возвращает полную информацию о городе и регионе) Тестирование производительности И на десерт, небольшое сравнительное тестирование производительности. В качестве оппонентов выступают GeoLite API и Geobaza API. Все участники тестирования используют бинарную базу данных собственного формата, и используют API на PHP. Тестирование проходит под Win 7 (на Linux пропорции сохраняются), PHP 5.2.17.

Результаты после 10 прогонов для каждого API в двух режимах (обычном и с кэшированием в памяти) усреднения и округления до десятков. Для каждого прогона создается массив из 50 000 случайных IP адресов, и в цикле осуществляется поиск каждым алгоритмом.

Предложение и пожелание приветствуются. Также ищутся желающие помочь с портированием API на другие языки, и созданием модулей для Apache и nginx.

Всем привет!

Не скажу, что часто, но время от времени у разработчиков появляется необходимость определения города по IP в PHP скрипте.

Например, вы решили облегчить работу пользователю по вводу контактной информации при оформлении заказа в Интернет магазине. Или хотите устанавливать язык интерфейса сайта в зависимости от страны, из которой к вам на сайт зашёл посетитель.

Ну, а чаще всего определение города по IP в PHP с помощью GeoIP, наверное, нужно разработчикам различных рекламных сетей, чтобы предлагать пользователям таргетированную рекламу в зависимости от географического местоположения.

Самому мне узнать страну по IP в PHP скрипте понадобилось всего один-единственный раз, когда я решил загружать на сайт виджеты различных соцсетей для пользователей из разных стран. Подробнее о том, зачем не это понадобилось и что в итоге получилось, я напишу в следующей статье.

А пока поговорим о том, сколько способов определения города и страны по IP в PHP существует и какие варианты их реализаций существуют.

PHP GeoIP — стандартный функционал стороннего производства

Я специально так озаглавил описание первого способа. Дело в том, что в самом PHP определить город и страну по IP адресу нельзя — язык не обладает для этого необходимыми инструментами.
Зато в официальной документации есть подсказка, как это сделать.

PHP GeoIP — это сторонняя библиотека, которую необходимо подключать дополнительно, несмотря на то, что описание функций, входящих в неё, является частью официальной документации PHP — http://php.net/manual/ru/ref.geoip.php

В принципе, мотивы разработчиков PHP вполне понятны.

Во-первых, включение данного модуля в комплект самого языка требует большого количества серверных ресурсов.

Во-вторых, GeoIP PHP работает на базе перечня IP адресов, соответствующих определённым странам и городам. Поэтому GeoIP PHP требует постоянной поддержки и расширения/модернизации существующей базы, что являлось бы лишней головной болью разработчиков PHP.

Ну, и в-третьих, определение города по IP в PHP — возможность достаточно редко используемая на практике.

В итоге, из-за этих факторов PHP GeoIP является сторонним расширением, поддержкой которого и созданием API для интеграции на существующих сайтах занимается компания MaxMind, ссылка на которую присутствует в описании данной библиотеки.

Я не буду заниматься описанием процесса её установки на сервер, т.к. я сам на практике этим не занимался, и в Интернете на данный момент полно мануалов по установке PHP GeoIP как на Linux, так и на Windows сервера.

Могу только сказать, что у данного способа определения города, страны и прочей гео информации по IP в PHP есть два существенных минуса:

  • Доступ к базе полной информации по IP адресам, предоставляемой компанией MaxMind, платный. Причём, сумма в долларах, как ни странно 🙂 Бесплатно доступны лишь существенно урезанные варианты — http://dev.maxmind.com/geoip/geoip2/geolite2/
  • Учитывая, что PHP GeoIP — стороннее расширение, его необходимо будет отдельно устанавливать на сервер, что при условии использования shared хостинга может стать затруднительным мероприятием. Можно конечно, обратиться в техподдержку, но не факт, что вам помогут. Мне, например, при просьбе установить Sphinx отказали.
  • Определение города по IP в PHP с помощью альтернативных библиотек

    Ещё один способ узнать город по IP в PHP скрипте — это использование альтернативных серверных библиотек и баз информации для IP адресов, отличных от MaxMind.

    Но они обладают теми же минусами, что и предыдущий вариант, т.к. являются всего лишь конкурентами MaxMind. Доступы к базам и возможность использования их API также платная. Бесплатно можно получить только список стран и городов по IP, в то время как при платном тарифе можно получать более широкий перечень данных.

    Единственное преимущество над PHP GeoIP заключается в том, что данные библиотеки интегрируются в PHP коде, а не на уровне сервера, т.е. их можно использовать даже на shared хостингах.

    Примером такой библиотеки является предоставляемая сервисом db-ip.com.

    Кстати, указанный мною сервис предоставляет не только свою PHP библиотеку для получения гео данных по IP клиентов, но и доступ к базам информации по адресам. Так что, в принципе, никто вам не мешает использовать их в PHP GeoIP, чтобы использовать его API, но информацию брать из других источников.

    Ну, и уж точно никто вам не мешает написать собственный парсер файлов баз IP адресов для получения из них информации самостоятельно, без всяких сторонних разрешений.

    Как определить город по IP в PHP online

    Ну, и вот я подошёл к финальному способу как узнать страну по IP в PHP и прочую гео информацию, который использовал сам на практике.

    Он заключается в использовании API онлайн сервисов, которые позволяют получать данные по IP адресу в режиме онлайн.

    Определять город по IP в PHP я решил именно данным способом, т.к. он лишён главного недостатка предыдущих. А именно, он самый простой в реализации — не нужно ничего устанавливать и настраивать на сервере, а, тем более, просить об этом техподдержку shared хостингов.

    Для того, чтобы получить необходимую информацию по IP, достаточно всего лишь отправить запрос на определённый URL и обработать ответ.

    Что касается стоимости их использования — в большинстве своём они так же платные, т.к. работают, как правило, на основе существующих коммерческих баз IP. Но есть и бесплатные сервисы, которые предоставляют, возможно, на такую полную информацию, как коммерческие, но зато её можно получать в неограниченном объёме.

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

    В итоге, я отыскал то, что мне было необходимо, чем и хочу с вами определиться — http://www.geoplugin.com/

    Данный сервис позволяет как определять город и другую информацию по IP на сайте сервиса, так и производить это из кода. Далее я приведу пример определения страны по IP в PHP скрипте с помощью geoplugin.com. коде осуществляется с помощью кода, описанного в статье по ссылке.

    Как видите, суть приведённого кода заключается в определении IP адреса клиента, причём учитывается возможность его подключения через прокси, и отправке запроса по API GeoPlugin с дальнейшим декодированием и анализом результатов.

    В моём примере, как я уже и говорил, результатом работы данного скрипта будет являться код страны клиента сайта. Вообще, полный список возвращаемых параметров выглядит так (для примера решил взять IP Новосибирской области РФ):

    { "geoplugin_request":"195.208.128.3", "geoplugin_status":200, "geoplugin_credit":"Some of the returned data includes GeoLite data created by MaxMind, available from http:\/\/www.maxmind.com.", "geoplugin_city":"Novosibirsk", "geoplugin_region":"Novosibirsk", "geoplugin_areaCode":"0", "geoplugin_dmaCode":"0", "geoplugin_countryCode":"RU", "geoplugin_countryName":"Russian Federation", "geoplugin_continentCode":"EU", "geoplugin_latitude":"55.09", "geoplugin_longitude":"82.6519", "geoplugin_regionCode":"53", "geoplugin_regionName":"Novosibirsk", "geoplugin_currencyCode":"RUB", "geoplugin_currencySymbol":"руб", "geoplugin_currencySymbol_UTF8":"\u0440\u0443\u0431", "geoplugin_currencyConverter":58.9289 }

    Как видите, данный сервис использует упоминаемый ранее MaxMind (параметр geoplugin_credit), но платную информацию или нет — сложно предположить. С одной стороны, ссылка на источник говорит о том, что используется бесплатный доступ к БД IP, но, с другой, мы видим не только страну и город, но и ещё много всякой информации, включая город, географические координаты координаты (langitude, latitude), текущую валюту и даже её курс.

    Так что данный сервис можно назвать PHP GeoIP онлайн. Единственное его отличие от серверного аналога — то, что он получает информацию по IP немного медленнее за счёт отсутствия серверного кэширования. Но это ещё не значит, что его нет на самом сервере GeoPlugin 😉 Так что недостаток этот, скорее, символический.

    В любом случае, разработчики GeoPlugin заслуживают на аплодисменты, а, в особенности, ещё и за то, что они даже не захламили своё сайт контекстной рекламой. Т.е. как они вообще выживают — непонятно. Единственный способ сказать им «спасибо» — это пожертвования на PayPal счёт.

    Кстати, приведённый мною PHP код для определения города по IP является универсальным. Можете его использовать для получения гео данных и с помощью других сервисов. Единственное, что вам нужно будет в нём изменить — это URL API сервиса и имя необходимых параметров, которые вам нужно будет получить.

    На этом у меня всё. Пишите ваши отзывы о статье в комментариях ниже и не забывайте делиться записью со своими друзьями в социальных сетях.

    P.S. : если вам нужен сайт либо необходимо внести правки на существующий, но для этого нет времени и желания, могу предложить свои услуги.

    Более 5 лет опыта профессиональной разработки сайтов. Работа с PHP , OpenCart , WordPress , Laravel , Yii , MySQL , PostgreSQL , JavaScript , React , Angular и другими технологиями web-разработки.

    Опыт разработки проектов различного уровня: лендинги , корпоративные сайты , Интернет-магазины , CRM , порталы . В том числе поддержка и разработка HighLoad проектов . Присылайте ваши заявки на email [email protected] .

    В продолжение темы про IP, в этой статье будут рассмотрены способы определения страны, города и другой гео-ино о пользователе по его IP.

    GeoIP в виде PHP расширения

    Наверное самая часто используемая библиотека для определения IP (оф. док на php.net). Оно и не мудрено, ведь бинарная БД + скомпилированное PHP расширение работают быстрее всех остальных способов.

    Установка на Ubuntu Server:

    Sudo apt-get install php5-geoip

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

    После этих действий необходимо перезагрузить PHP. Это нужно для того что бы PHP интерпретатор подгрузил только что установленное расширение (php5-geoip) и новые базы IP адресов.

    Также периодически необходимо обновлять базы IP адресов:

    Sudo wget -N http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz sudo gunzip GeoIP.dat.gz sudo mv GeoIP.dat /usr/share/GeoIP/

    После обновления так же необходимо перезагружать PHP для применения обновленной базы IP адресов:

    Sudo service php5-fpm restart # если вы используете NGINX # или sudo service apache2 restart # если вы используете Apache

    После того как GeoIP установлен, его можно использовать в коде, например так: