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

Maxmind ha dejado de ofrecer su listado con rangos de IPs por países en CSV en enero de 2019 y aunque aun es posible usarlo mediante un formato binario, es mejor alternativa usar ip2location LITE:
https://download.ip2location.com/lite/IP2LOCATION-LITE-DB1.CSV.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.

 

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

CREATE TABLE IF NOT EXISTS `ip2c` (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `begin_ip` char(15) DEFAULT NULL,
  `end_ip` char(15) DEFAULT NULL,
  `begin_ip_num` int(11) UNSIGNED DEFAULT NULL,
  `end_ip_num` int(11) UNSIGNED DEFAULT NULL,
  `country_code` char(2) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `begin_ip_num` (`begin_ip_num`,`end_ip_num`),
  KEY `begin_ip` (`begin_ip`),
  KEY `end_ip` (`end_ip`),
  KEY `country_code` (`country_code`)
) ENGINE=MyISAM DEFAULT CHARSET=ascii;

 

Para cargar los datos en MySQL se puede usar el siguiente script, se puede automatizar por ejemplo llamándolo una vez al mes desde el cron:


/**
 * @name Import ip2location LITE to MySQL
 * @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
 */


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

//URL of ip2location to download the file
$ip2location_url = 'https://download.ip2location.com/lite/';

//Compressed ip2location file
$ip2location_zip = 'IP2LOCATION-LITE-DB1.CSV.ZIP';

//DEcompressed ip2location file
$ip2location_csv = 'IP2LOCATION-LITE-DB1.CSV';

//Other zip files
$ip2location_license = 'LICENSE-CC-BY-SA-4.0.TXT';
$ip2location_readme = 'README_LITE.TXT';

//Path to tmp directory
$_tmp_dir = '/path/to/tmp/directory/';

//Full path of the compressed ip2location file
$ip2location_zip_file = $_tmp_dir.$ip2location_zip;

//Full path of the DEcompressed ip2location file
$ip2location_csv_file = $_tmp_dir.$ip2location_csv;

//Full path of other zip files
$ip2location_license_file = $_tmp_dir.$ip2location_license;
$ip2location_readme_file = $_tmp_dir.$ip2location_readme;

//Download file
file_put_contents($ip2location_zip_file, file_get_contents($ip2location_url.$ip2location_zip));

//Get path
$path = pathinfo(realpath($ip2location_zip_file), PATHINFO_DIRNAME);

//Initialize zip class and open file
$zip = new ZipArchive;
$res = $zip->open($ip2location_zip_file);

//Unzip it if file exist
if ($res === true) {
$zip->extractTo($path);
$zip->close();
}



/*
* Import into MySQL
*/

//Truncate current table data
$db->query("TRUNCATE TABLE ip2c");

$i = 1;
$ip2c_sql = null;
$csvfile = fopen($ip2location_csv_file, "r");

//Iterate every csv line to create SQL insert data set
while (($i2c = fgetcsv($csvfile, 0, ",")) !== FALSE) {
$begin_ip = long2ip($i2c[0]);
$end_ip = long2ip($i2c[1]);
if ($i2c[2] == '-') {
$i2c[2] = 'OO';
}
$ip2c_sql .= "($i,'$begin_ip','$end_ip','$i2c[0]','$i2c[1]','$i2c[2]'),";
$i++;
}
fclose($csvfile);
$ip2c_sql = preg_replace("/,$/",'',ip2c_sql);

//Insert new data
$db->query("
INSERT INTO ip2c
(id,begin_ip,end_ip,begin_ip_num,end_ip_num,country_code)
VALUES $ip2c_sql ");



/*
* Deletes remaining files
*/
unlink($ip2location_csv_file);
unlink($ip2location_zip_file);
unlink($ip2location_license_file);
unlink($ip2location_readme_file);

 

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_var("SELECT country_code FROM ip2c 
 WHERE $ipnum BETWEEN begin_ip_num 
 AND end_ip_num ");

echo 'El país de la IP '.$ip.' es '.$pais;

 

La base de datos de ip2location contiene el nombre del país en inglés además del código ISO, pero en mi opinión es un error ponerlo en la misma base de datos, lo correcto sería cruzarlo con otra base de datos con el nombre del país, para poder elegir el idioma correcto.

Se puede descargar una base de datos en formato MySQL con los nombres de país en español e inglés aquí:
country_names.sql.zip

 

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

 

 

 

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

Responder a Alan Villaseca Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *