最近项目某个功能需要根据ip地址从第三方接口获取详细的地理位置,从网上找了很多例子,主要接口有新浪的,淘宝的,腾讯的。试了淘宝的,如果是数量级小的还可以,如果数量级达到上十万级就速度慢了,会导致系统崩溃。下面例子是新浪的,例子不是适合每个项目,需要改一下.

/**
 ipSearchUrl=http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip=(这是新浪的接口地址)
    在项目中新浪的接口地址没有直接写死,而是去读属性文件。
*/
    public static String getIpInfoBySina(String ip){
     // 读取属性文件(属性文件key-value和格式)
        final String PROP_IPSEARCHURL="ipSearchUrl";
        final String RET_SUCCESS="1";
        final String RET="ret";
        final String PROVINCE="province";
        final String CITY="city";
        final String DISTRICT="district";
        final String ISP="isp";
        String  ipAddress="";
        if(StringUtils.isBlank(ip)){
            return null;
        }
        String url = SystemParamPropertyUtils.getSystemParamKeyValue(PROP_IPSEARCHURL);//这个是从属性文件中获取url,即新浪接口地址
        if(StringUtils.isNotBlank(url)){
            String  path=url+ip;//"http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip="+ip;
            HttpClient httpClient = new HttpClient();
            Map<String, String> paramMap = new HashMap<String, String>();
            String remoteIpInfo="";
            
            try {
                remoteIpInfo = HttpClientUtil.request(httpClient, path, paramMap,"sina");
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(StringUtils.isNotBlank(remoteIpInfo)){
                String _ret=searchValue(remoteIpInfo, RET);
                if(RET_SUCCESS.equals(_ret)){
                    String provinceName=searchValue(remoteIpInfo, PROVINCE);
                    String cityName=searchValue(remoteIpInfo, CITY);
                    String district=searchValue(remoteIpInfo, DISTRICT);
                    String isp=searchValue(remoteIpInfo, ISP);
                    ipAddress=provinceName+cityName+district+isp;
                }
            }    
        }
        return ipAddress;
    }
 private static String searchValue(String remoteIpInfo,String key){
        String _value="";
      if(StringUtils.isNotBlank(remoteIpInfo)){
          _value=StringUtils.substringBetween(remoteIpInfo,"\""+key+"\":", ",");
          if(StringUtils.isNotBlank(_value)){
                _value=UnicodeUtils.decodeUnicode(_value);                
          }
      }    
      return _value;
    }
读新浪的接口地址很快,我本人测试到了九万条左右,十分钟。淘宝的话一个多小时,五万多条。还有一个小技巧,就是把读到的ip存到map中,然后下次读的话就直接从map取出,这样快很多。这个会衍生出很多问题,当日志文件达到百万级,千万级,怎么解决。类似淘宝这样的,一秒多少订单,每个订单ip不一样。我不知道怎么解决。有大神知道回我一下。
下面是用淘宝的。
 
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
 
 
 
/**
 * 根据IP地址获取详细的地域信息 
* @author Lwl
* @dateJan 26, 2016
 */
public class AddressUtils {
 
 
    
/** 
  * 
  * @param content 
  *            请求的参数 格式为:name=xxx&pwd=xxx 
  * @param encoding 
  *            服务器端请求编码。如GBK,UTF-8等 
  * @return 
  * @throws UnsupportedEncodingException 
  */  
 public String getAddresses(String content, String encodingString)  
   throws UnsupportedEncodingException {  
  // 这里调用pconline的接口  
  String urlStr = "http://ip.taobao.com/service/getIpInfo.php";  
  // 从http://whois.pconline.com.cn取得IP所在的省市区信息  
  String returnStr = this.getResult(urlStr, content, encodingString);  
  if (returnStr != null) {  
   // 处理返回的省市区信息  
   System.out.println(returnStr);  
   String[] temp = returnStr.split(",");  
   if(temp.length<3){  
    return "0";//无效IP,局域网测试  
   }  
   String region = (temp[5].split(":"))[1].replaceAll("\"", "");  
   region = decodeUnicode(region);// 省份  
    
            String country = "";  
            String area = "";  
            // String region = "";  
            String city = "";  
            String county = "";  
            String isp = "";  
            for (int i = 0; i < temp.length; i++) {  
                switch (i) {  
                case 1:  
                    country = (temp[i].split(":"))[2].replaceAll("\"", "");  
                    country = decodeUnicode(country);// 国家  
                    break;  
                    case 3:  
                        area = (temp[i].split(":"))[1].replaceAll("\"", "");  
                        area = decodeUnicode(area);// 地区   
                    break;  
                    case 5:  
                        region = (temp[i].split(":"))[1].replaceAll("\"", "");  
                        region = decodeUnicode(region);// 省份   
                    break;   
                    case 7:  
                        city = (temp[i].split(":"))[1].replaceAll("\"", "");  
                        city = decodeUnicode(city);// 市区  
                    break;   
                    case 9:  
                            county = (temp[i].split(":"))[1].replaceAll("\"", "");  
                            county = decodeUnicode(county);// 地区   
                    break;  
                    case 11:  
                        isp = (temp[i].split(":"))[1].replaceAll("\"", "");  
                        isp = decodeUnicode(isp); // ISP公司  
                    break;  
                }  
            }  
     
    System.out.println(country+area+region+city+county+isp);  
   return new StringBuffer(country).append(area).append(region).append(city).append(county).append(isp).toString();  
  }  
  return null;  
 }  
 /** 
  * @param urlStr 
  *            请求的地址 
  * @param content 
  *            请求的参数 格式为:name=xxx&pwd=xxx 
  * @param encoding 
  *            服务器端请求编码。如GBK,UTF-8等 
  * @return 
  */  
 private String getResult(String urlStr, String content, String encoding) {  
  URL url = null;  
  HttpURLConnection connection = null;  
  try {  
   url = new URL(urlStr);  
   connection = (HttpURLConnection) url.openConnection();// 新建连接实例  
   connection.setConnectTimeout(2000);// 设置连接超时时间,单位毫秒  
   connection.setReadTimeout(33000);// 设置读取数据超时时间,单位毫秒  
   connection.setDoOutput(true);// 是否打开输出流 true|false  
   connection.setDoInput(true);// 是否打开输入流true|false  
   connection.setRequestMethod("POST");// 提交方法POST|GET  
   connection.setUseCaches(false);// 是否缓存true|false  
   connection.connect();// 打开连接端口  
   DataOutputStream out = new DataOutputStream(connection.getOutputStream());// 打开输出流往对端服务器写数据  
   out.writeBytes(content);// 写数据,也就是提交你的表单 name=xxx&pwd=xxx  
   out.flush();// 刷新  
   out.close();// 关闭输出流  
   BufferedReader reader = new BufferedReader(new InputStreamReader(  
     connection.getInputStream(), encoding));// 往对端写完数据对端服务器返回数据  
   // ,以BufferedReader流来读取  
   StringBuffer buffer = new StringBuffer();  
   String line = "";  
   while ((line = reader.readLine()) != null) {  
    buffer.append(line);  
   }  
   reader.close();  
   return buffer.toString();  
  } catch (IOException e) {  
   e.printStackTrace();  
  } finally {  
   if (connection != null) {  
    connection.disconnect();// 关闭连接  
   }  
  }  
  return null;  
 }  
 /** 
  * unicode 转换成 中文 
  * 
  * @author fanhui 2007-3-15 
  * @param theString 
  * @return 
  */  
 public static String decodeUnicode(String theString) {  
  char aChar;  
  int len = theString.length();  
  StringBuffer outBuffer = new StringBuffer(len);  
  for (int x = 0; x < len;) {  
   aChar = theString.charAt(x++);  
   if (aChar == '\\') {  
    aChar = theString.charAt(x++);  
    if (aChar == 'u') {  
     int value = 0;  
     for (int i = 0; i < 4; i++) {  
      aChar = theString.charAt(x++);  
      switch (aChar) {  
      case '0':  
      case '1':  
      case '2':  
      case '3':  
      case '4':  
      case '5':  
      case '6':  
      case '7':  
      case '8':  
      case '9':  
       value = (value << 4) + aChar - '0';  
       break;  
      case 'a':  
      case 'b':  
      case 'c':  
      case 'd':  
      case 'e':  
      case 'f':  
       value = (value << 4) + 10 + aChar - 'a';  
       break;  
      case 'A':  
      case 'B':  
      case 'C':  
      case 'D':  
      case 'E':  
      case 'F':  
       value = (value << 4) + 10 + aChar - 'A';  
       break;  
      default:  
       throw new IllegalArgumentException(  
         "Malformed      encoding.");  
      }  
     }  
     outBuffer.append((char) value);  
    } else {  
     if (aChar == 't') {  
      aChar = '\t';  
     } else if (aChar == 'r') {  
      aChar = '\r';  
     } else if (aChar == 'n') {  
      aChar = '\n';  
     } else if (aChar == 'f') {  
      aChar = '\f';  
     }  
     outBuffer.append(aChar);  
    }  
   } else {  
    outBuffer.append(aChar);  
   }  
  }  
  return outBuffer.toString();  
 }  
 // 测试  
 public static void main(String[] args) {  
  AddressUtils addressUtils = new AddressUtils();  
  // 测试ip 219.136.134.157 中国=华南=广东省=广州市=越秀区=电信  
  String ip = "125.70.11.136";  
  String address = "";  
  try {  
   address = addressUtils.getAddresses("ip="+ip, "utf-8");  
  } catch (UnsupportedEncodingException e) {  
   // TODO Auto-generated catch block  
   e.printStackTrace();  
  }  
  System.out.println(address);  
  // 输出结果为:广东省,广州市,越秀区  
 }  
 
 
}
 

根据ip地址从第三方接口获取详细的地理位置的更多相关文章

  1. 分享几个免费IP地址查询API接口

    几个免费IP地址查询API接口 1.IP地址查询接口:http://apis.juhe.cn/ip/ip2addr要先去https://www.juhe.cn/docs/api/...申请APPKEY ...

  2. #实现详细记录登陆过系统的用户,IP地址,shell命令及详细操作的时间

    //实现详细记录登陆过系统的用户,IP地址,shell命令及详细操作的时间 将下面代码加入/etc/profile //history USER_IP = who -u am i 2> /dev ...

  3. C# 设置IP地址及设置自动获取IP

    原文:C# 设置IP地址及设置自动获取IP </pre><pre name="code" class="csharp">1.添加引用&q ...

  4. linux c++ curl 根据IP地址获得当前网络的所在的地理位置

    注意: 可能每个电脑的默认中文编码格式不同,有时会出现乱码,需要对返回内容进行编码转换,或者换成可指定编码格式的接口.如  搜狐IP地址查询接口(可设置编码):http://pv.sohu.com/c ...

  5. 淘宝IP地址库API接口(PHP)通过ip获取地址信息

    淘宝IP地址库网址:http://ip.taobao.com/ 提供的服务包括: 1. 根据用户提供的IP地址,快速查询出该IP地址所在的地理信息和地理相关的信息,包括国家.省.市和运营商. 2. 用 ...

  6. php 获取客户端的真实ip地址 通过第三方网站

    <?php include 'simple_html_dom.php'; // 1获取真实IP地址方式 function get_onlineip() { $ch = curl_init('ht ...

  7. 几个免费IP地址查询API接口

    转:http://blog.csdn.net/ishxiao/article/details/52670242 -------------------------------------------- ...

  8. 七、环回接口ip地址(逻辑接口)

    loopback接口,在网络设备(一般是路由器)上是一种特殊的接口,它不是物理接口,而是一种看不见摸不着的逻辑接口(也称虚拟接口),但是对于网络设备来说却是至关重要的. 在网络设备上可以通过配置命令来 ...

  9. 输入网址调用第三方接口获取结果_java

    最近公司给了一个第三方服务的网址,要我调用后返回需要用到的信息 具体网址:http://www.xxxx.com/xxx-api/xxxx/getXxxByUserId?userId=" + ...

随机推荐

  1. 在ASP.NET MVC中使用DropDownList

    在ASP.NET MVC中,尽管我们可以直接在页面中编写HTML控件,并绑定控件的属性,但更方便的办法还是使用HtmlHelper中的辅助方法.在View中,包含一个类型为HtmlHelper的属性H ...

  2. e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (三) SqlServer数据库的访问

    上一篇文章“e2e 自动化集成测试 架构 京东 商品搜索 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step 二 图片验证码的识别” ...

  3. 特效TD 的工作准则

    特效 TD 的工作准则 作者:Hammer Chen / 转载自 http://hammerbchen.blogspot.com/2013/07/vfx-td-td.html 一直以来都想写这样的文章 ...

  4. IE兼容性问题解决方案3--css中的overflow

    overflow:hidden:IE8下没效果? width:100%;IE6.7.8下必须有宽带,而且不能是auto: weight:auto; overflow-x:scroll; overflo ...

  5. bzoj 2154 Crash的数字表格(莫比乌斯反演及优化)

    Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b)表示能同时被a和b整除的最小正整数.例如 ...

  6. 清空具有外键约束的表时报ERROR 1701(42000)的解决办法

    ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint (`furion`.`tbl_fr ...

  7. HDU-1007 Quoit Design 平面最近点对

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1007 简单裸题,测测模板,G++速度快了不少,应该是编译的时候对比C++优化了不少.. //STATU ...

  8. python的资料

    python2.7的类库:https://docs.python.org/2.7/library/index.html

  9. sts中从svn导入maven项目

    1.创建资源库 2.导入项目作为本地项目 3.将子module从本地导入(默认情况下,只会将主pom所在的工程导入)

  10. React Native学习笔记-1:JSC profiler is not supported.(转载)

    运行react-native中Example下的UIEXPLORER Project 遇到虾面报错: 2016-03-21 14:12:18.941 [trace][tid:com.facebook. ...