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 相关文章推荐
兼容PHP5的PHP目录管理函数库
Jul 10 PHP
php程序效率优化的一些策略小结
Jul 17 PHP
解析dedeCMS验证码的实现代码
Jun 07 PHP
解析Ubuntu下crontab命令的用法
Jun 24 PHP
PHP自动重命名文件实现方法
Nov 04 PHP
ThinkPHP 404页面的设置方法
Jan 14 PHP
PHP生成各种常见验证码和Ajax验证过程
Jan 10 PHP
php微信公众号js-sdk开发应用
Nov 28 PHP
php微信开发之图片回复功能
Jun 14 PHP
PHP超低内存遍历目录文件和读取超大文件的方法
May 01 PHP
Yii2框架配置文件(Application属性)与调试技巧实例分析
May 27 PHP
解决php extension 加载顺序问题
Aug 16 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
PHP连接access数据库
2015/03/27 PHP
关于php中的json_encode()和json_decode()函数的一些说明
2016/11/20 PHP
网页设计常用的一些技巧
2006/12/22 Javascript
奇妙的js
2007/09/24 Javascript
jQuery+.net实现浏览更多内容(改编php版本)
2013/03/28 Javascript
JavaScript获取当前cpu使用率的方法
2015/12/15 Javascript
基于javascript实现图片预加载
2016/01/05 Javascript
JQuery点击行tr实现checkBox选中的简单实例
2016/05/26 Javascript
Bootstrap布局组件教程之Bootstrap下拉菜单
2016/06/12 Javascript
AngularJS中$http服务常用的应用及参数
2016/08/22 Javascript
值得分享的JavaScript实现图片轮播组件
2016/11/21 Javascript
Vue 单文件中的数据传递示例
2017/03/21 Javascript
Angular中实现树形结构视图实例代码
2017/05/05 Javascript
JavaScript对JSON数据进行排序和搜索
2017/07/24 Javascript
详解vue mint-ui源码解析之loadmore组件
2017/10/11 Javascript
vue2.0移动端滑动事件vue-touch的实例代码
2018/11/27 Javascript
JavaScript常见事件处理程序实例总结
2019/01/05 Javascript
解决jquery validate 验证不通过后验证正确的信息仍残留在label上的方法
2019/08/27 jQuery
ZK中使用JS读取客户端txt文件内容问题
2019/11/07 Javascript
微信小程序封装多张图片上传api代码实例
2019/12/30 Javascript
vue.js+ElementUI实现进度条提示密码强度效果
2020/01/18 Javascript
js找出5个数中最大的一个数和倒数第二大的数实现方法示例小结
2020/03/04 Javascript
antd table按表格里的日期去排序操作
2020/11/17 Javascript
Android应用开发中Action bar编写的入门教程
2016/02/26 Python
python如何为创建大量实例节省内存
2018/03/20 Python
django将图片上传数据库后在前端显式的方法
2018/05/25 Python
python os用法总结
2018/06/08 Python
pytorch 彩色图像转灰度图像实例
2020/01/13 Python
英国亚马逊官方网站:Amazon.co.uk
2019/08/09 全球购物
安全检查与奖惩制度
2014/01/23 职场文书
2015年护士节活动总结
2015/02/10 职场文书
学生会个人总结范文
2015/02/15 职场文书
2016年小学感恩节活动总结
2016/04/01 职场文书
centos8安装MongoDB的详细过程
2021/10/24 MongoDB
Vue的列表之渲染,排序,过滤详解
2022/02/24 Vue.js
pytorch分类模型绘制混淆矩阵以及可视化详解
2022/04/07 Python