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 02 PHP
解析Linux下Varnish缓存的配置优化
Jun 20 PHP
如何使用PHP获取指定日期所在月的开始日期与结束日期
Aug 01 PHP
浅析php fwrite写入txt文件的时候用 \r\n不能换行的问题
Aug 06 PHP
PHP实现采集抓取淘宝网单个商品信息
Jan 08 PHP
Laravel 5 框架入门(四)完结篇
Apr 09 PHP
PHP5.4起内置web服务器使用方法
Aug 09 PHP
Yii2创建多界面主题(Theme)的方法
Oct 08 PHP
Win7环境下Apache连接MySQL提示连接已重置的解决办法
May 09 PHP
PHP后端银联支付及退款实例代码
Jun 23 PHP
php正则表达式使用方法整理集合
Jan 31 PHP
PHP设计模式(一)工厂模式Factory实例详解【创建型】
May 02 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 HTML代码串 截取实现代码
2009/06/29 PHP
PHP命名空间(Namespace)的使用详解
2013/05/04 PHP
PHP第三方登录―QQ登录实现方法
2017/02/06 PHP
关于php几种字符串连接的效率比较(详解)
2017/02/22 PHP
PHP实现微信支付(jsapi支付)流程步骤详解
2018/03/15 PHP
javascript之通用简单的table选项卡实现(二)
2010/05/09 Javascript
使用Json比用string返回数据更友好,也更面向对象一些
2011/09/13 Javascript
js实现弹窗插件功能实例代码分享
2013/12/12 Javascript
网站内容禁止复制和粘贴、另存为的js代码
2014/02/26 Javascript
JavaScript Array对象扩展indexOf()方法
2014/05/09 Javascript
Node.js模块加载详解
2014/08/16 Javascript
AngularJS向后端ASP.NET API控制器上传文件
2016/02/03 Javascript
Js遍历键值对形式对象或Map形式的方法
2016/08/08 Javascript
微信小程序 动态的设置图片的高度和宽度详解及实例代码
2017/02/24 Javascript
JQuery form表单提交前验证单选框是否选中、删除记录时验证经验总结(整理)
2017/06/09 jQuery
微信小程序 获取javascript 里的数据
2017/08/17 Javascript
Bootstrap图片轮播效果详解
2017/10/17 Javascript
浅谈Node.js CVE-2017-14849 漏洞分析(详细步骤)
2017/11/10 Javascript
使用svg实现动态时钟效果
2018/07/17 Javascript
vue实现广告栏上下滚动效果
2020/11/26 Vue.js
Node使用koa2实现一个简单JWT鉴权的方法
2021/01/26 Javascript
python3 实现的人人影视网站自动签到
2016/06/19 Python
基于Python_脚本CGI、特点、应用、开发环境(详解)
2017/05/23 Python
python3.4用函数操作mysql5.7数据库
2017/06/23 Python
单利模式及python实现方式详解
2018/03/20 Python
Python 取numpy数组的某几行某几列方法
2019/10/24 Python
ubuntu16.04升级Python3.5到Python3.7的方法步骤
2020/08/20 Python
Delphi笔试题
2016/11/14 面试题
服装设计行业个人的自我评价
2013/12/20 职场文书
师范学院毕业生求职信
2014/06/24 职场文书
道德模范事迹材料
2014/12/20 职场文书
处级干部考察材料
2014/12/24 职场文书
先进基层党组织材料
2014/12/25 职场文书
2015年人力资源工作总结
2015/04/08 职场文书
攻击最高的10只幽灵系神奇宝贝,坚盾剑怪排第一,第五最为可怕
2022/03/18 日漫
用PYTHON去计算88键钢琴的琴键频率和音高
2022/04/10 Python