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 正则表达式小结
Aug 31 PHP
php面向对象全攻略 (七) 继承性
Sep 30 PHP
php 获取全局变量的代码
Apr 21 PHP
最新用php获取谷歌PR值算法,附上php查询PR值代码示例
Dec 25 PHP
php preg_filter执行一个正则表达式搜索和替换
Feb 27 PHP
PHP程序级守护进程的实现与优化的使用概述
May 02 PHP
关于PHP堆栈与列队的学习
Jun 21 PHP
使用php自动备份数据库表的实现方法
Jul 28 PHP
Laravel 加载第三方类库的方法
Apr 20 PHP
YII框架http缓存操作示例
Apr 29 PHP
Centos7 Yum安装PHP7.2流程教程详解
Jul 02 PHP
php使用fputcsv实现大数据的导出操作详解
Feb 27 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+mysql大量用户登录解决方案分析
2014/12/29 PHP
yii2框架中使用下拉菜单的自动搜索yii-widget-select2实例分析
2016/01/09 PHP
PHP7基于curl实现的上传图片功能
2018/05/11 PHP
将string解析为json的几种方式小结
2010/11/11 Javascript
js前台分页显示后端JAVA数据响应
2013/03/18 Javascript
当达到输入长度时表单自动切换焦点
2014/04/06 Javascript
jQuery中:image选择器用法实例
2015/01/03 Javascript
jQuery使用animate创建动画用法实例
2015/08/07 Javascript
javascript正则表达式定义(语法)总结
2016/01/08 Javascript
JavaScript简单下拉菜单特效
2016/09/13 Javascript
jQuery实现6位数字密码输入框
2016/12/29 Javascript
jQuery的时间datetime控件在AngularJs中的使用实例(分享)
2017/08/17 jQuery
vue路由懒加载的实现方法
2018/03/12 Javascript
jQuery实现浏览器之间跳转并传递参数功能【支持中文字符】
2018/03/28 jQuery
bootstrap datepicker的基本使用教程
2019/07/09 Javascript
关于layui的动态图标不显示的解决方法
2019/09/04 Javascript
[53:03]Optic vs TNC 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python中urllib2模块的8个使用细节分享
2015/01/01 Python
Python网站验证码识别
2016/01/25 Python
python和opencv实现抠图
2018/07/18 Python
python的schedule定时任务模块二次封装方法
2019/02/19 Python
pandas中的series数据类型详解
2019/07/06 Python
Python中print函数简单使用总结
2019/08/05 Python
Python turtle库绘制菱形的3种方式小结
2019/11/23 Python
英国第一的购买便宜玩具和游戏的在线购物网站:Bargain Max
2018/01/24 全球购物
信息管理专业推荐信
2013/10/29 职场文书
连锁经营管理专业大学生求职信
2013/10/30 职场文书
送货司机岗位职责
2013/12/11 职场文书
平民服装店创业计划书
2014/01/17 职场文书
幼儿园中秋节活动方案
2014/02/06 职场文书
武当山导游词
2015/02/03 职场文书
幼儿园庆元旦主持词
2015/07/06 职场文书
如何把新闻人物写得立体、鲜活?
2019/08/14 职场文书
导游词之井冈山
2019/11/20 职场文书
MySQL数据库完全卸载的方法
2022/03/03 MySQL
java中如何截取字符串最后一位
2022/07/07 Java/Android