前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >小课堂 | 根据ip获取城市名

小课堂 | 根据ip获取城市名

作者头像
孟君
发布2021-11-16 15:26:49
3.4K0
发布2021-11-16 15:26:49
举报

在某些场景下,我们需要根据ip获得对应的城市名称。比如,我们需要统计访问ip在各城市的分布;如物联网环境中,设备接入按城市维度进行统计等。

到目前为止,很多开放接口,如淘宝、新浪、腾讯、百度等开放接口或失效或需要key。很多接口已不再免费调用,本文提供3种方式:

  • 使用莫名API
  • 使用Ip2Region
  • 使用MaxMind提供的GeoIp离线包

1、使用莫名API

莫名API介绍

访问https://api.qzone.work/doc/ipaddress.html了解。其返回结果格式如下:

代码语言:javascript
复制
{
  "msg":"success",
  "code":10000,
  "data":{
    "country":"中国",
    "province":"广东省",
    "city":"深圳市",
    "ip":"101.105.35.57",
    "ISP":"鹏博士"
  },
  "time":0.00932,
  "info":"欢迎使用莫名博客(Qzone.Work)旗下免费提供的API服务!"
}

代码步骤

1、构建HttpClient对象,调用莫名API的URL地址

代码语言:javascript
复制
    String url = "https://api.qzone.work/api/ip.address?ip="+ip;
    String cityName = "";
    HttpClient client = HttpClientBuilder.create().build();
    HttpGet request = new HttpGet(url);

2、解析返回的json字串即可

代码语言:javascript
复制
    HttpResponse response = client.execute(request);
    int statusCode = response.getStatusLine().getStatusCode();
    if (statusCode == HttpStatus.SC_OK) {
        String strResult = EntityUtils.toString(response.getEntity());
          JSONObject jsonResult = JSON.parseObject(strResult);
          System.out.println(JSON.toJSONString(jsonResult, true));
          JSONObject dataJson = jsonResult.getJSONObject("data");
          cityName = dataJson.getString("city");
     }
 ... ...

2、使用ip2region

ip2region - 准确率99.9%的离线IP地址定位库,0.0x毫秒级查询,ip2region.db数据库只有数MB,提供了java,php,c,python,nodejs,golang,c#等查询绑定和Binary,B树,内存三种查询算法。

每条ip数据段都固定了格式:

代码语言:javascript
复制
_城市Id|国家|区域|省份|城市|ISP_

如;

{
  "cityId":995,
  "dataPtr":117853,
  "region":"中国|华东|上海市|上海市|移动"
}

代码步骤:

1、准备db文件,如在src/main/resource目录下创建data目录,存放ip2region.db文件

2、引入ip2region依赖包

代码语言:javascript
复制
    <dependency>
      <groupId>org.lionsoul</groupId>
      <artifactId>ip2region</artifactId>
      <version>1.7.2</version>
    </dependency>

3、读取ip2region.db文件,指定查询算法,如btreeSearch,然后获取DataBlock 结果,block的region就包含城市信息。

代码语言:javascript
复制
    DbSearcher searcher = null;
    try {
      String dbPath = Ip2CityUtil.class.getClassLoader().getResource("data/ip2region.db").getPath();
      File file = new File(dbPath);
      if (file.exists()) {
        DbConfig config = new DbConfig();
        searcher = new DbSearcher(config, file.getPath());
        Method method = searcher.getClass().getMethod("btreeSearch", String.class);
        if (!Util.isIpAddress(ip)) {
         System.out.println("Error: Invalid ip address");
        }
        DataBlock dataBlock = (DataBlock) method.invoke(searcher, ip);
        System.out.println(JSON.toJSONString(dataBlock, true));
        return dataBlock.getRegion();
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return "";
  }

3、使用GeoLite2

GeoLite2和ip2region一样,先准备离线数据包、导入依赖包。

代码步骤:

1、准备db文件,如在src/main/resource目录下创建data目录,存放GeoLite2-City.mmdb文件

2、引入geolite2依赖包

代码语言:javascript
复制
  <dependency>
      <groupId>com.maxmind.geoip2</groupId>  
      <artifactId>geoip2</artifactId>
      <version>2.14.0</version>
  </dependency>

3、读取GeoLite2-City.mmdb文件,创建DatabaseReader对象 ,然后通过reader.city方法获取CityResponse结果,其中包含丰富的地理位置信息。

代码语言:javascript
复制
public static String getCityNameByGeoLite2(String ip) {
    try {
      InputStream database = Ip2CityUtil.class.getClassLoader().getResourceAsStream("data/GeoLite2-City.mmdb");

      // 创建 DatabaseReader对象
      DatabaseReader reader = new DatabaseReader.Builder(database).build();

      InetAddress ipAddress = InetAddress.getByName(ip);

      CityResponse response = reader.city(ipAddress);
      System.out.println(JSON.toJSONString(response, true));
      // System.out.println( response.getCity().getNames().get("zh-CN"));
      return response.getCity().getNames().get("zh-CN");
    } catch (Exception e) {
      e.printStackTrace();
    }
    return "";

  }

4、一个CityResponse的内容示例如下:

代码语言:javascript
复制
{
  "city":{
    "geoNameId":1796236,
    "name":"Shanghai",
    "names":{
      "de":"Shanghai",
      "ru":"Шанхай",
      "pt-BR":"Xangai",
      "ja":"上海",
      "en":"Shanghai",
      "fr":"Shanghai",
      "zh-CN":"上海",
      "es":"Shanghai"
    }
  },
  "continent":{
    "code":"AS",
    "geoNameId":6255147,
    "name":"Asia",
    "names":{
      "de":"Asien",
      "ru":"Азия",
      "pt-BR":"Ásia",
      "ja":"アジア",
      "en":"Asia",
      "fr":"Asie",
      "zh-CN":"亚洲",
      "es":"Asia"
    }
  },
  "country":{
    "geoNameId":1814991,
    "inEuropeanUnion":false,
    "isoCode":"CN",
    "name":"China",
    "names":{
      "de":"China",
      "ru":"Китай",
      "pt-BR":"China",
      "ja":"中国",
      "en":"China",
      "fr":"Chine",
      "zh-CN":"中国",
      "es":"China"
    }
  },
  "leastSpecificSubdivision":{
    "geoNameId":1796231,
    "isoCode":"SH",
    "name":"Shanghai",
    "names":{
      "en":"Shanghai",
      "fr":"Municipalité de Shanghai",
      "zh-CN":"上海",
      "pt-BR":"Xangai"
    }
  },
  "location":{
    "accuracyRadius":20,
    "latitude":31.0449,
    "longitude":121.4012,
    "timeZone":"Asia/Shanghai"
  },
  "maxMind":{

  },
  "mostSpecificSubdivision":{"$ref":"$.leastSpecificSubdivision"},
  "postal":{

  },
  "registeredCountry":{
    "geoNameId":1814991,
    "inEuropeanUnion":false,
    "isoCode":"CN",
    "name":"China",
    "names":{
      "de":"China",
      "ru":"Китай",
      "pt-BR":"China",
      "ja":"中国",
      "en":"China",
      "fr":"Chine",
      "zh-CN":"中国",
      "es":"China"
    }
  },
  "representedCountry":{
    "inEuropeanUnion":false,
    "names":{}
  },
  "subdivisions":[
    {"$ref":"$.leastSpecificSubdivision"}
  ],
  "traits":{
    "anonymous":false,
    "anonymousProxy":false,
    "anonymousVpn":false,
    "hostingProvider":false,
    "ipAddress":"183.194.238.19",
    "legitimateProxy":false,
    "network":{
      "networkAddress":"183.194.128.0",
      "prefixLength":17
    },
    "publicProxy":false,
    "satelliteProvider":false,
    "torExitNode":false
  }
}

可以通过response.getCity().getNames().get("zh-CN")获取城市信息,如上述示例获取的是上海

4、相关库下载

资源下载

https://pan.baidu.com/s/4pRI9z2F

GeoLite2的信息很全面,但相对而言其准确率并不是很精确。ip2region相对较准确点。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、使用莫名API
  • 2、使用ip2region
  • 3、使用GeoLite2
  • 4、相关库下载
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档