首页 > 编程学习 > 根据IP获取用户的地理位置

根据IP获取用户的地理位置

发布时间:2022/1/17 12:49:24

1.根据IP获取用户地理位置思路:
通过IP地址去查询数据库,然后从数据库里面提取相应地理位置信息

2.下载MaxMind的数据库下载地址
https://dev.maxmind.com/geoip/geoip2/geolite2/
它有 binary格式 和 CSV格式的,可以先都下载:

GeoLite2-City.mmdb.gz
GeoLite2-Country.mmdb.gz
GeoLite2-City-CSV_20180306.zip
GeoLite2-Country-CSV_20180306.zip

3.然后是操作它数据库的libmaxminddb的github地址:
https://github.com/maxmind/libmaxminddb/releases

libmaxminddb安装命令:

$ ./configure
$ make
$ make check
$ sudo make install
$ sudo ldconfig

libmaxminddb说明文档地址:
http://maxmind.github.io/libmaxminddb/
而且还给出一个例子:

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

int main(int argc, char **argv)
{
    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);
}

编译命令:gcc -v test.c -o mmdb -lmaxminddb

命令如下:

./mmdb <dbpath> <IP>
./mmdb /home/share/GeoLite2-City.mmdb 112.225.35.70

效果如下:

{
    "city": 
      {
        "geoname_id": 
          1805753 <uint32>
        "names": 
          {
            "de": 
              "Jinan" <utf8_string>
            "en": 
              "Jinan" <utf8_string>
            "es": 
              "Jinan" <utf8_string>
            "fr": 
              "Jinan" <utf8_string>
            "ja": 
              "済南市" <utf8_string>
            "pt-BR": 
              "Jinan" <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": 
          36.668300 <double>
        "longitude": 
          116.997200 <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": 
            1796328 <uint32>
          "iso_code": 
            "SD" <utf8_string>
          "names": 
            {
              "en": 
                "Shandong" <utf8_string>
              "fr": 
                "Province de Shandong" <utf8_string>
              "zh-CN": 
                "山东省" <utf8_string>
            }
        }
      ]
  }

单独获取其他信息:

比如我只想获取国家,省份和城市我写的例子如下:

/*
 * gcc -v test.c -o mmdb -lmaxminddb
 */
#include <maxminddb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "cJSON.h"

int main(int argc, char **argv)
{
    char *filename = "GeoLite2-City.mmdb";
    char *ip_address = argv[1];
    MMDB_s mmdb;
    char country[8] = {0};
    char province[64] = {0};
    char city[32] = {0};

    if (argc < 2){
        printf("usage <IP>\n");
        exit(1);
    }

    int status =  MMDB_open(filename, MMDB_MODE_MMAP, &mmdb);
    if (MMDB_SUCCESS != status){
        printf("can't open %s - %s\n", filename, MMDB_strerror(status));
        if ( MMDB_IO_ERROR == status ) {
            printf(" 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) {
        printf("Error from getaddrinfo for %s - %s\n\n",
                ip_address, gai_strerror(gai_error));
        exit(2);
    }

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


    MMDB_entry_data_s entry_data;

    // get country
    status = MMDB_get_value(&result.entry, &entry_data, 
            "country", "iso_code", NULL);

    if ( ! entry_data.has_data ) {
        printf("entry_data has no data\n");
        goto end;
    }

    if ( entry_data.type != MMDB_DATA_TYPE_UTF8_STRING ) {
        printf("entry_data's type isn't UTF-8");
        goto end;
    }

    memcpy(country, entry_data.utf8_string, entry_data.data_size);
    printf("country:%s\n", country);

    // get province
    status = MMDB_get_value(&result.entry, &entry_data, 
            "subdivisions", "0", "names", "en", NULL);

    if ( ! entry_data.has_data ) {
        printf("entry_data has no data\n");
        goto end;
    }

    if ( entry_data.type != MMDB_DATA_TYPE_UTF8_STRING ) {
        printf("entry_data's type isn't UTF-8");
        goto end;
    } 

    memcpy(province, entry_data.utf8_string, entry_data.data_size);
    printf("province:%s\n", province);

    // get city 
    status = MMDB_get_value(&result.entry, &entry_data, 
            "city", "names", "en", NULL);

    if ( ! entry_data.has_data ) {
        printf("entry_data has no data\n");
        goto end;
    }

    if ( entry_data.type != MMDB_DATA_TYPE_UTF8_STRING ) {
        printf("entry_data's type isn't UTF-8");
        goto end;
    } 

    memcpy(city, entry_data.utf8_string, entry_data.data_size);
    printf("city:%s\n", city);

end:
    MMDB_close(&mmdb);
    exit(0);
}

命令:./mmdb 112.225.35.70
效果如图:
这里写图片描述

Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000