Obtenir, en PHP sans TRACERT [system('traceroute'." ".$IP)], le Pays du visiteur de son site.
C'est fait très simplement et sans trop de pénalisation (hormis ~1s Elapse [CPU + I/O + Flux + Idle]).
Le code de base de la détection de géolocalisation (utilise un fichier CSV à télécharger) :
<?php
$IP_split = preg_split( '/[.]+/',$_SERVER['REMOTE_ADDR']);
$IP_val = (double) (16777216*$IP_split[0] + 65536*$IP_split[1] + 256*$IP_split[2] + $IP_split[3]);
$f_hndl = fopen('http://'.$_SERVER['SERVER_NAME'].'/IP-country.csv','r');
while (($data = fgetcsv($f_hndl,1000,',')) !== FALSE)
if( ($IP_val >= $data[0]) && ($IP_val <= $data[1])) break;
$country_v = $data[2];
fclose($f_hndl);
?>Le résultat est dans $country_v (string).
Le fichier IP-country.csv (4.307 Ko) est à mettre dans le répertoire racine du domaine ou du sous-domaine.
Il est disponible sur le FTP anonyme de Cigiema à ftp://ftp2.cigiema.fr/cigiema/documents/IP-country.csv
(patience pour le téléchargement... Le fichier est LOURD --> 4 Mo)
Ensuite, l'on en fait ce que l'on veut, on peut même le stocker en BDD (avec l'IP et le timestamp
)...
![]()
AHOHNM
NB : Le fichier CSV a été créé par Export de Table BDD triée sur le champ begin_num avec PHP my Admin (en remplaçant ";" par ","), cette Table ayant été précédemment remplie en Import en utilisant un fichier provenant de MaxMind GeoLite Country puis simplifiée (la modification est explicitement autorisée) afin de l'alléger considérablement (les champs begin_ip, end_ip et country ont été supprimés dans IP-country.csv - restent begin_num, end_num et name --> Gain de 50%)
PS : Si le fichier s'ouvre dans une fenêtre, le copier et l'enregistrer sous le nom IP-country.csv !
ATTENTION ! Pas d'extension .mht mais .csv (renommer IP-country_csv.mht en IP-country.csv au besoin) !
PPS : Bien que l'utilisation de cette fonction soit beaucoup plus performante en créant et utilisant une Table en BDD, j'ai privilégié l'utilisation directe du CSV afin de ne pas surcharger une Base de faible capacité qui est déjà bien remplie. Il reste toutefois préférable d'utiliser SQL pour un rendement optimal (consulter la Documentation de MaxMind [en Anglais]).
PPPS : Il est de bon aloi d'ajouter la ligne suivante (avec le lien) dans les pages de sites utilisant ce CSV
--> "This product includes GeoLite data created by MaxMind, available from http://www.maxmind.com/."
Dernière modification par Crazy (31/12/2009 12:36:22)
Hors ligne
Vu et ça marche !
<edit Smeagold> UDLPELM
</edit>
Hors ligne
Et il ne reste plus qu'à modifier le script proposé dans Afficher-nombre-visiteurs-site...
Ainsi que la Table de la BDD qui est utilisée...
Changer :
if ($res['nbre_connect'] == 0) mysql_query('INSERT INTO connect VALUES(\''.$_SERVER['REMOTE_ADDR'].'\', '.time().')');Par :
if ($res['nbre_connect'] == 0) mysql_query('INSERT INTO connect VALUES(\''.$_SERVER['REMOTE_ADDR'].'\', '.time().', \''.$country_v.'\')');Et pour la BDD ajouter le champ correspondant en VARCHAR(50) !
Fastoche, non ? ![]()
![]()
AHOHNM
PS : J'aime bien mettre du SQL dans un Topic de PHP... ![]()
Hors ligne
Il existe la même chose pour les villes...
Mais c'est beaucoup plus lourd : 130 Mo !
--> http://www.maxmind.com/app/geolitecity![]()
Alain AKA Arma
Hors ligne
Salut Crazy,
Je viens de voir passer ce message dans le flux RSS de ton forum que je publie sur le référencement pour les nuls
Très sympa ton code. Je pense que je lui trouverai vite une utilité.
Par contre, il faut savoir que tous les providers ne respectent pas les normes: sur Numéricable, il m'est arrivé à une époque de posséder une IP Suisse ou Belge alors que je suis en région parisienne.
Sans parler des boites étrangères installées en France et dont les connexions passent par un proxy d'entreprise installé dans leur pays d'origine.
Allez, à l'année prochaine ![]()
Hors ligne
C'est exact, de même que (avec ce code et ce CSV édulcoré)...
Les abonnés AOL sont tous géolocalisés "United States".
Mais cela n'est pas vraiment très gênant...
MaxMind met normalement son CSV (différent du mien) à jour le 1er de chaque mois.
Je tâcherai de mettre à disposition une MAJ trimestrielle (~ leur fichier moins trois champs).
Sinon, rien n'empêche de s'affranchir de mon Script Zarbi et d'utiliser leur système directement...![]()
Alain AKA Arma
PS : GeoLite Coutry free version --> Returns US for all AOL users ![]()
PPS : @ Loki --> Je l'utilise pour mes Stats perso... Mais Chut...
![]()
Hors ligne
Voici ce que l'on peut faire en utilisant deux Tables en BDD :
// ------------------------------------------------------------------------------------------------------------------
$decomp = preg_split( '/[.]+/',$_SERVER['REMOTE_ADDR']);
$ipnum = (double) (16777216*$decomp[0] + 65536*$decomp[1] + 256*$decomp[2] + $decomp[3]);
$res = mysql_fetch_array(mysql_query('SELECT * FROM countries WHERE '.$ipnum.' >= begin_num AND '.$ipnum.' <= end_num LIMIT 1'),MYSQL_ASSOC);
$country = $res['country'];
// ------------------------------------------------------------------------------------------------------------------
$res = mysql_fetch_array(mysql_query('SELECT COUNT(*) AS nbre_connect FROM connect WHERE ip=\''.$_SERVER['REMOTE_ADDR'].'\''));
if ($res['nbre_connect'] == 0) mysql_query('INSERT INTO connect VALUES (\''.$_SERVER['REMOTE_ADDR'].'\', '.time().', \''.$lang.'\', \''.$country.'\')');
else mysql_query('UPDATE connect SET timestamp='.time().', lang=\''.$lang.'\' WHERE ip=\''.$_SERVER['REMOTE_ADDR'].'\'');
mysql_query('DELETE FROM connect WHERE timestamp <= '.(time() - (60 * 3)));
$res = mysql_fetch_array(mysql_query('SELECT COUNT(*) AS nbre_connect FROM connect'));
if ($lang == 'fr') echo 'A cet instant : <b>'.$res['nbre_connect'].' visiteur'.(($res['nbre_connect'] > 1) ? 's' : '').'</b> sur ';
else echo 'At this time: <b>'.$res['nbre_connect'].' visitor'.(($res['nbre_connect'] > 1) ? 's' : '').'</b> connected on ';
echo $_SERVER['SERVER_NAME']."\n";
$res1 = mysql_fetch_array(mysql_query('SELECT COUNT(*) AS nbre_FR FROM connect WHERE lang=\'fr\''));
$res2 = mysql_fetch_array(mysql_query('SELECT COUNT(*) AS nbre_EN FROM connect WHERE lang=\'en\''));
echo ' <small>(<b>'.$res1['nbre_FR'].' FR</b> / <b>'.$res2['nbre_EN'].' EN</b>)</small>'."\n";
$res = mysql_query('SELECT COUNT(*) AS nb_by_lang, country, lang FROM connect GROUP BY country, lang ORDER BY country, lang');
while ($result = mysql_fetch_array($res,MYSQL_ASSOC)) $countries[] = $result['country'].' ('.$result['nb_by_lang'].' '.strtoupper($result['lang']).')';
$country_list = implode(', ',$countries);
$country_list = str_replace('United States','United States / AOL',$country_list);
if ($lang == 'fr') echo '<br /><small>Provenant de : '.$country_list.'</small>';
else echo '<br /><small>From: '.$country_list.'</small>';Cet exemple (bilingue) provient de l'Annuaire Cigiema.![]()
Alain AKA Arma
Hors ligne
Merci bien pour ce petit bout de code.
Je cherchais un truc dans le genre pour orienter fonction du pays / langues.
![]()
Hors ligne
Il est possible de faire un peu mieux...
Remplacer :
$res = mysql_query('SELECT COUNT(*) AS nb_by_lang, country, lang FROM connect GROUP BY country, lang ORDER BY country, lang');
while ($result = mysql_fetch_array($res,MYSQL_ASSOC)) $countries[] = $result['country'].' ('.$result['nb_by_lang'].' '.strtoupper($result['lang']).')';
$country_list = implode(', ',$countries);
$country_list = str_replace('United States','United States / AOL',$country_list);Par :
$res = mysql_query('SELECT COUNT(*) AS nb_by_lang, country, lang FROM connect GROUP BY country, lang ORDER BY country, lang');
while ($result = mysql_fetch_array($res,MYSQL_ASSOC))
{
if ($result['lang'] == 'fr' && $result['country'] == 'United States') $result['country'] = str_replace('United States','AOL FR',$result['country']);
$countries[] = $result['country'].' ('.$result['nb_by_lang'].' '.strtoupper($result['lang']).')';
}
sort($countries);
$country_list = implode(', ',$countries);Cela permet de déterminer les AOL dont la langue est le Français, sans les confondre avec les US en Anglais
(Bien sûr les AOL EN restent confondus avec les US mais on ne peut faire mieux en aussi rapide et peu couteux en BDD).![]()
Alain AKA Arma
Hors ligne
Autre version du code ci-dessus :
$res = mysql_query('SELECT COUNT(*) AS nb_by_lang, country, lang FROM connect GROUP BY country, lang ORDER BY country, lang');
while ($result = mysql_fetch_array($res,MYSQL_ASSOC))
{
if ($result['country'] == 'United States') $result['country'] .= ' / AOL';
elseif (!$result['country']) $result['country'] = 'Unknown';
$countries[] = $result['country'].' ('.$result['nb_by_lang'].' '.strtoupper($result['lang']).')';
}
sort($countries);
$country_list = implode(', ',$countries);Cela affine encore les résultats et gère les plages d'IP inconnues ou secrètes (il y en a).![]()
Alain AKA Arma
Hors ligne
L'on peut aussi détecter les Robots des Moteurs de Recherche.
C'est un excellent complément à cette fonction.
--> Détecter les Robots qui visitent un site.
Le code complet qui exécute les deux fonctions y est donné et expliqué.![]()
Alain AKA Arma
Hors ligne
J'avais oublié de donner l'algorithme de détection de la langue...
Détecter la langue d'un visiteur :
<?php
// Created by Crazy (c)2010
$default_lang = 'fr'; // Langue par défaut
// ------------------------------------ INFOS COOKIE ---------------------------------------
$cookie_time = time() + (3600 * 24 * 365); // Validité du cookie : 1 an
$cookie_path = '/';
$cookie_domain = $_SERVER['SERVER_NAME'];
$cookie_secure = FALSE;
// ------------------------------------------------------------------------------------------------
// Existe-t-il un cookie ?
if (isset($_COOKIE["c_lang"])) $lang = $_COOKIE["c_lang"];
// Si pas de Cookie et que PHP connait la langue du Client alors on la force sans vergogne
if ($lang !== 'fr' && $lang !== 'en')
{
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && $_SERVER['HTTP_ACCEPT_LANGUAGE'] != '')
if (stristr($_SERVER['HTTP_ACCEPT_LANGUAGE'],'fr')) $lang = 'fr';
else $lang = 'en';
else $lang = $default_lang;
setcookie('c_lang', $lang, $cookie_time, $cookie_path, $cookie_domain, $cookie_secure); // Cookie pour la prochaine page
}
// ------------------------------------------------------------------------------------------
?>Ce code utilise un Cookie qui permet de se souvenir de la langue choisie par le visiteur.
Il faut aussi autoriser l'utilisateur à choisir sa langue...
C'est un plus non négligeable !![]()
Alain AKA Arma
Hors ligne
Loin de moi de vouloir contester mon maitre mais :
Que fait ton code de plus que la saga GEOIP inclue dans php ?
# geoip_continent_code_by_name() — Lit le code de continent d'une IP
# geoip_country_code_by_name() — Récupère les deux lettres du code pays
# geoip_country_code3_by_name() — Récupère les trois lettres du code pays
# geoip_country_name_by_name() — Récupère le nom complet du pays
Perso je l'ai pas mal utilisé sur buzzinessman avant de passer à ads manager de google, & jamais eu le moindre souci.
Hors ligne
Il n'y a aucun appel à quelque fonction GeoIP dans les codes proposés !
Cela fonctionne totalement différemment et c'est très simplifié donc plutôt rapide.
D'autant que je n'utilise pas la table GeoIP de base mais un ersatz particulièrement allégé.![]()
Alain AKA Arma
Hors ligne
|
© 2006-2010 / A. G.☺ CiGi€M@®, 1997-2010 |
|
Reproduction totale ou partielle strictement interdite Contact : / |