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 木马攻击防御技巧
Jun 13 PHP
php 在文件指定行插入数据的代码
May 08 PHP
php函数的常用方法及注意之处小结
Jul 10 PHP
PHP获取指定函数定义在哪个文件中以及其所在的行号实例
May 08 PHP
ThinkPHP3.1新特性之多层MVC的支持
Jun 19 PHP
PHP生成短网址的3种方法代码实例
Jul 08 PHP
php数组索引的Key加引号和不加引号的区别
Aug 19 PHP
php使用post数组的键值创建同名变量并赋值的方法
Apr 03 PHP
详解PHP归并排序的实现
Oct 18 PHP
php 二维数组时间排序实现代码
Nov 19 PHP
Ubuntu 16.04下安装PHP 7过程详解
Mar 28 PHP
PHP中时间加减函数strtotime用法分析
Apr 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的单引号和双引号 字符串效率
2009/05/27 PHP
ThinkPHP视图查询详解
2014/06/30 PHP
windows7下安装php的php-ssh2扩展教程
2014/07/04 PHP
async和DOM Script文件加载比较
2014/07/20 PHP
thinkPHP中分页用法实例分析
2015/12/26 PHP
PHP中用mysqli面向对象打开连接关闭mysql数据库的方法
2016/11/05 PHP
JavaScript 工具库 Cloudgamer JavaScript Library v0.1 发布
2009/10/29 Javascript
JavaScript Event学习第五章 高级事件注册模型
2010/02/07 Javascript
简单分析javascript面向对象与原型
2015/05/21 Javascript
javascript事件模型介绍
2016/05/31 Javascript
JS跨域交互(jQuery+php)之jsonp使用心得
2016/07/01 Javascript
jQuery实现标签页效果实战(4)
2017/02/08 Javascript
ES6新增数据结构WeakSet的用法详解
2017/08/07 Javascript
nodejs操作mongodb的增删改查功能实例
2017/11/09 NodeJs
Vue服务器渲染Nuxt学习笔记
2018/01/31 Javascript
详解extract-text-webpack-plugin 的使用及安装
2018/06/12 Javascript
vue props传值失败 输出undefined的解决方法
2018/09/11 Javascript
VUE接入腾讯验证码功能(滑块验证)备忘
2019/05/07 Javascript
一篇文章介绍redux、react-redux、redux-saga总结
2019/05/23 Javascript
node.js express捕获全局异常的三种方法实例分析
2019/12/27 Javascript
Vue 构造选项 - 进阶使用说明
2020/08/14 Javascript
[00:32]2018DOTA2亚洲邀请赛Newbee出场
2018/04/03 DOTA
python求pi的方法
2014/10/08 Python
代码讲解Python对Windows服务进行监控
2018/02/11 Python
Python模拟简单电梯调度算法示例
2018/08/20 Python
python实现信号时域统计特征提取代码
2020/02/26 Python
pycharm如何实现跨目录调用文件
2020/02/28 Python
Python读取VOC中的xml目标框实例
2020/03/10 Python
浅析Python 简单工厂模式和工厂方法模式的优缺点
2020/07/13 Python
python3.9实现pyinstaller打包python文件成exe
2020/12/13 Python
美国在线精品家居网站:Burke Decor
2017/04/12 全球购物
丹尼尔惠灵顿手表天猫官方旗舰店:Daniel Wellington
2017/08/25 全球购物
小学生纪念九一八事变演讲稿
2014/09/14 职场文书
工程安全生产协议书
2014/11/21 职场文书
债务纠纷代理词
2015/05/25 职场文书
详细了解java监听器和过滤器
2021/07/09 Java/Android