使用 GeoIP2 獲取 IP 的地理位置


1. 准備工作

准備好這兩個就可以了。


 2. 敲代碼

我使用的操作系統是 CentOS7.1。

2.1 編譯 libmaxminddb
把 libmaxminddb 的代碼下載下來,隨便放在什么地方, 然后解壓,進入解壓后的目錄,執行 bootstrap,configure,make

$ tar xzf libmaxminddb-1.3.1.tar.gz $ cd libmaxminddb-1.3.1 $ ./bootstrap $ ./configure $ make

1.在執行 bootstrap 的時候可能會報錯,應該是缺少 autoconf 之類的自動構建工具導致的,到谷歌或者百度查詢一下安裝即可。

2.在執行 make 命令的時候,也會報錯,不過報錯信息指向的是 libmaxminddb-1.3.1/t 里面缺少 libtap/tap.h。 https://github.com/pozorvlak/libtap 是 libtap 在 GitHub 上的地址, 其項目首頁上的注釋是:Testing library for C, implementing the Test Anything Protocol. Written by Nik Clayton.

既然是測試使用的,那么不編譯應該也沒什么大問題。

3.看 make 命令后的編譯記錄,可以發現 libmaxminddb.a 靜態鏈接庫已經編譯好了, 並且放在了 libmaxminddb-1.3.1/src/.libs 目錄里面。

[root@fengbo libmaxminddb-1.3.1]# ls src/.libs/ -l total 312
-rw-r--r--. 1 root root  12632 Dec  8 22:30 data-pool.o -rw-r--r--. 1 root root 111620 Dec  8 22:30 libmaxminddb.a lrwxrwxrwx. 1 root root     18 Dec  8 22:30 libmaxminddb.la -> ../libmaxminddb.la -rw-r--r--. 1 root root    959 Dec  8 22:30 libmaxminddb.lai lrwxrwxrwx. 1 root root     21 Dec  8 22:30 libmaxminddb.so -> libmaxminddb.so.0.0.7 lrwxrwxrwx. 1 root root     21 Dec  8 22:30 libmaxminddb.so.0 -> libmaxminddb.so.0.0.7
-rwxr-xr-x. 1 root root  79477 Dec  8 22:30 libmaxminddb.so.0.0.7
-rw-r--r--. 1 root root 100104 Dec  8 22:30 maxminddb.o

2.2 編寫示例代碼

示例代碼是從 maxmind 的官方 GitHub 上直接復制下來的。不過我加了幾條日志信息。 https://github.com/maxmind/libmaxminddb/blob/master/doc/libmaxminddb.md#example

代碼如下:$cat example.c

#include <errno.h>
#include "maxminddb.h"
#include <stdlib.h>
#include <string.h>

#define xdebug(fmt, arg...) \
    do{\
        printf("%s %d : ", __FILE__, __LINE__); \
        printf(fmt, ##arg); \
        printf("\n"); \
    }while(0)

int main(int argc, char **argv)
{
    if(argc < 2) {
        xdebug("Usage : %s dbfilename IP", argv[0]);
    }
    char *filename = argv[1];
    char *ip_address = argv[2];

    MMDB_s mmdb;
    int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb);

    if (MMDB_SUCCESS != status) {
        fprintf(stderr, "\n  Can't open %s - %s\n",
                filename, MMDB_strerror(status));

        if (MMDB_IO_ERROR == status) {
            fprintf(stderr, "    IO error: %s\n", strerror(errno));
        }
        exit(1);
    }

    int gai_error, mmdb_error;
    MMDB_lookup_result_s result =
        MMDB_lookup_string(&mmdb, ip_address, &gai_error, &mmdb_error);

    if (0 != gai_error) {
        fprintf(stderr,
                "\n  Error from getaddrinfo for %s - %s\n\n",
                ip_address, gai_strerror(gai_error));
        exit(2);
    }

    if (MMDB_SUCCESS != mmdb_error) {
        fprintf(stderr,
                "\n  Got an error from libmaxminddb: %s\n\n",
                MMDB_strerror(mmdb_error));
        exit(3);
    }

    MMDB_entry_data_list_s *entry_data_list = NULL;

    int exit_code = 0;
    if (result.found_entry) {
        int status = MMDB_get_entry_data_list(&result.entry,
                &entry_data_list);

        if (MMDB_SUCCESS != status) {
            fprintf(
                    stderr,
                    "Got an error looking up the entry data - %s\n",
                    MMDB_strerror(status));
            exit_code = 4;
            goto end;
        }

        if (NULL != entry_data_list) {
            MMDB_dump_entry_data_list(stdout, entry_data_list, 2);
        }
    } else {
        fprintf(
                stderr,
                "\n  No entry for this IP address (%s) was found\n\n",
                ip_address);
        exit_code = 5;
    }

end:
    MMDB_free_entry_data_list(entry_data_list);
    MMDB_close(&mmdb);
    exit(exit_code);
}
View Code

編譯我們的示例代碼:

把 libmaxminddb 源碼中的 libmaxminddb-1.3.1/include/maxminddb_config.h 和 libmaxminddb-1.3.1/include/maxminddb.h 放到 example.c 所在的目錄下。 還有 libmaxminddb-1.3.1/src/.libs/libmaxminddb.a 也要放進來。

$ gcc -o example example.c ./libmaxminddb.a $ ls example example.c libmaxminddb.a maxminddb_config.h maxminddb.h

2.3 下載 GeoLite2 開源數據庫
到網頁 https://dev.maxmind.com/geoip/geoip2/geolite2/ 中,下載 GeoLite2 的數據庫。

Downloads

Database MaxMind DB binary, gzipped CSV format, zipped
GeoLite2 City Download (md5 checksum) Download (md5 checksum)
GeoLite2 Country Download (md5 checksum) Download (md5 checksum)
GeoLite2 ASN (Autonomous System Number) Download (md5 checksum) Download (md5 checksum)

我下載的是 GeoLite2 City 數據庫。解壓后的文件如下:

[root@fengbo maxmind]# ls GeoLite2-City_20171205/ COPYRIGHT.txt GeoLite2-City.mmdb  LICENSE.txt  README.txt

2.4 測試一下這個程序的效果
先拿到一個 IP,比如 www.fengbohello.top 的 IP。

[root@fengbo maxmind]$ ping www.fengbohello.top PING www.fengbohello.top (139.199.212.133) 56(84) bytes of data. 64 bytes from 139.199.212.133: icmp_seq=1 ttl=48 time=41.7 ms

運行一下 example 試試看:

[root@fengbo maxmind]$ ./example GeoLite2-City_20171205/GeoLite2-City.mmdb "139.199.212.133" { "city": { "geoname_id": 1816670 <uint32>
        "names": { "de": "Peking" <utf8_string>
            "en": "Beijing" <utf8_string>
            "es": "Pekín" <utf8_string>
            "fr": "Pékin" <utf8_string>
            "ja": "北京市" <utf8_string>
            "pt-BR": "Pequim" <utf8_string>
            "ru": "Пекин" <utf8_string>
            "zh-CN": "北京" <utf8_string> } } "continent": { "code": "AS" <utf8_string>
        "geoname_id": 6255147 <uint32>
        "names": { "de": "Asien" <utf8_string>
            "en": "Asia" <utf8_string>
            "es": "Asia" <utf8_string>
            "fr": "Asie" <utf8_string>
            "ja": "アジア" <utf8_string>
            "pt-BR": "Ásia" <utf8_string>
            "ru": "Азия" <utf8_string>
            "zh-CN": "亞洲" <utf8_string> } } "country": { "geoname_id": 1814991 <uint32>
        "iso_code": "CN" <utf8_string>
        "names": { "de": "China" <utf8_string>
            "en": "China" <utf8_string>
            "es": "China" <utf8_string>
            "fr": "Chine" <utf8_string>
            "ja": "中國" <utf8_string>
            "pt-BR": "China" <utf8_string>
            "ru": "Китай" <utf8_string>
            "zh-CN": "中國" <utf8_string> } } "location": { "accuracy_radius": 50 <uint16>
        "latitude": 39.928900 <double>
        "longitude": 116.388300 <double>
        "time_zone": "Asia/Shanghai" <utf8_string> } "registered_country": { "geoname_id": 1814991 <uint32>
        "iso_code": "CN" <utf8_string>
        "names": { "de": "China" <utf8_string>
            "en": "China" <utf8_string>
            "es": "China" <utf8_string>
            "fr": "Chine" <utf8_string>
            "ja": "中國" <utf8_string>
            "pt-BR": "China" <utf8_string>
            "ru": "Китай" <utf8_string>
            "zh-CN": "中國" <utf8_string> } } "subdivisions": [ { "geoname_id": 2038349 <uint32>
          "iso_code": "11" <utf8_string>
          "names": { "en": "Beijing" <utf8_string>
              "fr": "Municipalité de Pékin" <utf8_string>
              "zh-CN": "北京市" <utf8_string> } } ] }
View Code

我擦,解析結果居然是北京。我問了十三哥,他說我們的服務器是騰訊雲的,當時選擇的是深圳機房。

下面是使用不同的廠商得到的結果:

廠商 地理位置
百度 廣東省廣州市 騰訊集團
ip.cn 廣東省深圳市 騰訊雲
freegeoip.net China.Beijing
新浪:int.dpool.sina.com.cn 中國.廣東.廣州
淘寶:ip.taobao.com 中國.華南.廣東省.廣州市.電信
騰訊:ip.qq.com 中國廣東省廣州市 未知

有意思吧,我也不知道該信誰的。


同步發表:https://www.fengbohello.top/archives/ip2location-geolite2

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM