Как определить страну посетителя веб-сайта (в частности, США или нет)?

Мне нужно показать разные ссылки на мой сайт для посетителей из США и других стран. Это только для удобства, поэтому я не ищу сверхвысокой степени точности, а безопасность или спуфинг не беспокоят.

Я знаю, что существуют службы геотаргетинга и списки, но это кажется излишним, поскольку мне нужно только определить (приблизительно), находится ли человек в США или нет.

Я думал об использовании JavaScript для получения часового пояса пользователя, но, похоже, это дает только смещение, поэтому пользователи в Канаде, Мексике и Южной Америке будут иметь такое же значение, как и люди в США.

Есть ли какие-либо другие биты информации, доступные либо в JavaScript, либо в PHP, кроме захвата IP-адреса и выполнения поиска, чтобы определить это?


person David Smith    schedule 28.01.2010    source источник
comment
Я думаю, что решение на базе IP — единственный надежный способ. На все остальное могут повлиять настройки пользователя. Решения на базе IP тоже могут быть перекошены, но это сложнее.   -  person FrustratedWithFormsDesigner    schedule 28.01.2010
comment
@FrustratedWithFormsDesigner. Обратите внимание, что он сказал: «Это только для удобства, поэтому я не ищу сверхвысокой степени точности, а безопасность или спуфинг не беспокоят». поэтому решение на основе IP может быть излишним для того, что ему нужно. Он также сказал: ... если не считать IP-адреса и поиска, чтобы определить это?   -  person Taylor Leese    schedule 28.01.2010


Ответы (8)


Есть несколько бесплатных сервисов, которые позволяют выполнять геолокацию на основе страны и IP-адреса со стороны клиента.

Я использовал бесплатный сервис JSONP wipmania, он очень прост в использовании:

<script type="text/javascript">
  // plain JavaScript example
  function jsonpCallback(data) { 
    alert('Latitude: ' + data.latitude + 
          '\nLongitude: ' + data.longitude + 
          '\nCountry: ' + data.address.country); 
  }
</script>
<script src="http://api.wipmania.com/jsonp?callback=jsonpCallback"
        type="text/javascript"></script>

Или, если вы используете фреймворк, поддерживающий JSONP, например jQuery, вы можете:

// jQuery example
$.getJSON('http://api.wipmania.com/jsonp?callback=?', function (data) { 
  alert('Latitude: ' + data.latitude + 
        '\nLongitude: ' + data.longitude + 
        '\nCountry: ' + data.address.country); 
});

Проверьте приведенный выше фрагмент, работающий здесь.

person Christian C. Salvadó    schedule 28.01.2010
comment
Как можно изменить ваш код, чтобы вместо диалогового окна предупреждения было перенаправление URL-адреса, которое перенаправляет посетителя из США на адрес .COM и позволяет посетителю из Канады проходить нормально? (Для версии .CA веб-сайта с дочерним сайтом версии .COM) - person ; 16.02.2011
comment
оператор switch в событии onload, проверьте страну, возвращаемую функцией json, затем вызовите Server.Transfer или аналогичный. - person Anonymous Type; 16.02.2011
comment
Большое спасибо за код и ссылку, она рабочая и классная :) - person Mujahid; 13.06.2011
comment
Это не поддерживает https :( - person Brian Leishman; 08.06.2017
comment
Обычно я использую geo-ip.net/locate?query=stackoverflow.com&format =json поддерживает ssl-соединения - person Gerard; 06.07.2018

Лучшим индикатором, вероятно, является заголовок HTTP Accept-Language. В HTTP-запросе это будет выглядеть примерно так:

GET / HTTP/1.1
Accept: */*
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; MDDC; OfficeLiveConnector.1.4; OfficeLivePatch.0.0; .NET CLR 3.0.30729)
Accept-Encoding: gzip, deflate
Host: www.google.com
Connection: Keep-Alive

Вы должны иметь возможность получить это в PHP, используя следующее:

<?php
echo $_SERVER['HTTP_ACCEPT_LANGUAGE'];
?>
person Taylor Leese    schedule 28.01.2010
comment
Что определяет Accept-Language? Задается ли он операционной системой или пользователь может на него повлиять? Если мой коллега настроит свой ноутбук на использование китайского языка, каким будет Accept-Language? Кроме того, как насчет en-gb? - person FrustratedWithFormsDesigner; 28.01.2010
comment
Это определяется настройками браузера пользователя. - person Taylor Leese; 28.01.2010
comment
@FrustratedWithFormsDesigner: язык принятия определяется браузером. Пользователь может манипулировать им, если захочет. Например, в firefox перейдите в «Настройки» > «Содержимое» > «Языки». - person Mark; 28.01.2010
comment
Он устанавливается браузером, обычно инициализируемым ОС. Таким образом, пока я нахожусь в Канаде, я могу казаться, что нахожусь в США, Великобритании или где-то еще, установив язык, как это обычно называется в браузерах, таких как IE и FF. - person JB King; 28.01.2010
comment
@all: это говорит о том, что решение на основе IP гораздо надежнее. - person FrustratedWithFormsDesigner; 28.01.2010
comment
Это не идеальное решение. Вы бы сделали обоснованное предположение, основанное на заголовке. Если этого недостаточно, вам придется изучить службы определения местоположения на основе IP. Обратите внимание, ОП сказал: «Это только для удобства, поэтому я не ищу сверхвысокой степени точности, и безопасность или спуфинг не вызывают беспокойства». - person Taylor Leese; 28.01.2010
comment
@FrustratedWithFormsDesigner: Абсолютно. Тем не менее, en-us — довольно хороший указатель. - person Pekka; 28.01.2010
comment
Ребята, особенно Тейлор, похоже, это то решение, которое мне нужно. Как я уже сказал, меня не волнует, что пользователь притворяется, что он из другого места, так как он, безусловно, может это сделать. Я собираюсь дать ему некоторое время, чтобы посмотреть, есть ли у меня другие хорошие варианты, но спасибо! - person David Smith; 28.01.2010
comment
@BigDave: Теперь мне любопытно: почему ваши результаты могут быть такими приблизительными? - person FrustratedWithFormsDesigner; 28.01.2010
comment
Учитывая, насколько легко было бы реализовать ответ CMS, я не уверен, почему предпочтительнее использовать заголовок HTTP. Существуют бесплатные библиотеки геолокации, так что это определенно путь. Они достаточно точны для западных стран. - person Anonymous Type; 19.08.2010

Я бы сказал, что геотаргетинг — единственный метод, который хотя бы отдаленно надежен. Но бывают и случаи, когда это совсем не помогает. Я продолжаю заходить на сайты, которые думают, что я нахожусь во Франции, потому что там находится магистраль моей компании, и весь интернет-трафик проходит через нее.

Заголовка HTTP Accept недостаточно для определения локали пользователя. Он только сообщает вам, что пользователь выбрал в качестве своего языка, что может не иметь никакого отношения к тому, где он находится. Подробнее об этом здесь.

person Farinha    schedule 28.01.2010

В зависимости от того, какие страны вы хотите различать, часовые пояса могут быть очень простым способом добиться этого — и я предполагаю, что это довольно надежно, поскольку у большинства людей часы на их компьютерах установлены правильно. (Хотя, конечно, есть много стран, которые вы не сможете различить с помощью этой техники).

Вот действительно простой пример того, как это сделать:

http://unmissabletokyo.com/country-detector

person Mike    schedule 07.07.2010

Wipmania.com и PHP

<?php
$site_name = "www.your-site-name.com";

function getUserCountry() {
    $fp = fsockopen("api.wipmania.com", 80, $errno, $errstr, 5);
    if (!$fp) {
        // API is currently down, return as "Unknown" :(
        return "XX";
    } else {
        $out = "GET /".$_SERVER['REMOTE_ADDR']."?".$site_name." HTTP/1.1\r\n";
        $out .= "Host: api.wipmania.com\r\n";
        $out .= "Typ: php\r\n";
        $out .= "Ver: 1.0\r\n";
        $out .= "Connection: Close\r\n\r\n";
        fwrite($fp, $out);
        while (!feof($fp)) {
            $country = fgets($fp, 3);
        }
        fclose($fp);
        return $country;
    }
}
?>
person Slot Gamer    schedule 23.09.2013

@ростислав

или используя cURL:

public function __construct($site_name) {
    // create a new cURL resource
    $ch = curl_init();

    // set URL and other appropriate options
    curl_setopt($ch, CURLOPT_POST, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type: text/xml"));
    curl_setopt($ch, CURLOPT_URL, "http://api.wipmania.com".$_SERVER['REMOTE_ADDR']."?".$site_name);
    curl_setopt($ch, CURLOPT_HEADER, 0);

    // grab URL and pass it to the browser
    $response = curl_exec($ch);
    $info = curl_getinfo($ch,CURLINFO_HTTP_CODE);

    if (($response === false) || ($info !== 200)) {
        throw new Exception('HTTP Error calling Wipmania API - HTTP Status: ' . $info . ' - cURL Erorr: ' . curl_error($ch));
    } elseif (curl_errno($ch) > 0) {
        throw new Exception('HTTP Error calling Wipmania API - cURL Error: ' . curl_error($ch));
    }

    $this->country = $response;

    // close cURL resource, and free up system resources
    curl_close($ch);
}
person TD_Nijboer    schedule 23.04.2014

Просто мы можем использовать Hostip API

<?php $country_code = file_get_contents("http://api.hostip.info/country.php"); <br/>if($country_code == "US"){ echo "You Are USA"; } <br/>else{ echo "You Are Not USA";} ?>

Все коды стран находятся здесь. 1_альфа-2

person sameeuor    schedule 07.01.2015
comment
это серверная часть? так он проверяет местоположение сервера вместо клиента? - person user782104; 16.07.2015

Мое решение, простое и маленькое, в этом примере я тестирую регион Канады на языке fr-CA or en-CA.

if( preg_match( "/^[a-z]{2}\-(ca)/i", $_SERVER[ "HTTP_ACCEPT_LANGUAGE" ] ) ){

   $region = "Canada";

}
person Leonardo Ciaccio    schedule 18.10.2016