最近項目某個功能需要根據ip地址從第三方接口獲取詳細的地理位置,從網上找了很多例子,主要接口有新浪的,淘寶的,騰訊的。試了淘寶的,如果是數量級小的還可以,如果數量級達到上十萬級就速度慢了,會導致系統崩潰。下面例子是新浪的,例子不是適合每個項目,需要改一下.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
/** 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不一樣。我不知道怎么解決。有大神知道回我一下。
下面是用淘寶的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
|
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); // 輸出結果為:廣東省,廣州市,越秀區 } } |