如何使用地理位置获取访问者的位置(即国家/地区)?

Posted

技术标签:

【中文标题】如何使用地理位置获取访问者的位置(即国家/地区)?【英文标题】:How to get visitor's location (i.e. country) using geolocation? 【发布时间】:2010-08-15 22:02:17 【问题描述】:

我正在尝试扩展原生地理定位功能

if(navigator.geolocation) 
    navigator.geolocation.getCurrentPosition(function(position) 
        var latitude = position.coords.latitude;
        var longitude = position.coords.longitude;
    );

以便我可以使用访问者的国家/地区名称(可能返回一个信息数组)。

到目前为止,我能找到的只是显示谷歌地图界面的功能,但实际上没有一个能提供我想要的功能,除了 this library 工作良好 in this example 但由于某种原因在我的电脑。我不知道为什么那里出错了。

不管怎样,你知道我如何简单地返回一个数组,其中包含来自纬度和经度值的国家、城市等信息吗?

【问题讨论】:

$.get("https://api.ipdata.co", function (response) $("#response").html(JSON.stringify(response, null, 4)); , "jsonp"); 见小提琴jsfiddle.net/6wtf0q4g 快速免责声明,我构建了上述服务 ipdata.co,它还具有极强的可扩展性,有 10 个全球端点,每个端点每天能够处理超过 8 亿次调用! @SamuelLiew 我不相信这种情况下的重复是有效的。这个问题专门询问地理位置,而重复询问的是语言环境,这是一个类似但不同的问题(因为语言环境不包括纬度和经度、城市等)。 【参考方案1】:

您可以为此使用我的服务http://ipinfo.io。它将为您提供客户端 IP、主机名、地理位置信息(城市、地区、国家/地区、区号、邮政编码等)和网络所有者。这是一个记录城市和国家/地区的简单示例:

$.get("https://ipinfo.io", function(response) 
    console.log(response.city, response.country);
, "jsonp");

这是一个更详细的 JSFiddle 示例,它还打印出完整的响应信息,因此您可以查看所有可用的详细信息:http://jsfiddle.net/zK5FN/2/

该位置通常不如本地地理位置详细信息准确,但它不需要任何用户许可。

【讨论】:

这对我不起作用,当我请求数据时,我会得到完整的网站作为我的回复。有没有更好的服务可以打电话? 您可以通过将 /json 添加到 url 来强制 json 响应。你提出的要求是什么?它应该会自动检测到你想要 json。 但它不支持带有“https”的站点。太可惜了。 请注意,从定价页面: > 如果您需要每天向我们的 API 发出少于 1,000 个请求并且它是用于非商业用途,或者您只是想测试一下,请免费注册计划。否则,请选择以下付费计划之一。 - ipinfo.io/pricing 你不是在回答技术问题,而是在为你的公司做广告,wtf?每个 SO 问题都可以这样回答。 :“打电话给我们并与我们的顾问交谈”【参考方案2】:

如果您只需要用户所在的国家/地区,则无需定位用户。您可以在任何 IP-to-location 服务(如 maxmind、ipregistry 或 ip2location)中查找他们的 IP 地址。这在大多数情况下都是准确的。

这是一个使用 Ipregistry 的客户端示例(免责声明,我正在为之工作):

fetch('https://api.ipregistry.co/?key=tryout')
    .then(function (response) 
        return response.json();
    )
    .then(function (payload) 
        console.log(payload.location.country.name + ', ' + payload.location.city);
    );

如果你真的需要获取他们的位置,你可以通过该方法获取他们的纬度/经度,然后查询Google's或Yahoo's反向地理编码服务。

【讨论】:

@juanpastas 你没有。你只要ping一个服务,服务就会知道。或者您自己编写服务,但这超出了纯 javascript 范围。 但是要 ping 一个服务,那会在服务器端吗?你知道客户的方法吗? 如果我通过不同国家的代理访问互联网怎么办? ipregistry.co 比其他选择更慷慨。它有一个免费的 100k API 调用层,注册很简单,不需要输入信用卡。 不错的推荐,我试过 ipregistry,信息很简单。【参考方案3】:

您可以使用您的 IP 地址来获取您的“国家”、“城市”、“isp”等... 只需使用其中一个为您提供简单 api 的 Web 服务,例如 http://ip-api.com,它在 http://ip-api.com/json 为您提供 JSON 服务。只需发送一个 Ajax(或 Xhr)请求,然后解析 JSON 以获取您需要的任何数据。

var requestUrl = "http://ip-api.com/json";

$.ajax(
  url: requestUrl,
  type: 'GET',
  success: function(json)
  
    console.log("My country is: " + json.country);
  ,
  error: function(err)
  
    console.log("Request failed, error= " + err);
  
);

【讨论】:

由于 ip-api.com 不支持 https 请求,如果从 https 内容/页面中调用,大多数浏览器将拒绝该请求。另外,根据他们的网站,> 您可以免费将 ip-api.com 用于非商业用途。未经事先批准,我们不允许用于商业用途。 ip-api 只是提供 IP 定位服务的不同服务之一。该问题不涉及https 协议。如果您确实使用https 网站,我相信您可以实现相同的逻辑,只是使用不同的 IP-Location 服务。【参考方案4】:

请参阅 ipdata.co 我构建的一项服务,该服务速度快且性能可靠,这要归功于拥有 10 个全局端点,每个端点能够每秒处理超过 10,000 个请求!

此答案使用非常有限的“测试”API 密钥,仅用于测试几个调用。 Signup 获取您自己的免费 API 密钥,每天最多可收到 1500 个开发请求。

这个 sn-p 将返回您的 当前 ip 的详细信息。要查找其他 ip 地址,只需将 ip 附加到 https://api.ipdata.co?api-key=test url 例如。

https://api.ipdata.co/1.1.1.1?api-key=test

API 还提供了一个is_eu 字段,指示用户是否在欧盟国家/地区。

$.get("https://api.ipdata.co?api-key=test", function (response) 
    $("#response").html(JSON.stringify(response, null, 4));
, "jsonp");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre id="response"></pre>

这是小提琴; https://jsfiddle.net/ipdata/6wtf0q4g/922/

我还写了this 对 8 个最佳 IP 地理定位 API 的详细分析。

【讨论】:

那是错误的。该服务每月最多可免费处理 45,000 个请求。最小的计划是 10 美元,并返回提到的错误以防止滥用。请注意,它还附有一封电子邮件,警告您已用尽所有请求。 我的评论不假 您的评论本质上是虚假和误导性的。【参考方案5】:

您无法通过 ip 获取城市位置。 在这里您可以使用 jquery 获取国家/地区:

$.get("http://ip-api.com/json", function(response) 
console.log(response.country);, "jsonp");

【讨论】:

其他人在你之前给出了这个答案 + 他们补充说如果你的服务器在 https 服务器上运行,这将不起作用。网络浏览器将阻止它,因为它是不安全的调用。【参考方案6】:

ws.geonames.org 提供了一个非常易于使用的服务。这是一个示例网址:

http://ws.geonames.org/countryCode?lat=43.7534932&amp;lng=28.5743187&amp;type=JSON

这是我添加到您的代码中的一些 (jQuery) 代码:

if (navigator.geolocation) 
    navigator.geolocation.getCurrentPosition(function(position) 
        $.getJSON('http://ws.geonames.org/countryCode', 
            lat: position.coords.latitude,
            lng: position.coords.longitude,
            type: 'JSON'
        , function(result) 
            alert('Country: ' + result.countryName + '\n' + 'Code: ' + result.countryCode);
        );
    );
​

Try it on jsfiddle.net ...

【讨论】:

geolocation 不再通过 http 工作,并且该服务在 https 上不可用 他们有 https 端点:secure.geonames.orgforum.geonames.org/gforum/posts/list/34294.page【参考方案7】:

Webtechriser (click here to read the article)(称为wipmania)提供免费且易于使用的服务。这是一项 JSONP 服务,需要使用 HTML 进行简单的 javascript 编码。它也可以在 JQuery 中使用。我稍微修改了代码以更改输出格式,这就是我使用并发现可以正常工作的代码:(这是我的 HTML 页面的代码)

<html>
    <body>
        <p id="loc"></p>


        <script type="text/javascript">
            var a = document.getElementById("loc");

  	            function jsonpCallback(data)  
	            a.innerHTML = "Latitude: " + data.latitude + 
                              "<br/>Longitude: " + data.longitude + 
                              "<br/>Country: " + data.address.country; 
 	            
        </script>
        <script src="http://api.wipmania.com/jsonp?callback=jsonpCallback"
                     type="text/javascript"></script>


    </body>
</html>

请注意:HTML 5 geolocation API(您编写的代码)。因此,隐私受到损害。因此,您应该对这项服务进行司法使用。

【讨论】:

我看到 0 代表 LatitudeLongitudeUnknown 代表 Country 堆栈溢出但当我在 HTML 网页中使用它时它起作用了。 我刚刚在我的一个非常古老的网站上使用了它,我很高兴地说它可以工作:e-artlab.com/about-you - 虽然不是在所有平台或浏览器上(在我合作伙伴的 Win/Edge 和Win/Chrome 访问被阻止,尽管我的 Mac/Chrome 很好)? 使用 HTTP 的不安全连接。【参考方案8】:

我想在不使用任何外部 API 的情况下为少数国家/地区本地化客户端定价,因此我使用本地 Date 对象来获取国家/地区 new Date()).toString().split('(')[1].split(" ")[0]

    document.write((new Date()).toString().split('(')[1].split(" ")[0])

基本上这个小代码 sn-p 从 Date 对象中提取第一个单词。要检查不同的时区,您可以更改本地机器的时间。

就我而言,我们的服务只包括三个国家,所以我可以使用以下代码获取位置。

const countries = ["India", "Australia", "Singapore"]
const countryTimeZoneCodes = 
  "IND": 0,
  "IST": 0,
  "AUS": 1,
  "AES": 1,
  "ACS": 1,
  "AWS": 1,
  "SGT": 2,
  "SIN": 2,
  "SST": 2
 // Probable three characters from timezone part of Date object
let index = 0
try 
  const codeToCheck = (new Date()).toString().split('(')[1].split(" ")[0].toUpperCase().substring(0, 3)
  index = countryTimeZoneCodes[codeToCheck]

 catch (e) 

  document.write(e)
  index = 0


document.write(countries[index])

这只是为了改善用户体验。这不是检测位置的完整证明解决方案。作为未正确检测的后备方案,我在菜单栏中添加了一个下拉菜单以选择国家/地区。

【讨论】:

这只是为了改善用户体验,为了让新用户从下拉列表中选择国家,我们可以为少数提供自动选择。对于您的东部地区,您要么来自美国,要么来自加拿大。参考en.wikipedia.org/wiki/Eastern_Time_Zone 这对我来说不起作用。【参考方案9】:

对于寻找功能齐全的地理定位实用程序的开发人员,您可以查看geolocator.js(我是作者)。

下面的示例将首先尝试 HTML5 Geolocation API 来获取准确的坐标。如果失败或被拒绝,它将回退到 Geo-IP 查找。获取坐标后,它将坐标反向地理编码为地址。

var options = 
    enableHighAccuracy: true,
    timeout: 6000,
    maximumAge: 0,
    desiredAccuracy: 30,
    fallbackToIP: true, // if HTML5 geolocation fails or rejected
    addressLookup: true, // get detailed address information
    timezone: true, 
    map: "my-map" // this will even create a map for you
;

geolocator.locate(options, function (err, location) 
    console.log(err || location);
);

它支持地理位置(通过 HTML5 或 IP 查找)、地理编码、地址查找(反向地理编码)、距离和持续时间、时区信息等等...

【讨论】:

就像一个魅力!但是,您需要在 google 上启用多个 API 才能使其正常工作。必须启用 Google Maps Time Zone APIGoogle Maps Geocoding API。将其添加到文档中可以为用户节省更多时间:)。谢谢! Geolocator 在这里有详细的文档:onury.github.io/geolocator/?api=geolocator 谢谢。【参考方案10】:

您可以在不依赖 IP 服务的情况下本机执行此操作。您可以像这样获取用户的时区:

Intl.DateTimeFormat().resolvedOptions().timeZone

然后从该值中提取国家。 Here 是 CodePen 上的一个工作示例。

【讨论】:

这是一种非常有趣的方法。我觉得它一定有什么问题,但我想不出原因。我的第一个想法是跨越国家/地区的时区,但您似乎通过包含链接的时区来涵盖这一点。理论上,即使用户使用 ***,这仍然会获得正确的国家/地区。唯一的缺点是必须在时区更改时更新您的时区列表。 谢谢!是的,我不确定这在生产环境中有多可靠,但对于大多数情况来说似乎已经足够好了。我承认我没有在大型项目中测试过这个解决方案,因此我建议这样做时要小心。我认为也可以实现一些逻辑来处理时区的细微差别。 我在英国试过了,效果很好!【参考方案11】:

您可以使用ip-api.io 获取访问者的位置。它支持 IPv6。

作为奖励,它允许检查 ip 地址是否是 tor 节点、公共代理或垃圾邮件发送者。

JavaScript 代码:

function getIPDetails() 
    var ipAddress = document.getElementById("txtIP").value;

    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function () 
        if (this.readyState == 4 && this.status == 200) 
            console.log(JSON.parse(xhttp.responseText));
        
    ;
    xhttp.open("GET", "http://ip-api.io/json/" + ipAddress, true);
    xhttp.send();


<input type="text" id="txtIP" placeholder="Enter the ip address" />
<button onclick="getIPDetails()">Get IP Details</button>

jQuery 代码:

$(document).ready(function () 
        $('#btnGetIpDetail').click(function () 
            if ($('#txtIP').val() == '') 
                alert('IP address is reqired');
                return false;
            
            $.getJSON("http://ip-api.io/json/" + $('#txtIP').val(),
                 function (result) 
                     alert('Country Name: ' + result.country_name)
                     console.log(result);
                 );
        );
    );

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<div>
    <input type="text" id="txtIP" />
    <button id="btnGetIpDetail">Get Location of IP</button>
</div>

【讨论】:

最好在直接的 JavaScript 中也包含一个示例,任何使用 JQuery 的人 :-) 感谢@DaveEveritt!我也添加了 JavaScript 代码。 其他人在您之前给出了这个答案 + 它不适用于 HTTPS 网站,因为您的网络浏览器不允许调用 http://...,因为它们不安全。【参考方案12】:

如果您不想使用 api 并且只有国家/地区就足够了,您可以使用 topojson 和 worldatlas。

import  feature  from "https://cdn.skypack.dev/topojson@3.0.2";
import  geoContains, geoCentroid, geoDistance  from "https://cdn.skypack.dev/d3@7.0.0";

async function success(position) 
    const topology = await fetch("https://cdn.jsdelivr.net/npm/world-atlas@2/countries-50m.json").then(response => response.json());
    const geojson = feature(topology, topology.objects.countries);
    
    const 
        longitude,
        latitude,
     = position.coords;
    
    const location = geojson.features
        .filter(d => geoContains(d, [longitude, latitude]))
        .shift();
    
    if (location) 
        document.querySelector('#location').innerHTML = `You are in <u>$location.properties.name</u>`;
    
    
    if (!location) 
        const closestCountry = geojson.features
            // You could improve the distance calculation so that you get a more accurate result
            .map(d => ( ...d, distance: geoDistance(geoCentroid(d), [longitude, latitude]) ))
            .sort((a, b) => a.distance - b.distance)
            .splice(0, 5);
        
        if (closestCountry.length > 0) 
            const possibleLocations = closestCountry.map(d => d.properties.name);
            const suggestLoctions = `$possibleLocations.slice(0, -1).join(', ') or $possibleLocations.slice(-1)`;
            
            document.querySelector('#location').innerHTML = `It's not clear where you are!<section>Looks like you are in $suggestLoctions</section>`;
        
        
        if (closestCountry.length === 0) 
            error();
                
    


function error() 
    document.querySelector('#location').innerHTML = 'Sorry, I could not locate you';
;

navigator.geolocation.getCurrentPosition(success, error);

此代码获取经度和纬度并检查该点是否包含在 geojson 的一个特征(空间有界实体)中。我还创建了一个有效的example。

【讨论】:

【参考方案13】:

您可以通过https://apiip.net/ API 获得大量有关 IP 的信息。如果需要,它们也会提供 XML 响应,并且它支持 IPv6。

只需发送简单的 GET 调用:

https://apiip.net/api/check?ip=67.250.186.196&accessKey=your_api_key

回复:


  "ip": "67.250.186.196",
  "continentCode": "NA",
  "continentName": "North America",
  "countryCode": "US",
  "countryName": "United States",
  "countryNameNative": "United States",
  "city": "New York",
  "postalCode": "10001",
  "latitude": 40.8271,
  "longitude": -73.9359,
  "capital": "Washington D.C.",
  "phoneCode": "1",
  "countryFlagEmoj": "??",
  "countryFlagEmojUnicode": "U+1F1FA U+1F1F8",
  "isEu": false,
  "languages": 
    "en": 
      "code": "en",
      "name": "English",
      "native": "English"
    
  ,
  "currency": 
    "code": "USD",
    "name": "US Dollar",
    "symbol": "$",
    "number": "840",
    "rates": 
      "EURUSD": 1.11
     
  ,
  "timeZone": 
    "id": "America/New_York",
    "currentTime": "10/26/2021, 2:54:10 PM",
    "code": "EDT",
    "timeZoneName": "EDT",
    "utcOffset": -14400
  ,
  "connection": 
    "asn": 12271,
    "isp": "Charter Communications Inc"
  ,
  "security": 
    "isPublicProxy": false,
    "isResidentialProxy": false,
    "isTorExitNode": false,
    "network": "67.250.176.0/20"
  

【讨论】:

以上是关于如何使用地理位置获取访问者的位置(即国家/地区)?的主要内容,如果未能解决你的问题,请参考以下文章

在 Woocommerce 3 中获取地理位置的国家和地区

当用户在 Google 地图中拒绝位置访问时,如何向用户显示当前国家/地区?

如何从 Sitecore 地理位置信息中获取用户所在的国家/地区?

如何使用地理位置而不是完整的国家和地区名称获取国家和地区代码

如何使用地名服务 api 而不是 html5 位置对象的东西获取国家/地区代码信息

如何获取某个国家/地区的位置点取决于 Android 手机配置