嘗試多個查詢ip地理位置的api
首先看代碼:
public static void main(String[] args) throws UnsupportedEncodingException {
long l = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
System.out.println(getIpLocation("114.114.114.114"));
}
long l1 = System.currentTimeMillis();
System.out.println("總耗時: "+(l1-l) + "ms");
}
public static String getIpLocation(String ip) {
//只能支持少量低頻次調用,做了限流,循環100條只有前6次成功,後面都是限流失敗,4631ms
String taobaoApi = "http://ip.taobao.com/service/getIpInfo.php?ip="+ip;
//已經關閉
String sinaApi = "http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip="+ip;
//需要ak參數(註冊賬號),有併發限制,100條6357ms,普通已認證開發者賬號1天3w請求,未認證1天1k,限流1秒10次,網址 http://lbsyun.baidu.com/apiconsole/auth/privilege
//並且返回的中文是unicode編碼,很坑
String baiduApi = "http://api.map.baidu.com/location/ip?ak=xxxxxxx&ip="+ip;
//返回頁面
String pconlineApi = "https://whois.pconline.com.cn/?ip="+ip;
//速度尚可 100條4521ms
String ws126Api = "http://ip.ws.126.net/ipquery?ip="+ip;
//速度很慢,一個月免費3w條,100條24808ms,apiKey需要註冊賬號
String geoApi = "https://api.ipgeolocation.io/ipgeo?apiKey=xxxxxxx&ip="+ip;
//速度很慢,100條79133ms
String ip_Api = "http://ip-api.com/json/?ip="+ip;
//一個月3w條免費, 100條耗時 37394ms
String ipapi = "https://ipapi.co/"+ip+"/json";
HttpResult httpResult = HttpClientUtil.get(baiduApi);
if (HttpClientUtil.is200OK(httpResult)){
return httpResult.getRespStr();
}
return "無法確定";
}
其中嘗試了好幾種api,包括淘寶的,新浪的,百度的,以及國外的。(國外的返回的地址是拼音,準確的說是地址的英文)
其中大多都有併發限制和額度限制。而且返回速度有快有慢,我以100條測試,基本最快也要5秒,最慢可達1分鐘。
其中有一些比較坑,比如淘寶的api,使用瀏覽器和postman都可以正常調用,但是使用HttpClient就返回不了數據,後面發現需要將User-Agent 改爲postman或者chrome, 讓淘寶api以爲你是頁面調用的。默認HttpClient的User-Agent是Apache-HttpClient/4.5.10 (Java/1.8.0_181)
最後附上HttpClientUtil的代碼:
package com.zgd.base.spring.util.http;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.models.Scheme;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.http.MediaType;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
/**
* HttpClientUtil
*
* @author zgd
* @date 2019/8/13 15:46
*/
@Slf4j
public class HttpClientUtil {
private static HttpClient httpClient;
public static HttpResult get(String url) {
return get(url, null);
}
static {
getHttpClient();
}
/**
* 發起get請求
*
* @return java.lang.String
* @author zgd
* @date 2019/8/13 15:52
*/
public static HttpResult get(String url, List<NameValuePair> params) {
HttpGet get = null;
try {
URIBuilder uriBuilder = new URIBuilder(url);
uriBuilder.setCharset(StandardCharsets.UTF_8);
if (CollectionUtils.isNotEmpty(params)) {
uriBuilder.setParameters(params);
}
get = new HttpGet(uriBuilder.build());
log.info("請求的參數 url: {}\treq: {}", get.getURI(), params);
HttpResponse response = httpClient.execute(get);
String resp = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
int code = response.getStatusLine().getStatusCode();
log.info("返回的信息 resp: {}", resp);
return new HttpResult(code, resp);
} catch (Exception e) {
log.warn("請求異常 -- error!", e);
} finally {
if (get != null) {
get.releaseConnection();
}
}
return null;
}
/**
* 發送POST請求(普通表單形式)
*
* @return java.lang.String
* @author zgd
* @date 2019/8/13 15:56
*/
public static HttpResult postForm(String url, HashMap<String, String> form) {
List<BasicNameValuePair> params = form.entrySet().stream().map(en -> new BasicNameValuePair(en.getKey(), en.getValue()))
.collect(Collectors.toList());
HttpEntity entity = new UrlEncodedFormEntity(params, StandardCharsets.UTF_8);
return postRequest(url, MediaType.APPLICATION_FORM_URLENCODED_VALUE, entity);
}
/**
* 發送POST請求(JSON形式)
*
* @return java.lang.String
* @author zgd
* @date 2019/8/13 15:56
*/
public static HttpResult postJSON(String url, String json) {
StringEntity entity = new StringEntity(json, StandardCharsets.UTF_8);
return postRequest(url, MediaType.APPLICATION_JSON_VALUE, entity);
}
/**
* 發送post請求
*
* @param url
* @param mediaType
* @param entity
* @return
*/
public static HttpResult postRequest(String url, String mediaType, HttpEntity entity) {
log.info("[postRequest] resourceUrl: {}", url);
HttpPost post = null;
try {
URIBuilder uriBuilder = new URIBuilder(url);
post = new HttpPost(uriBuilder.build());
post.addHeader(HttpHeaders.CONTENT_TYPE, mediaType);
post.setEntity(entity);
HttpResponse response = httpClient.execute(post);
String resp = EntityUtils.toString(response.getEntity());
int code = response.getStatusLine().getStatusCode();
log.info("返回的信息 resp:{}", resp);
return new HttpResult(code, resp);
} catch (Exception e) {
log.warn("請求異常 -- error!", e);
} finally {
if (post != null) {
post.releaseConnection();
}
}
return null;
}
public static boolean is200OK(HttpResult result) {
return result != null && result.getCode() == HttpStatus.SC_OK;
}
public static String getValue(HttpResult result, String key) {
if (is200OK(result)) {
try {
JSONObject jsonObject = JSON.parseObject(result.getRespStr());
return jsonObject.getString(key);
} catch (Exception e) {
log.warn("解析失敗 ", e);
}
}
return null;
}
/**
* 獲取默認的httpClient
*
* @return
*/
public static HttpClient getHttpClient() {
if (httpClient == null) {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(3000)
.setConnectionRequestTimeout(3000)
.setSocketTimeout(5000).build();
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig)
.setMaxConnTotal(1000)
.setMaxConnPerRoute(100)
.setDefaultHeaders(getDefaultHeaders())
.build();
}
return httpClient;
}
/**
* 設置默認的請求頭
*
* @return
*/
public static List<Header> getDefaultHeaders() {
List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36"));
headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
headers.add(new BasicHeader("Accept-Language", "zh-CN"));
headers.add(new BasicHeader("Connection", "Keep-Alive"));
headers.add(new BasicHeader("Accept", "*/*"));
return headers;
}
}