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 相关文章推荐
提取HTML标签
Oct 09 PHP
php 调用远程url的六种方法小结
Nov 02 PHP
浅析memcache启动以及telnet命令详解
Jun 28 PHP
php批量更改数据库表前缀实现方法
Oct 26 PHP
php环境无法上传文件的解决方法
Apr 30 PHP
PHP 面向对象程序设计(oop)学习笔记 (四) - 异常处理类Exception
Jun 12 PHP
ThinkPHP调用common/common.php函数提示错误function undefined的解决方法
Aug 25 PHP
PHP多进程编程实例
Oct 15 PHP
微信公众号开发之通过接口删除菜单
Feb 20 PHP
PHP编辑器PhpStrom运行缓慢问题
Feb 21 PHP
PHP下 Mongodb 连接远程数据库的实例代码
Aug 30 PHP
php设计模式之策略模式实例分析【星际争霸游戏案例】
Mar 26 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 number_format() 函数通过千位分组来格式化数字的实现代码
2013/08/06 PHP
PHP设置images目录不充许http访问的方法
2016/11/01 PHP
php 使用redis锁限制并发访问类示例
2016/11/02 PHP
thinkPHP框架实现的无限回复评论功能示例
2018/06/09 PHP
Laravel框架Eloquent ORM删除数据操作示例
2019/12/03 PHP
ASP Json Parser修正版
2009/12/06 Javascript
jQuery 选择器、DOM操作、事件、动画
2010/11/25 Javascript
iphone safari不支持position fixed的解决方法
2012/05/04 Javascript
jquery写个checkbox——类似邮箱全选功能
2013/03/19 Javascript
Jquery中LigerUi的弹出编辑框(实现方法)
2013/07/09 Javascript
页面装载js及性能分析方法介绍
2014/03/21 Javascript
Nodejs中读取中文文件编码问题、发送邮件和定时任务实例
2015/01/01 NodeJs
JavaScript实现信用卡校验方法
2015/04/07 Javascript
JavaScript跨域调用基于JSON的RESTful API
2016/07/09 Javascript
html+js+highcharts绘制圆饼图表的简单实例
2016/08/04 Javascript
JavaScript lodash常见用法系列小结
2016/08/24 Javascript
ActiveX控件的使用-js实现打印超市小票功能代码详解
2017/11/22 Javascript
简单的vuex 的使用案例笔记
2018/04/13 Javascript
jQuery实现form表单序列化转换为json对象功能示例
2018/05/23 jQuery
详解如何webpack使用DllPlugin
2018/09/30 Javascript
JS实现的类似微信聊天效果示例
2019/01/29 Javascript
在vue中动态添加class类进行显示隐藏实例
2019/11/09 Javascript
深入理解python中函数传递参数是值传递还是引用传递
2017/11/07 Python
python和opencv实现抠图
2018/07/18 Python
html5生成柱状图(条形图)效果的实例代码
2016/03/25 HTML / CSS
Urban Outfitters美国官网:美国生活方式品牌
2016/08/26 全球购物
施华洛世奇波兰官网:SWAROVSKI波兰
2019/06/18 全球购物
英国名牌服装购物网站:OD’s Designer
2019/09/02 全球购物
设计部经理的岗位职责
2013/11/16 职场文书
学生自我鉴定模板
2013/12/30 职场文书
交通事故赔偿协议书
2014/04/15 职场文书
对教师的评语
2014/04/28 职场文书
分公司任命书
2014/06/06 职场文书
毕业生应聘求职信
2014/07/10 职场文书
大学生村官入党自传
2015/06/26 职场文书
2016入党积极分子考察评语
2015/12/01 职场文书