PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法


Posted in PHP onJuly 01, 2016

根据IP获取访客所在国家/城市/经纬度
安装GeoIP扩展:

sudo apt-get install libgeoip-dev
pecl install geoip-1.1.0

注意:Beta版要指定版本号.如果是apt安装的PHP,直接安装php5-geoip这个包即可.
php.ini中加入:

extension=geoip.so
geoip.custom_directory="/usr/share/GeoIP"

免费下载GeoLiteCity数据库(解压后18MB):
http://dev.maxmind.com/geoip/legacy/install/city/

wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gunzip GeoLiteCity.dat.gz
sudo mkdir -v /usr/share/GeoIP
sudo mv -v GeoLiteCity.dat /usr/share/GeoIP/GeoIPCity.dat

测试:

php -a
<?php
print_r(geoip_record_by_name('106.37.165.80')); //回车后按Ctrl+D运行
Array
(
 [continent_code] => AS
 [country_code] => CN
 [country_code3] => CHN
 [country_name] => China //国家
 [region] => 22
 [city] => Beijing //城市
 [postal_code] =>
 [latitude] => 39.928901672363 //纬度
 [longitude] => 116.38829803467 //经度
 [dma_code] => 0
 [area_code] => 0
)

在命令行用geoiplookup查看IP信息:

traceroute www.oschina.net

可见IP地址

61.145.122.155
sudo apt-get install geoip-bin geoip-database
geoiplookup 61.145.122.155 -f /usr/share/GeoIP/GeoIP.dat
GeoIP Country Edition: CN, China

geoip-database提供的GeoIP.dat只能精确到国家.

geoiplookup 61.145.122.155 -f /usr/share/GeoIP/GeoIPCity.dat
GeoIP City Edition, Rev 1: CN, 30, Guangdong, Guangzhou, N/A, 23.116699, 113.250000, 0, 0

从maxmind官网下的数据库GeoLiteCity则信息更详细.

geoiplookup 61.145.122.155 则同时显示上述两个数据库的信息.

根据IP确定经纬度与计算距离

可以用

geoip_record_by_name($_SERVER['REMOTE_ADDR'])

根据用户IP确定经纬度.
注意:

geoip_record_by_name()

返回的西经和南纬是负数.

5000米转成经纬度:
纬度 Latitude:  1 deg = 110852 m
经度 Longitude: 1 deg = 111320*cos(lat) m
同一经线上,相差一纬度约为 110852 米
同一纬线上,相差一经度约为 111320*cos(lat) 米 (lat为该纬线的纬度)

<?php
//以当前用户经纬度为中心,查询5000米内的其他用户
$y = 5000 / 110852; //纬度的范围
$x = 5000 / (111320*cos($lat)); //经度的范围
$sql = '
 select * from user where 
 lat >= ($lat-$y) and lat <= ($lat+$y) and 
 lon >= ($lon-$x) and lon <= ($lon+$x);
';

数据库用户表中设两个字段,分别存储用户的经度lat和纬度lon.

($lat-$y) <= lat <= ($lat+$y)
($lon-$x) <= lon <= ($lon+$x)

这个范围是一个粗略的范围,下面计算距离后把超过5公里的用户去掉即可.

根据上面查询出来的用户的经纬度,
用半正矢公式(Haversine)根据经纬度计算两点间距离:

<?php
function distance($lat1, $lon1, $lat2, $lon2) {
 $R = 6371393; //地球平均半径,单位米
 $dlat = deg2rad($lat2-$lat1);
 $dlon = deg2rad($lon2-$lon1);
 $a = pow(sin($dlat/2), 2) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * pow(sin($dlon/2), 2);
 $c = 2 * atan2(sqrt($a), sqrt(1-$a));
 $d = $R * $c;
 return round($d);
}
echo distance(0, 0, -1, 0); // 111202米

然后就可以用uasort或array_multisort由近到远列出用户了,比如有名为win,osx,lin这3个用户:

<?php
$arr = array(
 'win' => array(
  'dis' => 1024,
  'age' => 31
 ),
 'osx' => array(
  'dis' => 512,
  'age' => 15
 ),
 'lin' => array(
  'dis' => 512,
  'age' => 25
 )
);
foreach($arr as $k => $v) {
 $sort['dis'][$k] = $v['dis'];
 $sort['age'][$k] = $v['age'];
}
//先按距离升序排序,如果距离相同,则按年龄降序排序
array_multisort($sort['dis'], SORT_ASC, $sort['age'], SORT_DESC, $arr);
echo json_encode($arr);
//{"lin":{"dis":512,"age":25},"osx":{"dis":512,"age":15},"win":{"dis":1024,"age":31}}
PHP 相关文章推荐
JAVA/JSP学习系列之七
Oct 09 PHP
如何对PHP程序中的常见漏洞进行攻击(上)
Oct 09 PHP
PHP与MySQL开发中页面出现乱码的一种解决方法
Jul 29 PHP
php REMOTE_ADDR之获取访客IP的代码
Apr 22 PHP
php缓冲输出实例分析
Jan 05 PHP
PHP实现简单汉字验证码
Jul 28 PHP
Linux环境下php实现给网站截图的方法
May 03 PHP
php 使用fopen函数创建、打开文件详解及实例代码
Sep 24 PHP
详谈php静态方法及普通方法的区别
Oct 04 PHP
微信小程序 消息推送php服务器验证实例详解
Mar 30 PHP
PHP解决中文乱码
Apr 28 PHP
Thinkphp5.0 框架的请求方式与响应方式分析
Oct 14 PHP
php投票系统之增加与删除投票(管理员篇)
Jul 01 #PHP
PHP读书笔记_运算符详解
Jul 01 #PHP
php+MySql实现登录系统与输出浏览者信息功能
Jul 01 #PHP
php无法连接mysql数据库的正确解决方法
Jul 01 #PHP
Apache无法自动跳转却显示目录的解决方法
Nov 30 #PHP
Windows2003下php5.4安装配置教程(IIS)
Jun 30 #PHP
Windows2003下php5.4安装配置教程(Apache2.4)
Jun 30 #PHP
You might like
5种PHP创建数组的实例代码分享
2014/01/17 PHP
php文件读取方法实例分析
2015/06/20 PHP
thinkphp3.2.3版本的数据库增删改查实现代码
2016/09/22 PHP
如何在Laravel之外使用illuminate组件详解
2020/09/20 PHP
Nigma vs Alliance BO5 第三场2.14
2021/03/10 DOTA
img onload事件绑定各浏览器均可执行
2012/12/19 Javascript
谈谈关于JavaScript 中的 MVC 模式
2013/04/11 Javascript
JavaScript变量的作用域全解析
2015/08/14 Javascript
详解AngularJS控制器的使用
2016/03/09 Javascript
浅析C/C++,Java,PHP,JavaScript,Json数组、对象赋值时最后一个元素后面是否可以带逗号
2016/03/22 Javascript
基于javascript实现图片滑动效果
2016/05/07 Javascript
Bootstrap3制作图片轮播效果
2016/05/12 Javascript
JavaScript基础知识点归纳(推荐)
2016/07/09 Javascript
vue.js+Element实现表格里的增删改查
2017/01/18 Javascript
快速理解 JavaScript 中的 LHS 和 RHS 查询的用法
2017/08/24 Javascript
基于Web Audio API实现音频可视化效果
2020/06/12 Javascript
详解JavaScript 作用域
2020/07/14 Javascript
Vue filter 过滤器、以及在table中的使用介绍
2020/09/07 Javascript
nodejs中使用worker_threads来创建新的线程的方法
2021/01/22 NodeJs
Python生成数字图片代码分享
2017/10/31 Python
python入门前的第一课 python怎样入门
2018/03/06 Python
python素数筛选法浅析
2018/03/19 Python
Python OOP类中的几种函数或方法总结
2019/02/22 Python
解决python super()调用多重继承函数的问题
2019/06/26 Python
Python3.0 实现决策树算法的流程
2019/08/08 Python
利用python绘制中国地图(含省界、河流等)
2020/09/21 Python
解决margin 外边距合并问题
2019/07/03 HTML / CSS
机票销售员态度不好检讨书
2014/09/27 职场文书
演讲比赛主持词
2015/06/29 职场文书
公司庆典主持词
2015/07/04 职场文书
MySQL Innodb关键特性之插入缓冲(insert buffer)
2021/04/08 MySQL
解决golang在import自己的包报错的问题
2021/04/29 Golang
何时使用Map来代替普通的JS对象
2021/04/29 Javascript
python turtle绘图命令及案例
2021/11/23 Python
Redis命令处理过程源码解析
2022/02/12 Redis
设置IIS Express并发数
2022/07/07 Servers