Импорт базы Ipgeobase в локальную базу данных и дальнейшее использование.
Опубликовано 30 Март 2012 от FaNiska
Частенько сервер ipgeobase.ru не справляется с нагрузками. Если Вы напрямую к нему обращаетесь, то во время зависаний ipgeobase могут возникать трудности в работе вашего сайта, а может и не совсем корректная его работа из за использования гео привязки пользователей. Поэтому будет целесообразно скачать базу на свой сервер, импортировать его в базу данных и уже локально использовать. При такой работе перебоев в работе сайта связанных с недоступностью ipgeobase не будет.
Вам нужно скачать архив.
geo.zip — тут находится php файл, который будет импортировать текстовую базу с ipgeobase в mysql. Для работы скрипта нужно будет настроить подключение к базе данных (указать сервер, пользователя и пароль).
Также в архиве находится sh файл, который после предварительного изменения можно поставить как задание на крон. И вызывать с определенной периодичностью (например, раз в неделю), чтобы поддерживать базу данных в актуальном состоянии.
подробная инструкция как все сделать вручную
[1] Скачиваем и распаковываем файл geo.zip в папку на сервере
[2] В архиве есть файл geo.sql импортируем его в вашу БД. Этот файл создаст две пустые таблицы с названиями geo__base и geo__cities
Содержание файла geo.sql
Код:--
-- Структура таблицы `geo__base`
--
CREATE TABLE IF NOT EXISTS `geo__base` (
`long_ip1` bigint(20) NOT NULL,
`long_ip2` bigint(20) NOT NULL,
`ip1` varchar(16) NOT NULL,
`ip2` varchar(16) NOT NULL,
`country` varchar(2) NOT NULL,
`city_id` int(10) NOT NULL,
KEY `INDEX` (`long_ip1`,`long_ip2`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `geo__cities`
--
CREATE TABLE IF NOT EXISTS `geo__cities` (
`city_id` int(10) NOT NULL,
`city` varchar(128) NOT NULL,
`region` varchar(128) NOT NULL,
`district` varchar(128) NOT NULL,
`lat` float NOT NULL,
`lng` float NOT NULL,
PRIMARY KEY (`city_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
[3] В php файлах import_geobase.php и check_geobase.php в начале каждого файла указываем параметры подключения к вашей БД
[4] Отсюда http://ipgeobase.ru/cgi-bin/Archive.cgi скачиваем архив geo_files.zip
ipgeobase.ru/files/db/Main/geo_files.zip
[5] Распаковываем этот архив. Среди извлеченных файлов будут файлы с названием cidr_optim.txt и cities.txt — эти файлы нужно загрузить на сервер рядом с php файлами из архива geo.zip
[6] В браузере запускаем файл import_geobase.php — Ждем окончания импорта. Проверяем недавно созданные таблицы. После запуска импорта они очищаются и в них заносятся данные.
Содержание файла import_geobase.php:
Код:<?php
set_time_limit(0); // указываем, чтобы скрипт не ограничивался временем по умолчанию
ignore_user_abort(1); // указываем, чтобы скрипт продолжал работать даже при разрыве
// настройки для подключения к БД
$SERVER = 'localhost';
$DB_NAME = 'geo'; // название ВАШЕЙ базы данных
$DB_USER = 'geo'; // имя пользователя ВАШЕЙ бд
$DB_PASS = 'geo'; // пароль от ВАШЕЙ бд
// Соединяемся с базой данных
// авторизация на сервере базы
if (!($db = mysql_pconnect($SERVER, $DB_USER, $DB_PASS)))
{
echo "Нет соединения с сервером базы<br />*проверьте параметры подключения";
exit;
}
// подключение к базе
if (!mysql_select_db($DB_NAME, $db))
{
echo "База даных не найдена<br />*проверьте, существует ли данная база";
exit;
}
mysql_query('set charset utf8', $db);
mysql_query('SET names utf8', $db);
mysql_query('set character_set_client="utf8"', $db);
mysql_query('set character_set_connection="utf8"', $db);
mysql_query('set character_set_result="utf8"', $db);
// проверяем наличие файла cities.txt в папке рядом с этим скриптом
if(file_exists('cities.txt'))
{
mysql_query("TRUNCATE TABLE `geo__cities`"); // очищаем таблицу перед импортом актуальных данных
$file = file('cities.txt');
$pattern = '#(\d+)\s+(.*?)\t+(.*?)\t+(.*?)\t+(.*?)\s+(.*)#';
foreach ($file as $row)
{
$row = iconv('windows-1251', 'utf-8', $row);
if(preg_match($pattern, $row, $out))
{
mysql_query("INSERT INTO `geo__cities` (`city_id`, `city`, `region`, `district`, `lat`, `lng`) VALUES('$out[1]', '$out[2]', '$out[3]', '$out[4]', '$out[5]', '$out[6]')");
}
}
echo mysql_error();
}else
{
echo 'Ошибка! Файл cities.txt должен лежать рядом с этим файлом!';
}
// проверяем наличие файла cidr_optim.txt в папке рядом с этим скриптом
if(file_exists('cidr_optim.txt'))
{
mysql_query("TRUNCATE TABLE `geo__base`"); // очищаем таблицу перед импортом актуальных данных
$file = file('cidr_optim.txt');
$pattern = '#(\d+)\s+(\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+-\s+(\d+\.\d+\.\d+\.\d+)\s+(\w+)\s+(\d+|-)#';
foreach ($file as $row)
{
if(preg_match($pattern, $row, $out))
{
mysql_query("INSERT INTO `geo__base` (`long_ip1`, `long_ip2`, `ip1`, `ip2`, `country`, `city_id`) VALUES('$out[1]', '$out[2]', '$out[3]', '$out[4]', '$out[5]', '$out[6]')");
}
}
echo mysql_error();
}else
{
echo 'Ошибка! Файл cidr_optim.txt должен лежать рядом с этим файлом!';
}
?>
[7] Если шестой пункт прошел успешно, в браузере открываем файл check_geobase.php
Содержание файла check_geobase.php:
Код:<?php
// настройки для подключения к БД
$SERVER = 'localhost';
$DB_NAME = 'geo'; // название базы данных
$DB_USER = 'geo'; // имя пользователя бд
$DB_PASS = 'geo'; // пароль
// Соединяемся с базой данных
// авторизация на сервере базы
if (!($db = mysql_pconnect($SERVER, $DB_USER, $DB_PASS)))
{
echo "Нет соединения с сервером базы<br />*проверьте параметры подключения";
exit;
}
// подключение к базе
if (!mysql_select_db($DB_NAME, $db))
{
echo "База даных не найдена<br />*проверьте, существует ли данная база";
exit;
}
mysql_query('set charset utf8', $db);
mysql_query('SET names utf8', $db);
mysql_query('set character_set_client="utf8"', $db);
mysql_query('set character_set_connection="utf8"', $db);
mysql_query('set character_set_result="utf8"', $db);
include('geo.php');
$geo = new Geo(); // запускаем класс
$ip = $geo->get_ip(); // получаем ip адрес
function get_data($ip)
{
$country = 'N/A';
if(empty($ip))
exit('Передайте функции IP');
$long_ip = ip2long($ip);
$q = mysql_query("SELECT * FROM `geo__base` WHERE `long_ip1`<='$long_ip' AND `long_ip2`>='$long_ip' LIMIT 1");
$data = false;
if (mysql_num_rows($q))
{
$res1 = mysql_fetch_assoc($q);
$q = mysql_query("SELECT * FROM `geo__cities` WHERE `city_id`='$res1[city_id]' LIMIT 1");
if (mysql_num_rows($q))
{
$res2 = mysql_fetch_assoc($q);
$data = array_merge($res1, $res2);
}
}
return $data;
}
$data = get_data($ip); // запускаем функцию и получем данные
if(!$data)
{
// если функция вернула false. значит ip не найден в базе данных
}else
{
// выводим все полученные данные об IP
echo '<pre>';
print_r($data);
echo '</pre>';
// если нужно использовать только 1 значение из массива, то можно выводить так
echo 'Название города: '.$data['city'].'<br/>';
// список возможных ключей для использования 'country', 'city', 'region', 'district', 'lat', 'lng'
}
?>
[8] По пути /web/netcat/modules/default редактируем function.inc.php
В самый конец вставляем классы и функции:
Код:
class Geo
{
public function __construct($options = null) {
$this->dirname = dirname(__file__);
// ip
if(!isset($options['ip']) OR !$this->is_valid_ip($options['ip']))
$this->ip = $this->get_ip();
elseif($this->is_valid_ip($options['ip']))
$this->ip = $options['ip'];
// кодировка
if(isset($options['charset']) && $options['charset'] && $options['charset']!='windows-1251')
$this->charset = $options['charset'];
}
/**
* функция возвращет конкретное значение из полученного массива данных по ip
* @param string - ключ массива. Если интересует конкретное значение.
* Ключ может быть равным 'inetnum', 'country', 'city', 'region', 'district', 'lat', 'lng'
* @param bolean - устанавливаем хранить данные в куки или нет
* Если true, то в куки будут записаны данные по ip и повторные запросы на ipgeobase происходить не будут.
* Если false, то данные постоянно будут запрашиваться с ipgeobase
* @return array OR string - дополнительно читайте комментарии внутри функции.
*/
function get_value($key = false, $cookie = true)
{
$key_array = array('inetnum', 'country', 'city', 'region', 'district', 'lat', 'lng');
if(!in_array($key, $key_array))
$key = false;
// если используем куки и параметр уже получен, то достаем и возвращаем данные из куки
if($cookie && isset($_COOKIE['geobase']))
{
$data = unserialize($_COOKIE['geobase']);
}
else
{
$data = $this->get_geobase_data();
setcookie('geobase', serialize($data), time()+3600*24*7); //устанавливаем куки на неделю
}
if($key)
return $data[$key]; // если указан ключ, возвращаем строку с нужными данными
else
return $data; // иначе возвращаем массив со всеми данными
}
/**
* функция определяет ip адрес по глобальному массиву $_SERVER
* ip адреса проверяются начиная с приоритетного, для определения возможного использования прокси
* @return ip-адрес
*/
function get_ip()
{
$ip = false;
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
$ipa[] = trim(strtok($_SERVER['HTTP_X_FORWARDED_FOR'], ','));
if (isset($_SERVER['HTTP_CLIENT_IP']))
$ipa[] = $_SERVER['HTTP_CLIENT_IP'];
if (isset($_SERVER['REMOTE_ADDR']))
$ipa[] = $_SERVER['REMOTE_ADDR'];
if (isset($_SERVER['HTTP_X_REAL_IP']))
$ipa[] = $_SERVER['HTTP_X_REAL_IP'];
// проверяем ip-адреса на валидность начиная с приоритетного.
foreach($ipa as $ips)
{
// если ip валидный обрываем цикл, назначаем ip адрес и возвращаем его
if($this->is_valid_ip($ips))
{
$ip = $ips;
break;
}
}
return $ip;
}
/**
* функция для проверки валидности ip адреса
* @param ip адрес в формате 1.2.3.4
* @return bolean : true - если ip валидный, иначе false
*/
function is_valid_ip($ip=null)
{
if(preg_match("#^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$#", $ip))
return true; // если ip-адрес попадает под регулярное выражение, возвращаем true
return false; // иначе возвращаем false
}
}
function get_data($ip)
{
$country = 'N/A';
if(empty($ip))
exit('Передайте функции IP');
$long_ip = ip2long($ip);
$q = mysql_query("SELECT * FROM `geo__base` WHERE `long_ip1`<='$long_ip' AND `long_ip2`>='$long_ip' LIMIT 1");
$data = false;
if (mysql_num_rows($q))
{
$res1 = mysql_fetch_assoc($q);
$q = mysql_query("SELECT * FROM `geo__cities` WHERE `city_id`='$res1[city_id]' LIMIT 1");
if (mysql_num_rows($q))
{
$res2 = mysql_fetch_assoc($q);
$data = array_merge($res1, $res2);
}
}
return $data;
}
function substr_unicode($str, $s, $l = null) {
return join("", array_slice(
preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY), $s, $l));
}
[9] В макеты дизайна сайта, в те, которые используются в разделах, в каторых вы хотите оперировать получением id города
вставьте код:
Код:$geo = new Geo(); // запускаем класс
$ip = $geo->get_ip(); // получаем ip адрес
$data = get_data($ip); // запускаем функцию и получем данные
[10] в самих компонентах используем уже следующую конструкцию:
Код:<?
if(!$data)
{
echo "Город не определен.<br/>";
echo "Что угодно еще";
}else
{
echo 'Название города: '.$data['city'].'<br/>';
echo 'код города: '.$data['city_id'].'<br/>';
}
?>
[11] Если мы хотим использовать список городов ( который будет постоянно свежим)
а) создаем новый список region_bac - Список Городов.
б) создаем новый компонент. В префиксе этого компонента вставляем код:
Код:<? $nc_core->db->query("INSERT INTO `название вашей базы`.`classificator_region_bac`(region_bac_ID,region_bac_Name,region_bac_Priority) SELECT city_id,city,city_id FROM `название вашей базы`.`geo__cities`");?>
<? echo "done";?>
Этот код скопирует все города, и их ID в classificator_region_bac Таким образом в интерфейсе админки только что созданного списка увидим новый список городов. Россия и Украина.
Не забудьте этот компонент добавить в скрытый раздел вашего сайта и поставить системный планировщик задач на выполнение
после обновления списка городов с ipgeobase.
Вроде всё. Пользуюсь сам.
Круто и то, что можно использовать штатный функционал системы, в т.ч. и список городов.
Заметил, при добавлении нового города, ему присваивается новый ID. Уже имеющиеся ID городов не меняются.
Комментарии 0