您的位置:首页 > 其它

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

2018-03-16 18:46 676 查看
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

效果如图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息