zoukankan      html  css  js  c++  java
  • 根据ip地址从第三方接口获取详细的地理位置

    最近项目某个功能需要根据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 = ' ';  
         } else if (aChar == 'r') {  
          aChar = ' ';  
         } else if (aChar == 'n') {  
          aChar = ' ';  
         } 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);  
      // 输出结果为:广东省,广州市,越秀区  
     }  
     
     
    }
     
  • 相关阅读:
    思维发散的双刃剑
    一个请求过来都经过了什么?(Thrift版)
    业务开发转基础开发,这三种「高可用」架构你会么?
    程序常用的设计技巧
    美团分布式服务通信框架及服务治理系统OCTO
    《程序员修炼之道》解读
    面试官说:你真的不是不优秀只是不合适
    架构视角-文件的通用存储原理
    那些影响深远的弯路
    iOS sqlite ORM框架-LKDBHelper
  • 原文地址:https://www.cnblogs.com/izecsonLee/p/5271084.html
Copyright © 2011-2022 走看看