前端页面获取访问者的IP地址、经纬度和地理位置
本文主要通过高德地图API进行一系列的分析。提供具体的讲解和源码。
获取的经纬度和地理位置精确度并不高,仅供参考,
请勿非法使用,本人概不负责。
前期准备
注册成为开发者,获取Key
高德开发平台:https://console.amap.com/dev/key/app
注册用户
填写相关信息成为开发者
创建key
需要先创建应用
然后点击添加
创建完成后,就能获取到key了
IP定位和逆地理编码API文档
2022/07/22 发现v5已经改v3了,注意适配 https://restapi.amap.com/v3/ip?ip=114.247.50.2&output=xml&key=<用户的key>
更多详见
https://lbs.amap.com/api/webservice/guide/api/ipconfig/
有个key之后就可以调用到你的php网页了 比如php代买
<?php
//设置IP地址52无敌兔福利网提供代码
$ip = "192.168.1.1";
//设置高德地图应用KEY
$key = "your amap key";
//请求高德地图API接口返回地理位置信息1号优惠 · 51福利网www.51yhyh.com提供
$url = "https://restapi.amap.com/v3/ip?key={$key}&ip={$ip}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
curl_close($ch);
//将返回结果转换为JSON格式
$data = json_decode($res, true);
//输出地理位置信息
if($data['status'] == 1 && $data['province'] != ""){
echo "省份: ".$data['province']."<br>";
echo "城市: ".$data['city']."<br>";
}else{
echo "无法获取您的地理位置信息";
}
?>
如果您使用 CDN,那么您获取到的用户 IP 地址可能不是真实的用户 IP 地址,而是 CDN 的 IP 地址。
为了获取真实的用户 IP 地址,您需要当前服务器支持 HTTP_X_FORWARDED_FOR 头,它将包含用户的原始 IP 地址,例如:
<?php
$ip = '';
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ips[count($ips) - 1]);
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
// 输出用户真实 IP 地址
echo "用户真实 IP 地址:".$ip;
// 请求高德地图 API 接口返回地理位置信息1号优惠 · 51福利网www.51yhyh.com提
$key = "your amap key";
$url = "https://restapi.amap.com/v3/ip?key={$key}&ip={$ip}";
$response = file_get_contents($url);
// 输出地理位置信息1号优惠 · 51福利网www.51yhyh.com提
$data = json_decode($response, true);
if($data['status'] == 1 && $data['province'] != ""){
echo "省份: ".$data['province']."<br>";
echo "城市: ".$data['city']."<br>";
}else{
echo "无法获取您的地理位置信息";
}
?>
请注意,使用 HTTP_X_FORWARDED_FOR 头来获取真实的用户 IP 地址可能会有一些安全风险,具体问题可以查阅相关资料。
同时,需要注意如果您的服务器在境外,则可能无法正确获取中国大陆地区用户的 IP 地址。
更多要求比如:
根据你的要求取用把,亲测暂时可用
把获取到的地位位置加入session保存
<?php
session_start();
$ip = '';
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ips[count($ips) - 1]);
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
// 输出用户真实 IP 地址
echo "用户真实 IP 地址:".$ip;
$amap_key = 'your amap key';
$response = file_get_contents("https://restapi.amap.com/v3/ip?ip={$ip}&output=json&key={$amap_key}");
$data = json_decode($response, true);
if($data['status'] == 1 && $data['province'] != ""){
$province = $data['province'];
$city = $data['city'];
$_SESSION['province'] = $province;
$_SESSION['city'] = $city;
echo "省份: ".$province."<br>";
echo "城市: ".$city."<br>";
}else{
echo "无法获取您的地理位置信息";
}
?>
这里通过 session_start()
函数启动了一个会话,并将获取到的省份和城市信息存储到了 $_SESSION
中,您可以在后续页面中读取这些 session 变量值来进行业务逻辑处理
上面代码总结一下:
使用cdn后获取真实ip,用ip调用高德地图key获取地理位置,并将地理位置存入session可供其他网页调用,每个ip地址只查询一次,
session_start();
$ip = '';
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ips[count($ips) - 1]);
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
// 判断是否已经调用过高德地图1号优惠 · 51福利网www.51yhyh.com提
if (isset($_SESSION['amap']) && $_SESSION['amap']['ip'] == $ip) {
$province = $_SESSION['amap']['province'];
$city = $_SESSION['amap']['city'];
$userdizhi = $province . ' ' . $city;
echo "您的位置是: " . $userdizhi;
} else {
$amap_key = 'your amap key';
$response = file_get_contents("https://restapi.amap.com/v3/ip?ip={$ip}&output=json&key={$amap_key}");
$data = json_decode($response, true);
if($data['status'] == 1 && $data['province'] != ""){
$province = $data['province'];
$city = $data['city'];
$_SESSION['amap'] = array(
'ip' => $ip,
'province' => $province,
'city' => $city
);
$userdizhi = $province . ' ' . $city;
echo "您的位置是: " . $userdizhi;
} else {
echo "无法获取您的地理位置信息";
}
}
增加以下功能:1.将未成功获取地理位置或者地理位置Array的都设为地址未知。2。将未成功获取地理未知和成功获取地理未知的都存入不同的本地文件。3.再调用高德地图API之前先调用本地文件获取地理位置,本地未获取成功的再调用高德地图api。4.地理位置未知的全部跳转到1.html
session_start();
$unknown_address_file = 'unknown_address.txt';
$success_address_file = 'success_address.txt';
$fail_address_file = 'fail_address.txt';
$ip = '';
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$ip = trim($ips[count($ips) - 1]);
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
$address = null;
// 读取本地文件,获取地理位置
if (file_exists($success_address_file)) {
$addresses = json_decode(file_get_contents($success_address_file), true);
if (isset($addresses[$ip])) {
$address = $addresses[$ip];
}
}
// 如果之前没有获取过地址,尝试调用高德地图API
if ($address === null) {
$amap_key = 'your amap key';
$response = file_get_contents("https://restapi.amap.com/v3/ip?ip={$ip}&output=json&key={$amap_key}");
$data = json_decode($response, true);
if($data['status'] == 1 && $data['province'] != ""){
$province = $data['province'];
$city = $data['city'];
$address = array(
'province' => $province,
'city' => $city
);
// 将地址保存到本地文件
$addresses = array();
if (file_exists($success_address_file)) {
$addresses = json_decode(file_get_contents($success_address_file), true);
}
$addresses[$ip] = $address;
file_put_contents($success_address_file, json_encode($addresses));
} else {
// 将地址保存到本地文件
$addresses = array();
if (file_exists($fail_address_file)) {
$addresses = json_decode(file_get_contents($fail_address_file), true);
}
$addresses[$ip] = array();
file_put_contents($fail_address_file, json_encode($addresses));
}
}
if (empty($address)) {
// 将地址保存到本地文件
$addresses = array();
if (file_exists($unknown_address_file)) {
$addresses = json_decode(file_get_contents($unknown_address_file), true);
}
$addresses[$ip] = array();
file_put_contents($unknown_address_file, json_encode($addresses));
header('Location: 1.html');
exit;
}
$province = $address['province'];
$city = $address['city'];
$userdizhi = $province . ' ' . $city;
echo "您的位置是: " . $userdizhi;
首先,我增加了三个文件路径常量 $unknown_address_file
、$success_address_file
和 $fail_address_file
,分别代表保存未知地址、成功获取地址和获取失败地址的文件路径。
其次,我删除了之前的 if/else
逻辑,改为将地址设为 null
,然后在读取本地文件获取地址和调用高德地图API获取地址两个步骤中进行判断。如果从本地文件中获取到了地址,则直接使用,否则尝试调用高德地图API获取地址。
最后,如果获取到的地址是空的,则将这个 IP 记录在 $unknown_address_file
文件中,并通过 header
函数跳转至 1.html
页面。
我是一个php站点,把这个代码放到哪里最合适,用其他页面直接调用可以吗
这个代码可以放到你的 PHP 站点中的任何页面中,只需要将功能实现的代码嵌入到你现有页面的逻辑中即可。
但最好是放在开头,在其他代码执行前,这样可以确保在该页面内的任何代码都可以使用现有的地址信息。
如果在其他页面需要使用这个获取地址的功能,则可以将这段代码写成一个单独的 PHP 文件,然后使用 include
或 require
函数引入到需要获取地址的页面中即可。