Частенько сервер ipgeobase.ru не справляется с нагрузками. Если Вы напрямую к нему обращаетесь, то во время зависаний ipgeobase могут возникать трудности в работе вашего сайта, а может и не совсем корректная его работа из за использования гео привязки пользователей. Поэтому будет целесообразно скачать базу на свой сервер, импортировать его в базу данных и уже локально использовать. При такой работе перебоев в работе сайта связанных с недоступностью ipgeobase не будет. Сейчас опишу как импортировать данные ipgeobase в базу данных mysql и как их использовать.
Вам нужно скачать этот архив: geo.zip — тут находится php файл, который будет импортировать текстовую базу с ipgeobase в mysql. Для работы скрипта нужно будет настроить подключение к базе данных (указать сервер, пользователя и пароль).
Также в архиве находится sh файл, который после предварительного изменения можно поставить как задание на крон. И вызывать с определенной периодичностью (например, раз в неделю), чтобы поддерживать базу данных в актуальном состоянии.
Если Вы не умеете настраивать крон, то для Вас подробная инструкция как все сделать вручную.
[1] Скачиваем и распаковываем файл geo.zip в папку на сервере
[2] В архиве есть файл geo.sql импортируем его в вашу БД. Этот файл создаст две пустые таблицы с названиями geo__base и geo__cities
Содержание файла geo.sql
[3] В php файлах import_geobase.php и check_geobase.php в начале каждого файла указываем параметры подключения к вашей БД
[4] Отсюда http://ipgeobase.ru/cgi-bin/Archive.cgi скачиваем архив geo_files.zip (http://ipgeobase.ru/files/db/Main/geo_files.zip)
[5] Распаковываем этот архив. Среди извлеченных файлов будут файлы с названием cidr_optim.txt и cities.txt — эти файлы нужно загрузить на сервер рядом с php файлами из архива geo.zip
[6] В браузере запускаем файл import_geobase.php — Ждем окончания импорта. Проверяем недавно созданные таблицы. После запуска импорта они очищаются и в них заносятся данные.
Содержание файла import_geobase.php
[7] Если шестой пункт прошел успешно, в браузере открываем файл check_geobase.php
Содержание файла check_geobase.php
[8] В итоге после всего этого должны увидеть нечто вроде этого:
Array
(
[long_ip1] => 1560264704
[long_ip2] => 1560272895
[ip1] => 92.255.192.0
[ip2] => 92.255.223.255
[country] => RU
[city_id] => 1283
[city] => Казань
[region] => Республика Татарстан
[district] => Приволжский федеральный округ
[lat] => 55.7965
[lng] => 49.1082
)
Название города: Казань
Если у Вас это получилось. Поздравляю 🙂 Если нет, попробуй внимательно пройтись по всем пунктам несколько раз и найти свою ошибку. Эти скрипты я даю лишь как примеры, а не готовые решения. Бесплатным обучением PHP и благотворительностью не занимаюсь. Написанный тут материал передаю как есть. Поэтому в комментариях желательно писать только с конкретными вопросами именно по работе скрипта. Буду благодарен, если источником информации при обсуждении похожих тем на разных форумах будете давать ссылку на этот пост.
На правах рекламы:
Солнечные жаркие дни не за горами. Успейте купить солнечные очки. Какие очки купить и обзоры солнечных очков Вам представит сайт sunglasses-reviews.ru
Большое спасибо! Именно то, что очень хотелось найти =) Отлично работает!
Рад, что кому-то полезен 🙂
А сколько в среднем вес базы?
В Mysql около 11 Mb. Размер запакованного архива с базой смотрите на сайте ipgeobase.ru в разделе «архив»
Скрипт работает, но что-то с кодировкой. Если нужна кодировка cp1251, то что нужно сделать? Достаточно будет ли в файле import_geobase.php заменить set charset utf8 и т.д. на charset cp1251?
Чтобы это сделать, нужно поменять кодировку базы данных и в скрипте убрать строки, которая из windows-1251 конвертирует в utf-8
$row = iconv(‘windows-1251’, ‘utf-8’, $row); // вот это
Привет!
В первую очередь спасибо за скрипт. Сейчас реализую у себя на сайте все работает.
Только у меня была проблема $long_ip получалось отрицательным, нашел решение дописал строку в check_geobase.php после:
$long_ip = ip2long($ip);
добавил:
if ($long_ip < 0) $long_ip += pow(2,32);
Спасибо за скрипт! Очень помогло
php -f index.php 77.108.109.99
\PHP Notice: Undefined variable: ipa in on line 120
PHP Warning: Invalid argument supplied for foreach() in on line 120
PHP Notice: Undefined variable: ipa in on line 120
PHP Warning: Invalid argument supplied for foreach() in on line 120
Передайте функции IP
почему то не работает, я что то не так делаю?
Да. Откройте php файл и посмотрите. Скрипт не предназначен для запуска в консоли. IP адрес скрипт получает из глобальных переменных $_SERVER, а Ваш вариант передачи ip не предусмотрен.
Класс!
Все работает отлично.
Спасибо большое!
Здравствуйте.
Скрипт отличный. Спасибо большое.
Единственное возник вопрос. В файле geo.php идет обращение к:
$link = ‘ipgeobase.ru:7020/geo?ip=’.$this->ip;
Т.е. обращение все равно к этому сайту а не к базе, в которую мы залили данные?
Обратите внимание на содержание файла check_geobase.php
Там показан пример как обращаться к базе данных и получать локальные данные для ip адреса.
Т.е. вот из этого архива что выше, файл geo.php еще не готов для работы с локальной базой?
check_geobase.php — также обращается к geo.php
check_geobase.php обращается к geo.php не для запроса с геобазы, а лишь для того чтобы узнать IP адрес. Советую получше изучить скрипт.
А зачем обращаться к серверу ipgeobase.ru, если можно IP узнать через функцию:
$_SERVER[‘REMOTE_ADDR’]
У меня на денвере работает, если только вписать туда IP:
$link = ‘ipgeobase.ru:7020/geo?ip=46.151.240.15’
Пробывал в базе исправить один московский IP на 2130706433 (127.0.0.1 — локальный IP денвера), город не определился. Выходит, что локальную базу не читает.
Скрипт не обращается к серверу чтобы узнать IP. Скрипт обращается к серверу чтобы узнать гео-данные об этом IP. Внимательней посмотрите код.
Скрипт обращается к серверу чтобы узнать гео-данные об этом IP ?
А зачем же тогда скачивать базу на свой сервер?
Если-бы я хорошо разбирался в кодах, то я бы сам написал этот скрипт.
Описание об установке и работе не совсем понятно.
Импорт отлично работает, сразу разобрался. Спасибо!
«index.php» вобще не понятно для чего, там даже данных для подключения к базе нет.
А «check_geobase.php» работает, даже если строку обращения к «ipgeobase.ru» в «geo.php» удалить. И еще много чего удалял в «geo.php», при этом работает.
Увы для моего проекта этот скрипт не подходит. А за базу и импорт базы большое спасибо!
Класс в файле geo.php нужен для работы без импорта базы. Если Вы решили воспользоваться импортом базы, то, как Вы заметили, необходимости обращаться к стороннему серверу нет и данные нужно извлекать лишь с базы данных.
Ну что, тогда пора новую статью написать о том как использовать свою локальную базу? Чтобы там можно было выбрать вывод любых данных из базы и вывод информации в зависимости от города или региона посетителя.
В седьмом пункте этой статьи уже указано как пользоваться локальной базой.
Можете вместо переменной $ip вводить любой IP полученный любым удобным Вам способом.
Однако хочу предупредить что $_SERVER[‘REMOTE_ADDR’] не поможет выявить реальный IP если посетитель вашего сайта использует прокси или пользуется функцией «турбо» в Опере или яндекс.браузере.
А вот сейчас только понял, что «geo.php» не нужен. И мои посетители с прокси меня не интересуют.
все сделал по рецепту, определяю ip = 176.120.198.15, перевожу в число = 1334262257. Но такое число в диапазоне итальянских ip почему-то.
Когда обращаюсь через ваш класс к вашей БД, то определяет все нормально.
из-за чего такое может быть?
все проблема решена, спасибо пользователю Михаилу
Спасибо, все настроил, все работает!)
а это в джумла 2.5 работает и как установить поподробней пожалуйста))))
Заработает если сумеете поставить. Никаких подробностей не расскажу, не рассматриваю частные примеры использования.
и как понять импортируем в бд(базу данных) надо её закинуть в мененджер файлов
Думаю уровень ваших знаний пока маловат, чтобы с этими скриптами возиться. Почитайте в интернете что из себя представляет импорт, и как нужно импортировать дамп базы данных.
Советую вам убрать индекс из таблицы geo__base. У меня на компьютере время запроса на выборку одной строки из таблицы с индексом составляет 0,17с. Без индекса: 0,017. Быстрее в 10 раз.
Так то индекс предназначен для того, чтобы ускорять. Не стоит делать выводы из-за единичного случая. При моих тестах с индексом было гораздо быстрее, чем без него
Здравствуйте!
Скрипт отличный. Только вот при импорте в бд выдается ошибка:
Incorrect integer value: ‘- ‘ for column ‘city_id’ at row 1
Если подумать, то ничего удивительного в этом нет. city_id имеет тип INT, т.е. целочисленное значение и «-» туда никак не подходит.
Подскажите, пожалуйста, как быть?
Попробуйте поменять тип поля в БД или регулярное выражение в скрипте. Когда я делал, такой ошибки не ловил, возможно были незначительные изменения.
Отличный скрипт! Пробовал версию без базы данных — сайт частенько подвисал из-за постоянного обращения к ipgeobase. Советую всем настроить данную версию вместе с crontab’ом!
Для адреса 8.8.8.8 функция get_data возвращает значение null. Ошибка заключается в неверном слиянии массивов $res1 и $res2
Ниже исправленная версия:
function get_data($ip)
{
$country = ‘N/A’;
if(empty($ip))
exit(‘Передайте функции IP’);
$long_ip = ip2long($ip);
if ($long_ip < 0) $long_ip += pow(2,32);
$q = mysql_query("SELECT * FROM
geo__base
WHERElong_ip1
=’$long_ip’ LIMIT 1″);$data = false;
if (mysql_num_rows($q))
{
$res1 = mysql_fetch_assoc($q);
$q = mysql_query(«SELECT * FROM
geo__cities
WHEREcity_id
=’$res1[city_id]’ LIMIT 1″);if (mysql_num_rows($q))
{
$res2 = mysql_fetch_assoc($q);
//$data = array_merge($res1, $res2); <- ТУТ ОШИБКА
}
$data = array_merge((array)$res1, (array)$res2);
}
return $data;
}
В Вашем примере есть ошибка, так как переменной res2 может не быть и функция array_merge вернет false — тоже самое, что получится и в моем варианте кода. Только у меня вариант ошибки предусмотрен и заключен в условие, а у Вас нет.
Уважаемый автор!
Большое спасибо за скрипт. Работает отлично. Я выбрал вариант с переносом данных в свою SQL базу, но есть проблема. При сохранении IP более 127.127.127.127 функция ip2long присваивает целочисленной переменной отрицательное значение (это потому, что переменная signed а не unsigned). И, соответственно, город не определяется.
При сохранении результата ip2long в check_geobase.php в строке 47 необходимо сделать замену:
вместо $long_ip = ip2long($ip);
необходимо написать $long_ip=sprintf(‘%u’, ip2long($ip));
В данном случае всё работает хорошо.
Ещё раз спасибо за отличный скрипт.
С уважением,
Сергей
регулярные выражения учил по одной книге, но вот ваш патерн понять не могу, могли бы разъяснить что он проверяет?
Смотря про какой паттер Вы говорите. Если парсинг данных со строки, то паттерн служит для того, чтобы достать из строки данные так, чтобы их можно было внести в БД.
А почему импорт не сделать через массовое добавление (смотрим в поисковике bulk import mysql)? Например по 100 записей за проход — время импорта в 100 раз снизится почти.
Представленное мною решение — это всего лишь один вариант из ста. Каждый может на его основе сделать улучшенный способ импорта. Мое решение не претендует быть лучшим, я лишь привел пример и не заморачивался 🙂 Если разбираетесь, улучшайте и используйте как считаете нужным.
Не стал переносить на сайт, решил попробовать вариант вызова Вашей БД с вашего сайта: $link = ‘http://www.ipgeobase.ru:7020/geo?ip=’.’62.220.33.216′;
На Денвере все работает, как только переношу на сайт — тишина! Какая может быть причина? Подскажите, плиз.
Возможно на хостинге не включен curl. Причин может быть несколько, но для начала проверьте именно наличие curl’а.
В дополнение к вышенаписанному:
$ch = curl_init($link);
echo «init: «.$ch.»;
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$string = curl_exec($ch);
curl_close($ch);
echo «string: «.$string.»;
На Денвере все это работает, на сайте — висит!
Ничего не выводится… 🙁
Функция phpinfo(); на моем бесплатном хостинге не работает!
Может посоветуете нормальный, где Ваша тема заработает? Спасибо, заранее…
Проверил. На хостинге curl включен!
хостинг посоветовать не смогу. давно использую только вдс.
На Денвере получилось!
Но, не все. Вывелось содержимое массива в другой кодировке:
_____________________________________________
echo »;
print_r($data);
echo »;
// если нужно использовать только 1 значение из массива, то можно выводить так
echo ‘Название города: ‘.$data[‘city’].»;
____________________________________________
Результат:
Array
(
[long_ip1] => 1054613504
[long_ip2] => 1054617599
[ip1] => 62.220.32.0
[ip2] => 62.220.47.255
[country] => RU
[city_id] => 1956
[city] => РќРёР¶РЅРёР№ РќРѕРІРіРѕСЂРѕРґ
[region] => Нижегородская область
[district] => Приволжский федеральный округ
[lat] => 56.3299
[lng] => 44.0092
)
Название города: РќРёР¶РЅРёР№ РќРѕРІРіРѕСЂРѕРґ
______________________________
Как поменять кодировку вывода?
Как использовать другую кодировку для БД и в скрипте написано в комментариях скрипта, да и можно легко догадаться как поменять кодировку, если просто открыть скрипт. Но у Вас похоже, что можно обойтись сменой кодировки через htaccess. Поищите в интернете как поменять кодировку через .htaccess — я просто не знаю к какой кодировке вы пытаетесь получить данные.
Сделал на основе вашего класса и локальной базы георедирект на российскую и украинскую версии сайта. Крым и Россия идут на рублевый поддомен, остальная Украина идет на гривнёвый поддомен. Все остальные идут на страницу ручного выбора версии сайта. horeca-service.com
Пришлось делать потому как не только валюта разная, но и ассортимент товаров в зависимости от стран поставщиков. Компания теперь международная.
Спасибо за класс и метод.
На IPv6 не работает к сожелению
Да, вся работа сервиса основана на IPv4