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学习教程之第1天
Jun 15 PHP
php不用内置函数对数组排序的两个算法代码
Feb 08 PHP
关于二级目录拖拽排序的实现(源码示例下载)
Apr 26 PHP
PHP遍历目录函数opendir()、readdir()、closedir()、rewinddir()总结
Nov 18 PHP
php用户注册时常用的检验函数实例总结
Dec 22 PHP
PHP实现采集抓取淘宝网单个商品信息
Jan 08 PHP
ecshop 2.72如何修改后台访问地址
Mar 03 PHP
php通过ksort()函数给关联数组按照键排序的方法
Mar 18 PHP
php通过curl模拟登陆DZ论坛
May 11 PHP
php实现图片上传并进行替换操作
Mar 15 PHP
php封装json通信接口详解及实例
Mar 07 PHP
PHP经典实用正则表达式小结
May 04 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时间戳转换的示例
2014/03/31 PHP
用php代码限制国内IP访问我们网站
2015/09/26 PHP
javaScript同意等待代码实现心得
2011/01/01 Javascript
javascript学习笔记(十六) 系统对话框(alert、confirm、prompt)
2012/06/20 Javascript
随鼠标上下滚动的jquery代码
2013/12/05 Javascript
JS交换变量的方法
2015/01/21 Javascript
Jquery 分页插件之Jquery Pagination
2015/08/25 Javascript
JS实现重新加载当前页面或者父页面的几种方法
2016/11/30 Javascript
Vue非父子组件通信详解
2017/06/12 Javascript
JavaScript对JSON数据进行排序和搜索
2017/07/24 Javascript
JavaScript学习笔记之函数记忆
2017/09/06 Javascript
JavaScript同源策略和跨域访问实例详解
2018/04/03 Javascript
一次微信小程序内地图的使用实战记录
2019/09/09 Javascript
解决node终端下运行js文件不支持ES6语法
2020/04/04 Javascript
[43:24]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS Liquid
2018/03/30 DOTA
python的pdb调试命令的命令整理及实例
2017/07/12 Python
Python使用pandas处理CSV文件的实例讲解
2018/06/22 Python
flask中的wtforms使用方法
2018/07/21 Python
Python给图像添加噪声具体操作
2019/03/03 Python
python 为什么说eval要慎用
2019/03/26 Python
python修改字典键(key)的方法
2019/08/05 Python
python3读取csv文件任意行列代码实例
2020/01/13 Python
python 无损批量压缩图片(支持保留图片信息)的示例
2020/09/22 Python
python实现AdaBoost算法的示例
2020/10/03 Python
德国家具、照明、家居用品网上商店:Wayfair.de
2020/02/13 全球购物
安全生产检讨书
2014/01/21 职场文书
家具公司总经理岗位职责
2014/07/08 职场文书
幼儿园教师节演讲稿
2014/09/03 职场文书
2014年酒店年度工作总结
2014/12/10 职场文书
2015年安全生产责任书
2015/01/30 职场文书
督导岗位职责范本
2015/04/10 职场文书
离开雷锋的日子观后感
2015/06/09 职场文书
少先队入队仪式主持词
2015/07/04 职场文书
解析Java异步之call future
2021/06/14 Java/Android
Python 正则模块详情
2021/11/02 Python
动画《朋友游戏》公开佐藤友生绘制的开播纪念绘
2022/04/06 日漫