尝试多个查询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;
}
}