Определение страны и города посетителя сайта по его IP-адресу применяется во многих случаях. Например, автоматическая подстройка языка отображения сайта, более точный таргетинг рекламных или информационных блоков сайта, разграничение доступа к разделам сайта для разных источников трафика, а также для многих других целей. Наиболее полные базы географического положения IP-адресов в настоящее время предоставляет компания
MaxMind в своей базе GeoLite City. Бесплатный вариант базы содержит данные с точностью до города, его можно скачать с сайта в
бинарном формате (в распакованном виде около 30 мегабайт) и в
формате CSV (в распакованном виде около 130 мегабайт). На сайте также можно оформить подписку на коммерческие варианты базы, содержащие данные с точностью до улиц и обновляющиеся еженедельно, но это только если вашему проекту действительно требуется такая точность. Обновления бесплатной базы выходят регулярно, обычно в первых числах каждого месяца. Пример работы скрипта с коммерческой географической базой можно посмотреть на
сайте MaxMind. Там же на сайте можно скачать бесплатные
базы стран мира,
почтовые индексы некоторых стран и много других полезных данных. К сожалению, самые вкусности предоставляются только за деньги.
Доступ к базе осуществляется через API, для некоторых популярных языков программирования они расписаны
на сайте. Например,
для PHP, кроме собственно самой базы, потребуются еще файлы
geoipcity.inc,
geoip.inc и
geoipregionvars.php. Вызов функции определения положения очень простой:
<?
// Подключить класс для работы с базой
include "geoipcity.inc";
// IP-адрес для проверки
$visitor_ip="70.240.110.17";
// Открыть файл базы
$gi=GeoIP_open("GeoLiteCity.dat", GEOIP_STANDARD);
// Получить данные из базы
$record=GeoIP_record_by_addr($gi,$visitor_ip);
// Вывести данные на экран
print_r($record);
// Закрыть соединение с базой
GeoIP_close($gi);
?>
Результат работы скрипта будет следующим:
geoiprecord Object (
[country_code] => US
[country_code3] => USA
[country_name] => United States
[region] => TX
[city] => Houston
[postal_code] =>
[latitude] => 29.7755
[longitude] => -95.4152
[area_code] => 713
[dma_code] => 618
[metro_code] => 618
)
Отдельные параметры можно получить из соответствующих полей объекта. Для более оперативного доступа к данным можно хранить базу в памяти целиком (смотрите примеры в
описаниях API на офсайте), но такое расточительное использование ресурсов допустимо только на выделенных серверах.
Для автоматического обновления базы я написал вот такой небольшой скрипт. Он выкачивает на мой хост архив GeoLite City в бинарном формате, а затем распаковывает его для дальнейшего использования. Время обновления вместе с загрузкой файла составляет 3-5 секунд, так что оно особо не повлияет на работоспособность даже высоконагруженного проекта.
<?
$lnk="http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz";
if ($f1=@fopen($lnk,"r")) {
// Скачать файл архива и сохранить его локально
if ($f2=@fopen("GeoLiteCity.dat.gz","w+")) {
while (!feof($f1)) {
$data=fread($f1,10000);
fwrite($f2,$data);
}
fclose($f1);
fclose($f2);
// Распаковать архив в файл GeoLiteCity.dat
if ($f1=@gzopen("GeoLiteCity.dat.gz","rb")) {
if ($f2=@fopen("GeoLiteCity.dat","w+")) {
do {
$data=gzread($f1,100000);
fwrite($f2,$data);
} while ($data!="");
gzclose($f1);
fclose($f2);
}
else {
echo "Error create database file";
}
}
else {
echo "Error open database file";
}
// Удалить скачанный архив
unlink("GeoLiteCity.dat.gz");
}
else {
echo "Error create file";
fclose($f1);
}
}
else {
echo "Error open remote file";
}
?>
Опытным путем установлено, что при слишком частом скачивании файла базы с сервера MaxMind с одного и того же IP-адреса (что-то около пяти раз в день), доступ блокируется на сутки. Поэтому обновляйте файл только когда это действительно нужно. У меня на сайте он обновляется по планировщику cron 10-го числа каждого месяца. Еще время от времени рекомендуется проверять наличие новых версий файлов API, они тоже иногда обновляются.
Для максимально точного таргетинга в пределах России можете дополнительно использовать данные
IpGeoBase. База обновляется ежедневно, данные в ней хранятся в трех вариантах - master (разбивка по городам), slave (подробная информация по округам) и максимально подробная база с указанием районов и провайдеров. К сожалению, данные в базе хранятся в текстовом виде, по строкам, разделенными символами табуляции. На
странице примеров можно скачать примеры интерфейсов для взаимодействия с он-лайн сервисом и для парсинга файлов базы. Готовых решений на PHP нет, возможно, что когда-нибудь сделаю.