HttpUtils的封装
通过对HttpUtils的封装,可以很方便的调用方法获取网页信息,但封装HttpUtils并不与HttpClients的编写完全相同,在以下方面尤其需要注意:
- 这个工具我们希望可以直接使用,而不是通过创建对象的方式,所以要设置为abstract(不可以新建对象),将方法设置为静态方法以直接调用。
- 如果每次都在方法中声称对象,每次调用方法都会创建一次,造成了资源浪费,所以要在类中对对象做出声明,当加载类时对象就被创建好。
- /包装为工具类时异常不能随便抛出,调用方会不方便使用,所以要进行try catch。
package l.gy.util;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/* 封装HttpClient工具,方便爬取网页内容
这个工具我们希望可以直接使用,而不是通过创建对象的方式,所以要设置为abstract(不可以新建对象),将方法设置为静态方法以直接调用
如果每次都在方法中声称对象,每次调用方法都会创建一次,造成了资源浪费,
所以要在类中对对象做出声明,当加载类时对象就被创建好
*/
public class HttpUtils {
private static PoolingHttpClientConnectionManager cm;//声明HttpClient管理器对象,即连接池
private static List<String> userAgentList = null;//存放请求头
private static RequestConfig config = null;//请求的配置信息
//静态代码块在类加载的时候就会被执行
//在里面对成员变量进行初始化
static{
cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
config = RequestConfig.custom()
.setSocketTimeout(10000)
.setConnectTimeout(10000)
.setConnectionRequestTimeout(10000)
.build();
userAgentList = new ArrayList<String>();
userAgentList.add("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36");
userAgentList.add("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:73.0) Gecko/20100101 Firefox/73.0");
userAgentList.add("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15");
userAgentList.add("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299");
userAgentList.add("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36");
userAgentList.add("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0");
//爬虫每次访问时会从中随机选择一个,避免ip被封
}
public static String getHtml(String url){
//1.从连接池中获取HttpClient对象
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
//2.创建HttpGet对象
HttpGet httpGet = new HttpGet(url);
//3.设置请求配置对象和请求头
httpGet.setConfig(config);
httpGet.setHeader("User-Agent",userAgentList.get(new Random().nextInt(userAgentList.size())));
//4.发起请求
CloseableHttpResponse response = null;//因为最终response需要关闭最后还要添加一个finally,如果要关闭的话,声明还是在try内部就访问不到了,所以提前了。
try {
response = httpClient.execute(httpGet);
//5.获取响应内容
if(response.getStatusLine().getStatusCode() == 200){
String html = "";
if(response.getEntity() != null){
html = EntityUtils.toString(response.getEntity(), "UTF-8");
}
return html;
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
response.close();
//注意:这里的HttpClient是从cm(连接池)中获取的,不需要关闭,还会还回的到池中
} catch (IOException e) {
e.printStackTrace();
}
}
//包装为工具类时异常不能随便抛出,调用方会不方便使用,所以要进行try catch
return null;
}
public static void main(String[] args) {
String html = HttpUtils.getHtml("http://www.itcast.com");
System.out.println(html);
}
}