今天周日,闲下来突然想给自己的博客加个访客地图,目的是想要大概知道访客来源的地区。这里选用了百度地图开放平台的功能——点聚合。
由于之前没有做访客的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里面放了一个,感觉效果不错。