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的宝库目录--PEAR
Oct 09 PHP
一次编写,随处运行
Oct 09 PHP
Notice: Undefined index: page in E:\PHP\test.php on line 14
Nov 02 PHP
php simplexmlElement操作xml的命名空间实现代码
Jan 04 PHP
使用XDebug调试及单元测试覆盖率分析
Jan 27 PHP
PHP的PSR规范中文版
Sep 28 PHP
在PHP中使用redis
Nov 04 PHP
限制ckeditor上传图片文件大小的方法
Nov 15 PHP
php读取远程gzip压缩网页的方法
Dec 29 PHP
PHP实现QQ空间自动回复说说的方法
Dec 02 PHP
Zend Framework入门教程之Zend_Config组件用法详解
Dec 09 PHP
PDO::prepare讲解
Jan 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 include的妙用,实现路径加密
2008/07/29 PHP
php递归获取目录内文件(包含子目录)封装类分享
2013/12/25 PHP
浅析iis7.5安装配置php环境
2015/05/10 PHP
PHP中Trait及其应用详解
2017/02/14 PHP
PHP快速推送微信模板消息
2017/04/14 PHP
php curl上传、下载、https登陆实现代码
2017/07/23 PHP
对于Laravel 5.5核心架构的深入理解
2018/02/22 PHP
js控制表单操作的常用代码小结
2013/08/15 Javascript
javascript特殊用法示例介绍
2013/11/29 Javascript
JQuery中DOM事件绑定用法详解
2015/06/13 Javascript
window.location.reload 刷新使用分析(去对话框)
2015/11/11 Javascript
Node.js的Web模板引擎ejs的入门使用教程
2016/06/06 Javascript
JavaScript实现类似淘宝的购物车效果
2017/03/16 Javascript
Bootstrap实现各种进度条样式详解
2017/04/13 Javascript
vue中的 $slot 获取插槽的节点实例
2019/11/12 Javascript
使用nodejs实现JSON文件自动转Excel的工具(推荐)
2020/06/24 NodeJs
[07:52]2014DOTA2 TI逗比武士游V社解说背后的故事
2014/07/10 DOTA
10款最好的Web开发的 Python 框架
2015/03/18 Python
python定时执行指定函数的方法
2015/05/27 Python
[原创]教女朋友学Python(一)运行环境搭建
2017/11/29 Python
Python实现的多进程拷贝文件并显示百分比功能示例
2019/04/09 Python
python实现微信定时每天和女友发送消息
2019/04/29 Python
实例详解python函数的对象、函数嵌套、名称空间和作用域
2019/05/31 Python
对python 调用类属性的方法详解
2019/07/02 Python
Python爬虫动态ip代理防止被封的方法
2019/07/07 Python
pycharm设置鼠标悬停查看方法设置
2019/07/29 Python
python爬虫 execjs安装配置及使用
2019/07/30 Python
使用python+whoosh实现全文检索
2019/12/09 Python
TensorFlow实现checkpoint文件转换为pb文件
2020/02/10 Python
Python如何测试stdout输出
2020/08/10 Python
详解numpy.ndarray.reshape()函数的参数问题
2020/10/13 Python
Calzedonia美国官网:意大利风格袜子、打底裤和沙滩装
2018/07/19 全球购物
凌阳科技股份有限公司C++程序员面试题笔试题
2014/11/20 面试题
人力资源管理专业自荐书范文
2014/02/10 职场文书
写给汽车4S店的创业计划书,拿来即用!
2019/08/09 职场文书
详解运行Python的神器Jupyter Notebook
2021/06/03 Python