今天周日,闲下来突然想给自己的博客加个访客地图,目的是想要大概知道访客来源的地区。这里选用了百度地图开放平台的功能——点聚合。
由于之前没有做访客的ip记录,所以需要新增记录功能(这里不详细写过程),一般来说打开页面需要授权定位的都比较反感,所以我采用不太准确的方式:IP转经纬度。
步骤:
①在百度地图控制台新建应用——javascriptApi应用;
②在获取应用的ak,为了防止被恶意使用,一定要设置好白名单;

③在自己的博客网站后台记录访客的IP地址,顺便用百度的ip转经纬度接口把经纬度转换好存储起来。
2020-08-16 14:47:07|ios|119.39.248.35 2020-08-16 14:47:33|ios|113.218.4.224 2020-08-16 14:47:45|ios|117.136.79.220 2020-08-16 14:49:00|ios|113.242.192.251 2020-08-16 14:49:35|ios|124.229.77.235
查询记录并在web端展示效果。

php简单代码:
<?php
class Baidu_map
{
const BAIDU_MAP_AK = 'xxxxxxx';
public static function get_ip()
{
static $ip = '';
$ip = $_SERVER['REMOTE_ADDR'];
if (isset($_SERVER['HTTP_CDN_SRC_IP'])) {
$ip = $_SERVER['HTTP_CDN_SRC_IP'];
} elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {
foreach ($matches[0] AS $xip) {
if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {
$ip = $xip;
break;
}
}
}
return $ip;
}
public static function get_latlng($ip = '')
{
$get_ip = $ip ? $ip : self::get_ip();
$data = [
'ip' => $get_ip,
'ak' => self::BAIDU_MAP_AK,
'coor' => 'bd09ll'
];
$header = ['content-type:text/html;charset=utf-8'];
$res = self::http_get('http://api.map.baidu.com/location/ip', $data, $header);
if (!empty($res['status'])) {
return ['code' => -1, 'msg' => '转换失败', 'res' => $res];
}
return ['code' => 0, 'msg' => 'ok', 'point' => $res['content']['point'], 'res' => $res];
}
public static function http_get($url, $data = [], $headers = [])
{
if (!empty($data)) {
if (stripos($url, '?') === false) {
$url = $url . '?' . http_build_query($data);
} else {
$url = $url . '&' . http_build_query($data);
}
}
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($headers)) {
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
}
$response = curl_exec($curl);
$result = json_decode($response, true);
$error = curl_error($curl);
return $error ? $error : $result;
}
public static function test()
{
$ips = [];
$data = [];
$log = file_get_contents(__DIR__ . '/log1.txt');
$arr = explode(PHP_EOL, $log);
foreach ($arr as $item) {
$ips[] = explode('|', $item)[2];
}
$ips = array_unique($ips);
$has = @file_get_contents(__DIR__.'/check.json');
if (!empty($has)){
$hasData = json_decode($has,true);
$hasIps = array_column($hasData,'ip');
if (!empty($hasIps)){
$ips = array_filter(array_diff($ips,$hasIps));//找到不在已经获取过的地址
}
foreach ($hasData as $value){
$data[] = [
$value['lng'],
$value['lat']
];
}
}
$db = !empty($hasData)?$hasData: [];
if (!empty($ips)){
foreach ($ips as $ip) {
$lnglat = self::get_latlng($ip);
if ($lnglat['code']==0){
$data[] = [
$lnglat['point']['x'],
$lnglat['point']['y']
];
$db[] = ['ip'=>$ip,'lat'=>$lnglat['point']['y'],'lng'=>$lnglat['point']['x']];
}
}
file_put_contents(__DIR__.'/check.json',json_encode($db,JSON_UNESCAPED_UNICODE));
}
return $data;
}
}html :
<?php
require __DIR__.'/map.php';
$data = Baidu_map::test();
?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
body, html {width: 100%;height: 100%;margin:0;font-family:"微软雅黑";}
#allmap{width:100%;height:100%;}
p{margin-left:5px; font-size:14px;}
</style>
<script type="text/javascript" src="http://api.map.baidu.com/getscript?v=2.0&ak=自己的ak&services=&t=20200327103013"></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay_min.js"></script>
<script type="text/javascript" src="http://api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer_min.js"></script>
<title>点聚合</title>
</head>
<body>
<div id="allmap"></div>
<p>缩放地图,查看点聚合效果</p>
</body>
</html>
<script type="text/javascript">
// 百度地图API功能
var map = new BMap.Map("allmap");
map.centerAndZoom(new BMap.Point(112.0,29.0), 5);
map.enableScrollWheelZoom();
var MAX = '<?php echo count($data)?>';
var data = <?php echo json_encode($data)?>;
var markers = [];
var pt = null;
console.log(data)
var len = data.length
for(var i = 0; i < len; i++) {
pt = new BMap.Point(data[i][0],data[i][1]);
markers.push(new BMap.Marker(pt));
}
/*var i = 0;
for (; i < MAX; i++) {
pt = new BMap.Point(112,34);
// pt = new BMap.Point(Math.random() * 40 + 85, Math.random() * 30 + 21);
markers.push(new BMap.Marker(pt));
}*/
//最简单的用法,生成一个marker数组,然后调用markerClusterer类即可。
var markerClusterer = new BMapLib.MarkerClusterer(map, {markers:markers});
</script>用到的文件在附件中:
根据自己的需要调整逻辑即可。我在tp里面放了一个,感觉效果不错。