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实现的在线人员函数库
Apr 09 PHP
php与XML、XSLT、Mysql的结合运用实现代码
Nov 19 PHP
PHP字符串的递增和递减示例介绍
Feb 11 PHP
Yii结合CKEditor实现图片上传功能
Jun 13 PHP
thinkphp3.0输出重复两次的解决方法
Dec 19 PHP
关于WordPress的SEO优化相关的一些PHP页面脚本技巧
Dec 10 PHP
使用PHP如何实现高效安全的ftp服务器(一)
Dec 20 PHP
PHP中文字符串截断无乱码解决方法
Oct 10 PHP
php实用代码片段整理
Nov 12 PHP
PHP编程实现微信企业向用户付款的方法示例
Jul 26 PHP
PHP聊天室简单实现方法详解
Dec 08 PHP
PHP goto语句用法实例
Aug 06 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
IE 缓存策略的BUG的解决方法
2007/07/21 Javascript
各浏览器对link标签onload/onreadystatechange事件支持的差异分析
2011/04/27 Javascript
8款非常棒的响应式jQuery 幻灯片插件推荐
2012/02/02 Javascript
jquery 跳到顶部和底部动画2句代码简单实现
2013/07/18 Javascript
javascript操作referer详细解析
2014/03/10 Javascript
JavaScript中的函数重载深入理解
2014/08/04 Javascript
JavaScript中number转换成string介绍
2014/12/31 Javascript
jquery通过load获取文件的内容并跳到锚点的方法
2015/01/29 Javascript
jQuery插件实现静态HTML验证码校验
2015/11/06 Javascript
javascript从作用域链谈闭包
2020/07/29 Javascript
jQuery改变form表单的action,并进行提交的实现代码
2016/05/25 Javascript
JavaScript实现广告弹窗效果
2016/08/09 Javascript
简单实现JavaScript图片切换效果
2016/11/28 Javascript
完美解决浏览器跨域的几种方法(汇总)
2017/05/08 Javascript
EasyUI的DataGrid绑定Json数据源的示例代码
2017/12/16 Javascript
通过webpack引入第三方库的方法
2018/07/20 Javascript
30分钟精通React今年最劲爆的新特性——React Hooks
2019/03/11 Javascript
[08:53]DOTA2-DPC中国联赛 正赛 PSG.LGD vs LBZS 选手采访
2021/03/11 DOTA
python3.6+django2.0开发一套学员管理系统
2018/03/03 Python
python利用smtplib实现QQ邮箱发送邮件
2020/05/20 Python
Python数据类型之String字符串实例详解
2019/05/08 Python
tensorflow实现读取模型中保存的值 tf.train.NewCheckpointReader
2020/02/10 Python
python标准库OS模块函数列表与实例全解
2020/03/10 Python
python使用多线程+socket实现端口扫描
2020/05/28 Python
MAC平台基于Python Appium环境搭建过程图解
2020/08/13 Python
css图标制作教程制作云图标
2014/01/19 HTML / CSS
CSS3解析抖音LOGO制作的方法步骤
2019/04/11 HTML / CSS
澳大利亚便宜的家庭购物网站:CrazySales
2018/02/06 全球购物
大四学年自我鉴定
2013/11/13 职场文书
广告学专业自荐信范文
2014/02/24 职场文书
《七颗钻石》教学反思
2014/02/28 职场文书
教学改革实施方案
2014/03/31 职场文书
房屋出租协议书范本(标准版)
2014/09/24 职场文书
Redis做数据持久化的解决方案及底层原理
2021/07/15 Redis
React四级菜单的实现
2022/04/08 Javascript
PyTorch中permute的使用方法
2022/04/26 Python