关于把 IP 地址转换为地理位置可以使用网络上很多的 API,好处就是不用在本地存储一个 IP 数据库,而且一般网络上的 IP 库会自动更新,不利的地方就是太依赖于网络,性能表现也可能会弱些。比如像下面的 API:

http://api.hostip.info/get_html.php?ip=58.63.236.31
http://api.hostip.info/flag.php?ip=58.63.236.31

这里介绍 PHP 如何使用 GeoLiteCity.dat 库把 IP 转换为地理位置,GeoLiteCity.dat 可以在http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz 下,解压出 GeoLiteCity.dat,即可,我们可以手动去更新新的 IP 库。

下面 PHP 解析 IP 的过程参考自 WordPress 插件 Visitor Maps and Who's Online 的实现。可以找到该插件的两个文件 include-whos-online-geoip.php 和 visitor-maps.php 告诉了我们怎么做。你可以点击这里的链接下载到这两个文件,我这里把 include-whos-online-geoip.php 改名为 geoipcity.inc.php,然后参考 visitor-maps.php 中的 get_location_info($user_ip) 函数,那么我们可以写出自己的解析 IP 地址的程序 resolve_ip.php:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<?php
require_once("geoipcity.inc.php");
//ini_set("memory_limit","96M");
 
//最简单的函数只要这一个
function get_ip_record($user_ip) {
 
    global $path_visitor_maps;
 
    //假定 GeoLiteCity.data 放在与此文件同一目录下
    $gi = geoip_open_VMWO('GeoLiteCity.dat', VMWO_GEOIP_STANDARD);
 
    $record = geoip_record_by_addr_VMWO($gi, "$user_ip");
    geoip_close_VMWO($gi);
 
    //你可以直接使用上面取出的 $record 数据
    return $record;
}
 
function get_location_info($user_ip) {
 
    $record = get_ip_record($user_ip);
 
    //或者使用下面加工后的 $location_info
    global $GEOIP_REGION_NAME;
    $location_info = array();    // Create Result Array
 
    $location_info['city_name']    = (isset($record->city)) ? $record->city : '';  //城市
    $location_info['state_name']   = (isset($record->country_code) && isset($record->region)) //州名
          ? $GEOIP_REGION_NAME[$record->country_code][$record->region] : '';
    $location_info['state_code']   = (isset($record->region)) ? strtoupper($record->region) : ''; //州代号
    $location_info['country_name'] = (isset($record->country_name)) ? $record->country_name : '--'; //国家名
    $location_info['country_code'] = (isset($record->country_code)) ? strtoupper($record->country_code) : '--'; //国家代号
    $location_info['latitude']     = (isset($record->latitude)) ? $record->latitude : '0';   //维度
    $location_info['longitude']    = (isset($record->longitude)) ? $record->longitude : '0'; //经度
 
    //php 站点设置了 utf-8 字符集必要时进行转码
    $charset = 'utf-8';
    // this fixes accent characters on UTF-8, only when the blog charset is set to UTF-8
    if ( strtolower($charset) == 'utf-8' && function_exists('utf8_encode') ) {
        if ($location_info['city_name'] != '' ) {
            $location_info['city_name'] = utf8_encode($location_info['city_name']);
        }
        if ($location_info['state_name'] != '') {
            $location_info['state_name'] = utf8_encode($location_info['state_name']);
        }
        if ($location_info['country_name'] != '') {
            $location_info['country_name'] = utf8_encode($location_info['country_name']);
        }
    }
 
    return $location_info;
}
 
//查询一个 IP 测试下
$record = get_ip_record("206.19.49.154");
var_dump($record);
 
$location = get_location_info("206.19.49.154");
var_dump($location);
?>

执行后输出如下(可以作为系统脚本直接用 php resolve_ip.php 来执行):

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
object(geoiprecord_VMWO)#2 (10) {
  ["country_code"]=>
  string(2) "US"
  ["country_code3"]=>
  string(3) "USA"
  ["country_name"]=>
  string(13) "United States"
  ["region"]=>
  string(2) "TX"
  ["city"]=>
  string(10) "Richardson"
  ["postal_code"]=>
  string(5) "75080"
  ["latitude"]=>
  float(32.9722)
  ["longitude"]=>
  float(-96.7376)
  ["area_code"]=>
  int(972)
  ["dma_code"]=>
  float(623)
}
array(7) {
  ["city_name"]=>
  string(10) "Richardson"
  ["state_name"]=>
  string(5) "Texas"
  ["state_code"]=>
  string(2) "TX"
  ["country_name"]=>
  string(13) "United States"
  ["country_code"]=>
  string(2) "US"
  ["latitude"]=>
  float(32.9722)
  ["longitude"]=>
  float(-96.7376)
}

只要取你想要的数据就是了,里面还有诸如区号,邮编等数所,GeoLiteCity.dat 是个二进制文件,比普通文本要紧凑省空间。

不知道您有没有多留一份心,有无浏览链接:http://geolite.maxmind.com/download/geoip/api/php/,是这样的:

看到 GeoIp 给我们提供了不少的例子,那么多 sample.php,而实际上前面用到的 geoipcity.inc.php,就是 geopip.inc、geoipcity.inc 和 geoipregionvars.php 三个程序的内容合体。

再往上看:

 

官方提供的 API 何止 PHP 啊,几乎能全线满足您的实际需求了,c、java、perl、python、vb、ruby、tcl 等......,放其他程序里以后也不用愁了。

再进到 http://geolite.maxmind.com/download/geoip/database/ 瞧瞧:

正考虑着呢,不是说 IPv4 快用净了吗?IPv6 的数据也正为我们准备着呢?当然,天朝的 IPv9 恐怕永远不会有的。

本只是把 Visitor Maps and Who's Online 里的解析 IP 的做法抽出来用用,可总能不断 深入再深入,不知道可喜还是可怕了。

PHP 使用 GeoLiteCity 库解析 IP 为地理位置的更多相关文章

  1. 使用纯真IP库获取用户端地理位置信息

    引言 在一些电商类或者引流类的网站中经常会有获取用户地理位置信息的需求,下面我分享一个用纯真IP库获取用户地理位置信息的方案. 正文 第一步:本文的方案是基于纯真IP库的,所以首先要去下载最新的纯真I ...

  2. 使用 GeoIP2 获取 IP 的地理位置

    1. 准备工作 数据库 : 解析 IP 地理位置的的数据库来自 GeoLite2 开源数据库:https://dev.maxmind.com/geoip/geoip2/geolite2/ . C 语言 ...

  3. 学习Linux下的IP地址地理位置信息显示工具nali

    首先详细教程已经有前辈做了详细的安装和使用介绍,本人只是参照学习和记录下自己的实际操做. 本文参考档:http://www.cnblogs.com/mchina/archive/2012/12/24/ ...

  4. PHP通过IP 获取 地理位置(实例)

    发布:JB02   来源:脚本学堂  分享一例php代码,实现通过IP地址获取访问者的地理位置,在php编程中经常用到,有需要的朋友参考下吧.本节内容:PHP通过IP获取地理位置 例子: 复制代码代码 ...

  5. PHP通过IP 获取 地理位置(实例代码)

    发布:JB02   来源:脚本学堂 分享一例php代码,实现通过IP地址获取访问者的地理位置,在php编程中经常用到,有需要的朋友参考下吧.本节内容:PHP通过IP获取地理位置 例子: 复制代码代码示 ...

  6. python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码

    python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...

  7. Java使用纯真IP库获取IP对应省份和城市

    原文:http://blog.csdn.net/chwshuang/article/details/78027873?locationNum=10&fps=1 Java使用纯真IP库获取IP对 ...

  8. 基于thinkphp实现根据用户ip判断地理位置并提供对应天气信息的应用

    https://blog.csdn.net/MyCodeDream/article/details/46706469 我们都知道,在很多的网站都提供了给用户提供天气预报的功能,有时会发现,用户即使不输 ...

  9. [日志分析]Graylog2进阶之获取Nginx来源IP的地理位置信息

    如果你们觉得graylog只是负责日志收集的一个管理工具,那就too young too naive .日志收集只是graylog的最最基础的用法,graylog有很多实用的数据清洗和处理的进阶用法. ...

随机推荐

  1. 2.3多线程(java学习笔记)synchronized关键字

    一.为什么要用synchronized关键字 首先多线程中多个线程运行面临共享数据同步的问题. 多线程正常使用共享数据时需要经过以下步骤: 1.线程A从共享数据区中复制出数据副本,然后处理. 2.线程 ...

  2. 最近公共祖先 Least Common Ancestors(LCA)算法 --- 与RMQ问题的转换

    [简介] LCA(T,u,v):在有根树T中,询问一个距离根最远的结点x,使得x同时为结点u.v的祖先. RMQ(A,i,j):对于线性序列A中,询问区间[i,j]上的最值.见我的博客---RMQ - ...

  3. 【译】PHP之道(PHP the right way)

    刚入门的同学觉得自己能用PHP写出各种程序就很NB了,但其实作为一个专业程序员,你得有个全面点的知识结构.单元测试总得听过,文档工具总得用用,Xss总得会防.推荐大家把<PHP the righ ...

  4. SQL Server查看Sql语句执行的耗时和IO消耗

    原文:SQL Server查看Sql语句执行的耗时和IO消耗 在做系统过程中,经常需要针对某些场景进行性能优化,那么如何判定性能优化的效果呢?肯定需要知道优化之前Sql语句的耗时和优化之后Sql语句的 ...

  5. Vue2.0进阶组件 短信倒计时组件

    原本我想隔个几天再发文章,刚好今天项目上线,环境有问题,导致只有干等,刚好要为公司打造一套属于公司自己的一系列功能组件,这个使命就交给我了,大家也一直叫我来点干货,说实话我只是一个湿货,肚子里干一点就 ...

  6. A folder failed to be renamed or moved--安装Android SDK的问题

    对于Android是一直想学却一直未学,行动跟不上想法.现在,终于付诸于行动了. 首先,我找的第一个Android的资料是大话企业级Android,前阵子刚看完大话设计模式,通俗易懂,还是比较喜欢这一 ...

  7. axure产品原型图,元件库导入方法

    axure是公司产品经理常用的软件,用来绘制产品原型图. 为了画出漂亮的原型图,需要各色各样的元件.因此导入各类元件库很有用处: 打开元件库视图: 载入元件库,选择事先下载好的元件 元件库下载:htt ...

  8. 安装Webmin1.860(RPM方式)

    Webmin是基于web的功能强大的管理工具,管理员可以通过Webmin以图文方式方便的管理CentOS 7系统.本文介绍如何在CentOS 7中安装Webmin. 1.去官网获取最新的RPM链接 2 ...

  9. appium window64安装教程

    查看虫师的博客 地址http://www.cnblogs.com/fnng/p/4540731.html 共四篇

  10. android 中怎样获取IMEI号

    1)在Telephony Framework内部.能够直接使用GSMPhone或GeminiPhone提供的接口. KK之前的版本号: IMEI(International Mobile Equipm ...