前言
模拟浏览器发请求有两种
第几种 | 原理 | 优点 |
---|---|---|
第一种 | HttpURLConnection 配合 流处理 | 拿状态码等头文件容易 |
第二种 | HttpGet(模拟发送) 配合 CloseableHttpResponse(处理返回值) | 解析字符串数据自动拿字符集(接口拿json用它) |
目录
第一种代码
初始化
InputStream inputStream=null;
//这个网站返回的是gbk字符集
String urladdress="http://whois.pconline.com.cn/ipJson.jsp?ip="+"117.178.141.106"+"&json=true";
String jsonStr = "";
URL url;
模拟浏览器
1.用url创建HttpURLConnection对象
2.HttpURLConnection设置头文件属性以及连接属性
3.httpConn.setDoInput(true)设置是浏览器输出数据
try
{// 获取url连接对象
url = new URL(urladdress);
//根据url创建http对象
HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
// 设置连接属性
httpConn.setConnectTimeout(3000);
httpConn.setDoInput(true);
httpConn.setRequestMethod("GET");
//設置发出与接收的字符集
// httpConn.setRequestProperty("Charsert", "UTF-8");
4.HttpURLConnection得到返回值(状态码和头文件属性和返回数据)
// 获取相应状态码
int respCode = httpConn.getResponseCode();
httpConn.getContentType(); //返回内容字符集utf-8
httpConn.getContentEncoding();//返回编码头字符集gzip
// 如果成功发200状态码
if (respCode == 200)
{
inputStream=httpConn.getInputStream();
4.对流解析这里是接口返回json数据
// ByteArrayOutputStream相当于内存输出流
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
// 将输入流转移到内存输出流中
while ((len = inputStream.read(buffer, 0, buffer.length)) != -1)
{
out.write(buffer, 0, len);
}
// 将内存流转换为字符串"GB2312"是搜狐默认的,而且HttpURLConnection接收数据的时候 字符集默认的是GBK
jsonStr=out.toString("GB2312");
// new String(out.toByteArray(),"GB2312");
}
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
第二种代码
初始化
CloseableHttpClient httpClient;
String body = null,status = null;
// 1 HttpClients是java包里的,用它创建HttpClinet,相当于打开浏览器
httpClient = HttpClients.createDefault();
//url太平洋ip接口
String url = "http://whois.pconline.com.cn/ipJson.jsp?ip="+"117.178.141.106"+"&json=true";
将url绑定到HttpGet里
1.1当无参数的绑定时
HttpGet httpGet = new HttpGet(url);
1.2当有外界传来的map参数的绑定时
map.put(“ip”,ip);
map.put(“json”,“true”);
这里的String url = “http://whois.pconline.com.cn/ipJson.jsp"
// 声明URIBuilder(动态加变量用)
URIBuilder uriBuilder = new URIBuilder(url);
//参数放map里
Map<String, Object> map = null;
// 判断参数map是否为非空
if (map != null) {
// 遍历参数
for (Map.Entry<String, Object> entry : map.entrySet()) {
// 给url上设置参数
uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
}
}
// 2 创建httpGet对象,相当于设置url请求地址(带参数的)
HttpGet httpGet = new HttpGet(uriBuilder.build());
向浏览器请求
2.CloseableHttpClient绑定HttpGet并向浏览器请求execute
// 3 使用HttpClient执行httpGet,相当于按回车,发起请求
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpGet);
} catch (IOException e) {
logger.info(e+"浏览器请求错误");
}
拿到请求返回来的结果
3.这里可以拿返回来的头文件
eg:返回来的字符集是什么
注意这里是还要用正则表达式解析数据(没写)
// todo:拿状态码(用正则)
Header[] headers= response.getHeaders("content-type");//拿头文件字符集(包状态码)
for (Header header : headers) {
header.getName(); //拿key :content-type
header.getValue(); //拿值text/html; charset=GBK
logger.info(header.toString()); //拿全部Content-Type: text/html; charset=GBK
}
对请求返回的请求体解析
注意CloseableHttpResponse.getEntity()只能用一次
3.1这一部分是对返回的结果是字符串形式的写法
//对返回数据解析
try {
if (response.getEntity() != null) {
//拿状态码
status= String.valueOf(response.getStatusLine().getStatusCode());
//请求体CloseableHttpResponse.getEntity()不能调用多次,只能调用获取一次
//这种是自动获取发的字符集在解码成字符串,如果没有获取到,在以后面的字符集解码(UTF-8与gbk都行)
body=EntityUtils.toString(response.getEntity(),"gbk");//body是String
3.2这一部分是对返回的结果是其它文件,用2进制方式(没写)或者用流读取文件
InputToString inputToString = new InputToString();//工具类
if (response.getEntity() != null) {
//拿状态码
status= String.valueOf(response.getStatusLine().getStatusCode());
//以字节方式读传来的数据
// byte[] bytes = EntityUtils.toByteArray(response.getEntity());
//这种方式是以流方式拿数据,所以用gbk解码,因为发来的数据是gbk的
InputStream in = response.getEntity().getContent();
body=inputToString.InToString(in);
工具类代码
package com.xiao.demo.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
public class InputToString{
public String InToString(InputStream inputStream) throws IOException {
String jsonStr;
// ByteArrayOutputStream相当于内存输出流
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
// 将输入流转移到内存输出流中
while ((len = inputStream.read(buffer, 0, buffer.length)) != -1) {
out.write(buffer, 0, len);
}
// 将内存流转换为字符串"GB2312"是搜狐默认的,而且HttpURLConnection接收数据的时候 字符集默认的是GBK
jsonStr = out.toString("GB2312");
out.close();
inputStream.close();
return jsonStr;
}
}
结尾
} else {
//状态码
status= String.valueOf(response.getStatusLine().getStatusCode());
}
} catch (IOException e) {
e.printStackTrace();
}
logger.info("请求体:"+body+"--状态码:"+status);
json解析器
//字符串是这样的{"地址":"内容"}
JSONObject jsonObject = JSONObject.parseObject(String类型);
//取出地址对应内容
String pro = jsonObject.getString("地址");