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 相关文章推荐
用PHP和ACCESS写聊天室(九)
Oct 09 PHP
非常不错的MySQL优化的8条经验
Mar 24 PHP
PHP array 的加法操作代码
Jul 24 PHP
php文件上传的例子及参数详解
Dec 12 PHP
ThinkPHP框架实现session跨域问题的解决方法
Jul 01 PHP
php中Array2xml类实现数组转化成XML实例
Dec 08 PHP
PHP实现的redis主从数据库状态检测功能示例
Jul 20 PHP
PHP中“=&gt;
Mar 01 PHP
thinkPHP5框架接口写法简单示例
Aug 05 PHP
Laravel如何实现适合Api的异常处理响应格式
Jun 14 PHP
PHP unset函数原理及使用方法解析
Aug 14 PHP
Cookie跨域问题解决方案代码示例
Nov 24 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
2019十大人气国漫
2020/03/13 国漫
安装PHP可能遇到的问题“无法载入mysql扩展” 的解决方法
2007/04/16 PHP
php file_get_contents抓取Gzip网页乱码的三种解决方法
2013/11/12 PHP
PHP命名空间(namespace)的动态访问及使用技巧
2014/08/18 PHP
为你总结一些php系统类函数
2015/10/21 PHP
php正则提取html图片(img)src地址与任意属性的方法
2017/02/08 PHP
js固定DIV高度,超出部分自动添加滚动条的简单方法
2013/07/10 Javascript
ie8下修改input的type属性报错的解决方法
2014/09/16 Javascript
关于编写性能高效的javascript事件的技术
2014/11/28 Javascript
浅谈javascript事件取消和阻止冒泡
2015/05/26 Javascript
JavaScript数组去重的五种方法
2015/11/05 Javascript
7个jQuery最佳实践
2016/01/12 Javascript
JavaScript判断用户名和密码不能为空的实现代码
2016/05/16 Javascript
jquery版轮播图效果和extend扩展
2017/07/18 jQuery
jquery学习笔记之无new构建详解
2017/12/07 jQuery
微信小程序开发之获取用户手机号码(php接口解密)
2020/05/17 Javascript
[01:07:20]DOTA2-DPC中国联赛 正赛 Dynasty vs XG BO3 第二场 2月2日
2021/03/11 DOTA
Python守护进程和脚本单例运行详解
2017/01/06 Python
Pycharm学习教程(2) 代码风格
2017/05/02 Python
python中将一个全部为int的list 转化为str的list方法
2018/04/09 Python
python 实现对数据集的归一化的方法(0-1之间)
2018/07/17 Python
python组合无重复三位数的实例
2018/11/13 Python
python实现剪切功能
2019/01/23 Python
简单了解django orm中介模型
2019/07/30 Python
PyCharm导入python项目并配置虚拟环境的教程详解
2019/10/13 Python
python主要用于哪些方向
2020/07/05 Python
Jmeter HTTPS接口测试证书导入过程图解
2020/07/22 Python
详解Python中import机制
2020/09/11 Python
领先的荷兰线上超市:荷兰之家Holland at Home(支持中文)
2021/01/21 全球购物
请介绍一下Ant
2016/07/22 面试题
体育教育专业毕业生自荐信
2013/11/15 职场文书
利群广告词
2014/03/20 职场文书
十二生肖观后感
2015/06/12 职场文书
财产分割协议书
2016/03/22 职场文书
班干部竞选演讲稿(精选5篇)
2019/09/24 职场文书
nginx.conf配置文件结构小结
2022/04/08 Servers