Publicado por & archivado en PHP, Programación.

Obtener el país al que pertenece una dirección IP es bastante fácil y muy útil para algunos proyectos.

 

Lo primero es obtener la base de datos actualizada que relaciona IPs con países de Maxmind, que puede descargarse aquí:
http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip

 

El archivo es un ZIP que contiene un CSV con rangos de IPs relacionados con países. La carga se puede automatizar, por ejemplo poniendo una descarga en el cron una vez al mes, pero es posible cargar los datos desde phpmyadmin, importando el archivo CSV.

 

Para crear la base de datos se puede pegar esto en la ventana SQL de la base de datos en phpmyadmin:

CREATE TABLE `ip2c` (
 `id` int(10) unsigned NOT NULL auto_increment,
 `begin_ip` varchar(20) default NULL,
 `end_ip` varchar(20) default NULL,
 `begin_ip_num` int(11) unsigned default NULL,
 `end_ip_num` int(11) unsigned default NULL,
 `country_code` varchar(3) default NULL,
 `country_name` varchar(150) default NULL,
 PRIMARY KEY (`id`),
 KEY `begin_ip_num` (`begin_ip_num`,`end_ip_num`)
)

 

Una vez creada la tabla ip2c se pueden importar los datos usando phpmyadmin, en la opción “importar” eligiendo en tipo de archivo CSV y cambiando en Campos terminados en el valor por defecto “;” por “,” ya que el archivo de Maxmind utiliza coma en vez de punto y coma como separador de campos.

 

También se puede usar el siguiente script para automatizar la descarga, por ejemplo llamándolo una vez al mes desde el cron:


/**
 * @name Importa la base de datos de IPs a países de Maxmind
 * @copyright (c)2015 Intervia IT
 * @link http://intervia.com/doc/obtener-el-pais-a-partir-de-la-ip/
 * @license MIT http://opensource.org/licenses/MIT
 */


//Inicializa ezsql
include_once "ez_sql_core.php";
include_once "ez_sql_mysql.php";
$db = new ezSQL_mysql('database','pass','tabla','localhost');

//Poner a 1 para mostrar progreso en un navegador (a 0 para llamar desde el cron)
$progreso = 1;

//URL de Maxmind para descargar el archivo
$maxmindurl = 'http://geolite.maxmind.com/download/geoip/database/';

//Archivo de Maxmind comprimido
$maxmind = 'GeoIPCountryCSV.zip';

//Archivo de Maxmind DEScomprimido
$maxmindcsv = 'GeoIPCountryWhois.csv';

//Abre el archivo de log
$log = fopen('ip2c.log','a+');

//Muestra progreso (descargando archivo)
if (progreso){
 echo '<div style="position:absolute; top:5px; left:5px; background-color:#FFF; 
 width:500px;">[Descargando archivo de Maxmind]</div>';
 ob_flush(); flush(); 
}

//Descargar el archivo
file_put_contents($maxmind, file_get_contents($maxmindurl.$maxmind));
if (file_exists($maxmind)) fwrite($log,date("Y/m/d - H:i")." - DESCARGADO $maxmind\n");

//Obtener el path
$path = pathinfo(realpath($maxmind), PATHINFO_DIRNAME);

//Carga la clase zip y abre el archivo
$zip = new ZipArchive;
$res = $zip->open($maxmind);

//Si existe el archivo lo descomprime
if ($res === TRUE) {
 $zip->extractTo($path);
 $zip->close();
 fwrite($log,date("Y/m/d - H:i")." - DESCOMPRIMIDO el archivo $maxmind\n");
}else{

 //Escribe el error al log
 fwrite($log,date("Y/m/d - H:i")." - ERROR al abrir el archivo $maxmind\n");
}

//Si el archivo csv está vacío detiene el script y registra el error
if (!filesize($maxmindcsv)){
 fwrite($log,date("Y/m/d - H:i")." - ERROR $maxmindcsv vacío\n");
 exit;
}

/*
 * Si el archivo CSV está correcto, empiza la importación de datos
 */

//Vaciar la tabla actual
$db->query("TRUNCATE TABLE ip2c");
fwrite($log,date("Y/m/d - H:i")." - BORRADA la tabla ip2c\n");

//Importar en MySQL
$csvfile = fopen($maxmindcsv, "r"); 
while (($data = fgetcsv($csvfile, 0, ",")) !== FALSE) {

 //Cargar nombre del país en inglés
 //$country_name = $db->escape("$data[5]");

 //Cargar nombre del país en español
 $country_name = $db->get_var("SELECT pais_es FROM paises WHERE iso ='$data[4]' ");

 $db->query("INSERT into ip2c 
 (begin_ip,end_ip,begin_ip_num,end_ip_num,country_code,country_name) 
 VALUES ('$data[0]','$data[1]',$data[2],$data[3],'$data[4]','$country_name') ");

 //Muestra progreso (importando registros)
 if (progreso){
 echo '<div style="position:absolute; top:5px; left:5px; background-color:#FFF; 
 width:500px;">[Importando registro '.$db->insert_id.']</div>';
 ob_flush(); flush();
}

}
fclose($csvfile);
fwrite($log,date("Y/m/d - H:i")." - IMPORTADOS datos a la tabla ip2c\n");

//Borra los archivos
unlink($maxmindcsv);
unlink($maxmind);
fwrite($log,date("Y/m/d - H:i")." - BORRADOS archivos $maxmind y $maxmindcsv\n");

//Muestra progreso (importación finalizada)
if (progreso){
 echo '<div style="position:absolute; top:5px; left:5px; background-color:#FFF; 
 width:500px;">[Importación finalizada]</div>';
 ob_flush(); flush();
}

//Cierra el archivo de log
fclose($log); 

 

 

Este script necesita permisos de escritura en el directorio donde se encuentra para descargar y descomprimir el archivo y para borrarlos una vez terminado, y para escribir en el log. Si se quieren otras rutas basta con añadir el path delante.

Para el manejo de las bases de datos se usa ezsql que debe estar instalado en el mismo directorio o se debe alterar la ruta de los includes a donde se encuentren los archivos de ezsql.

Para cargar el idioma en español se necesita esta tabla SQL con la lista de idiomas. Si se prefieren los nombres de países en inglés hay que descomentar la línea debajo de “Cargar nombre del país en inglés” y comentar la que está debajo de “Cargar nombre del país en español”. También se podría añadir un segundo campo para tener los nombres en ambos idiomas o bien importarlo en inglés y obtener los nombres en español mediante una consulta a la tabla de países.

 

Una vez tenemos la base de datos cargada, podemos obtener el país de la IP con este código:


$ip = $_SERVER['REMOTE_ADDR'];

//Busca el país de cada IP
$ipnum = sprintf("%u",ip2long($ip));
$pais = $db->get_row("SELECT * FROM ip2c 
 WHERE $ipnum BETWEEN begin_ip_num 
 AND end_ip_num ");

echo 'El país de la IP '.$ip.' es '.$pais->country_name.
 '.<br>Código ISO del país: '.$pais->country_code;

 

 

Para que este código funcione tienes que usar ezsql.

 

 

 

3 Comentarios para “Obtener el país a partir de la IP”

Deja un comentario

Tu dirección de correo electrónico no será publicada.