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.MVC的模板标签系统(一)
Sep 05 PHP
php读取html并截取字符串的简单代码
Nov 30 PHP
PHP跨平台获取服务器IP地址自定义函数分享
Dec 29 PHP
php支付宝在线支付接口开发教程
Sep 19 PHP
PHP的Json中文处理解决方案
Sep 29 PHP
thinkPHP5框架实现基于ajax的分页功能示例
Jun 12 PHP
php中isset与empty函数的困惑与用法分析
Jul 05 PHP
解决在Laravel 中处理OPTIONS请求的问题
Oct 11 PHP
thinkphp框架类库扩展操作示例
Nov 26 PHP
php正则表达式使用方法整理集合
Jan 31 PHP
ThinkPHP3.1.2 使用cli命令行模式运行的方法
Apr 14 PHP
PHP 命名空间和自动加载原理与用法实例分析
Apr 29 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 Undefined index和Undefined variable的解决方法
2008/03/27 PHP
windows下PHP_intl.dll正确配置方法(apache2.2+php5.3.5)
2014/01/14 PHP
PHP把空格、换行符、中文逗号等替换成英文逗号的正则表达式
2014/05/04 PHP
PHP中使用循环实现的金字塔图形
2014/11/08 PHP
php实现批量删除挂马文件及批量替换页面内容完整实例
2016/07/08 PHP
PHP入门教程之上传文件实例详解
2016/09/11 PHP
php实现查询功能(数据访问)
2017/05/23 PHP
Laravel数据库读写分离配置的方法
2019/10/13 PHP
javascript 禁止复制网页
2009/06/11 Javascript
在次封装easyui-Dialog插件实现代码
2010/11/14 Javascript
基于jQuery的简单的列表导航菜单
2011/03/02 Javascript
js异常捕获方法介绍
2013/04/10 Javascript
JS.GetAllChild(element,deep,condition)使用介绍
2013/09/21 Javascript
struts2+jquery组合验证注册用户是否存在
2014/04/30 Javascript
JS不能跨域借助jquery获取IP地址的方法
2014/08/20 Javascript
详解maxlength属性在textarea里奇怪的表现
2015/12/27 Javascript
分享网页检测摇一摇实例代码
2016/01/14 Javascript
Bootstrap源码解读导航(6)
2016/12/23 Javascript
使用JavaScript触发过渡效果的方法
2017/01/19 Javascript
JS实现动态修改table及合并单元格的方法示例
2017/02/20 Javascript
微信小程序实现商品属性联动选择
2019/02/15 Javascript
javascript设计模式 ? 模板方法模式原理与用法实例分析
2020/04/23 Javascript
[55:26]DOTA2-DPC中国联赛 正赛 Aster vs LBZS BO3 第一场 2月23日
2021/03/11 DOTA
Python随机数random模块使用指南
2016/09/09 Python
python实现自主查询实时天气
2018/06/22 Python
Python wxPython库使用wx.ListBox创建列表框示例
2018/09/03 Python
Python3标准库glob文件名模式匹配的问题
2020/03/13 Python
Python中格式化字符串的四种实现
2020/05/26 Python
关于运动会的稿件
2014/02/02 职场文书
小学英语教师先进事迹
2014/05/28 职场文书
教师优秀党员事迹材料
2014/08/14 职场文书
带香烟到学校抽的检讨书
2014/09/25 职场文书
大学生自荐材料范文
2014/12/30 职场文书
索赔员岗位职责
2015/02/15 职场文书
初中物理教学反思
2016/02/19 职场文书
Java后台生成图片的完整步骤
2021/08/04 Java/Android