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 相关文章推荐
Windows下的PHP5.0安装配制详解
Sep 05 PHP
PHP Mysql编程之高级技巧
Aug 27 PHP
php strtotime 函数UNIX时间戳
Jan 14 PHP
编译php 5.2.14+fpm+memcached(具体操作详解)
Jun 18 PHP
php取得字符串首字母的方法
Mar 25 PHP
php数组生成html下拉列表的方法
Jul 20 PHP
详解WordPress中的头像缓存和代理中的缓存更新方法
Mar 01 PHP
9个比较实用的php代码片段
Mar 15 PHP
PHP基于单例模式编写PDO类的方法
Sep 13 PHP
php封装的pdo数据库操作工具类与用法示例
May 08 PHP
Laravel 微信小程序后端搭建步骤详解
Nov 26 PHP
tp5.1框架数据库子查询操作实例分析
May 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第一次无法获取cookie问题处理
2014/12/15 PHP
php实现每天自动变换随机问候语的方法
2015/05/12 PHP
PHP strip_tags() 去字符串中的 HTML、XML 以及 PHP 标签的函数
2016/05/22 PHP
PHP如何使用JWT做Api接口身份认证的实现
2020/02/03 PHP
Js 时间间隔计算的函数(间隔天数)
2011/11/15 Javascript
深入理解Javascript中this的作用域
2014/08/12 Javascript
js运动动画的八个知识点
2015/03/12 Javascript
跟我学习javascript创建对象(类)的8种方法
2015/11/20 Javascript
js面向对象的写法
2016/02/19 Javascript
Javascript基础_标记文字的实现方法
2016/06/14 Javascript
全面了解js中的script标签
2016/07/04 Javascript
easyui datagrid 大数据加载效率慢,优化解决方法(推荐)
2016/11/09 Javascript
Extjs gridpanel 中的checkbox(复选框)根据某行的条件不能选中的解决方法
2017/02/17 Javascript
jQuery遍历节点方法汇总(推荐)
2017/05/13 jQuery
JS+jQuery实现注册信息的验证功能
2017/09/26 jQuery
Vue项目使用CDN优化首屏加载问题
2018/04/01 Javascript
vue之封装多个组件调用同一接口的案例
2020/08/11 Javascript
Django实现快速分页的方法实例
2017/10/22 Python
python opencv之SURF算法示例
2018/02/24 Python
python 从文件夹抽取图片另存的方法
2018/12/04 Python
Python实现合并两个有序链表的方法示例
2019/01/31 Python
使用Pandas对数据进行筛选和排序的实现
2019/07/29 Python
Python读写文件模式和文件对象方法实例详解
2019/09/17 Python
python实现录屏功能(亲测好用)
2020/03/02 Python
浅谈TensorFlow之稀疏张量表示
2020/06/30 Python
python logging 重复写日志问题解决办法详解
2020/08/04 Python
Charles&Keith美国官方网站:新加坡快时尚鞋类和配饰零售商
2019/11/27 全球购物
五年后的职业生涯规划
2014/03/04 职场文书
演讲稿的写法
2014/05/19 职场文书
实习协议书范本
2014/09/25 职场文书
先进事迹材料怎么写
2014/12/30 职场文书
拾金不昧表扬信
2015/01/16 职场文书
小学教师自我评价
2015/03/04 职场文书
财务会计求职信范文
2015/03/20 职场文书
《青山不老》教学反思
2016/02/22 职场文书
安装pytorch时报sslerror错误的解决方案
2021/05/17 Python