基于HttpClient4.5.1实现

来源:互联网 发布:手机语音助手软件 编辑:程序博客网 时间:2024/05/22 23:59

httpclient是Apache下的一个用于执行http网络访问的一个工具包。

大致流程:新建一个httpclient对象->新建一个httpRequest对象->用httpclient去执行->得到一个response->通过解析这个response来获取自己所需要的信息。

 

一、新建httpClient对象:

在httpClient4.5中,初始化的方式已经和以前版本有一些不同。

有大致以下几种方式:

Java代码  收藏代码
  1. static  CloseableHttpClient client = HttpClients.createDefault();  
  2. //最好使用static修饰,以保证用同一个client对象处理请求,以保存进度  

 

Java代码  收藏代码
  1. static CloseableHttpClient httpClient=HttpClients.custom().build();  

 此二种都是新建一个默认的httpClient对象。可以在第二种方法里添加一些网络访问选项设置。

Java代码  收藏代码
  1. /** 
  2.      * initialize a instance of the httpClient depending on your own request 
  3.      */  
  4.     private static CloseableHttpClient getInstanceClient() {  
  5.         CloseableHttpClient httpClient;  
  6.                 StandardHttpRequestRetryHandler standardHandler = new StandardHttpRequestRetryHandler(5true);  
  7.         HttpRequestRetryHandler handler = new HttpRequestRetryHandler() {  
  8.   
  9.             @Override  
  10.             public boolean retryRequest(IOException arg0, int retryTimes, HttpContext arg2) {  
  11.                 if (arg0 instanceof UnknownHostException || arg0 instanceof ConnectTimeoutException  
  12.                         || !(arg0 instanceof SSLException) || arg0 instanceof NoHttpResponseException) {  
  13.                     return true;  
  14.                 }  
  15.                 if (retryTimes > 5) {  
  16.                     return false;  
  17.                 }  
  18.                 HttpClientContext clientContext = HttpClientContext.adapt(arg2);  
  19.                 HttpRequest request = clientContext.getRequest();  
  20.                 boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);  
  21.                 if (idempotent) {  
  22.                     // 如果请求被认为是幂等的,那么就重试。即重复执行不影响程序其他效果的  
  23.                     return true;  
  24.                 }  
  25.                 return false;  
  26.             }  
  27.         };  
  28.         HttpHost proxy = new HttpHost("127.0.0.1"80);// 设置代理ip  
  29.         DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);  
  30.         httpClient = HttpClients.custom().setRoutePlanner(routePlanner).setRetryHandler(handler)  
  31.                 .setConnectionTimeToLive(1, TimeUnit.DAYS).setDefaultCookieStore(cookieStore).build();  
  32.         return httpClient;  
  33.     }  

 在该代码中分别设置了网络代理,重试处理,对于请求的keepalive时间,指定cookiestore用于保存cookie。

 

 

retryHandler:代码里给了两种方式。第一个是简便的用于设置重试,第一个参数为最大重试次数,第二个参数为请求在幂等情况下是否重试。第二种方式详细的规定了在发生了什么exception个下重试,以及幂等和重试次数下的重试情况。

routePlanner:httpClient支持代理。新建一个httphost对象传给一个routeplanner对象即可。httphost的构造方法中可以指定代理ip和端口

CookieStore:需要预先新建一个cookieStore对象。初始化方式如下:

Java代码  收藏代码
  1. CookieStore cookieStore = new BasicCookieStore();  

 

二、执行get请求:

先上代码

Java代码  收藏代码
  1. /** 
  2.      * used to get the html code from the url 
  3.      */  
  4. static RequestConfig config = RequestConfig.custom().setConnectTimeout(6000).setSocketTimeout(6000)  
  5.             .setCookieSpec(CookieSpecs.STANDARD).build(); // 设置超时及cookie策略  
  6.     public static String getDemo(String url) {  
  7.         HttpGet get = new HttpGet(url);  
  8.         get.setConfig(config);  
  9.         HttpResponse response = null;  
  10.         String html = null;  
  11.         try {  
  12.             response = client.execute(get);  
  13.             int statusCode = response.getStatusLine().getStatusCode();// 连接代码  
  14.             Header[] headers = response.getAllHeaders();  
  15.             // 用于得到返回的文件头  
  16.             for (Header header : headers) {  
  17.                 System.out.println(header);  
  18.             }  
  19.             html = new String(EntityUtils.toString(response.getEntity()).getBytes("iso8859-1"), "gb2312");  
  20.             // 在后面参数输入网站的编码,一般为utf-8  
  21.             // 返回的html代码,避免发生编码错误  
  22.             System.out.println(html);  
  23.         } catch (IOException e) {  
  24.             e.printStackTrace();  
  25.         }  
  26.         return html;  
  27.     }  

 大致流程:新建httpget对象->用httpClient执行->解析返回的response得到自己需要的内容

cookieSpec:即cookie策略。参数为cookiespecs的一些字段。作用:1、如果网站header中有set-cookie字段时,采用默认方式可能会被cookie reject,无法写入cookie。将此属性设置成CookieSpecs.STANDARD_STRICT可避免此情况。2、如果要想忽略cookie访问,则将此属性设置成CookieSpecs.IGNORE_COOKIES。

tips:注意网站编码,否则容易出现乱码

 

三、执行post请求:

Java代码  收藏代码
  1. /** 
  2.      * used to post form data which is the url needed 
  3.      */  
  4.     public static void postDemo(String url) {  
  5.         HttpPost post = new HttpPost(url);  
  6.         post.setConfig(config);  
  7.         post.setHeader("User-Agent",  
  8.                 "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36");  
  9.         post.setHeader("Connection""keep-alive");  
  10.         List<NameValuePair> list = new ArrayList<NameValuePair>();  
  11.         list.add(new BasicNameValuePair("key""value"));  
  12.         list.add(new BasicNameValuePair("key""value"));  
  13.         list.add(new BasicNameValuePair("key""value"));  
  14.         list.add(new BasicNameValuePair("key""value"));  
  15.         list.add(new BasicNameValuePair("key""value"));  
  16.         try {  
  17.             HttpEntity entity = new UrlEncodedFormEntity(list, "utf-8");  
  18.             post.setEntity(entity);  
  19.             HttpResponse response = client.execute(post);  
  20.             String responseHtml = EntityUtils.toString(response.getEntity());  
  21.             System.out.println(responseHtml);  
  22.         } catch (IOException e) {  
  23.             e.printStackTrace();  
  24.         }  
  25.     }  

 大致流程:新建post对象->新建需要的表单页->将表单内容设置入请求中->执行并获得response

 

四:解析response:

得到html code:

Java代码  收藏代码
  1. String responseHtml = EntityUtils.toString(response.getEntity());  

 得到http状态码:

Java代码  收藏代码
  1. int statusCode = response.getStatusLine().getStatusCode();// 连接代码  

 得到response header:

Java代码  收藏代码
  1. response.getFirstHeader("key");// 得到第一个名字为key的header  
  2.             response.getHeaders("key");// 得到名字为key的所有header,返回一个数组  
  3.             response.getLastHeader("key");  

 

得到inputstream:(下载网络部分资源的时候有可能会对cookie有要求,此时需要用到httpClient来下载。)例如验证码等等。

 

Java代码  收藏代码
  1. InputStream inputStream = response.getEntity().getContent();  
 

 

五:管理cookie:

httpClient里默认自动管理cookie,如果想要提取cookie或者发送自定义的cookie,则需要在httpClient对象初始化时设置一个默认的cookiestore来保存。(方法见初始化httpClient对象里的setDefaultCookieStore)。

得到当前所有cookie:

 

Java代码  收藏代码
  1. List<Cookie> list = cookieStore.getCookies();// get all cookies  
  2.         System.out.println("cookie is:");  
  3.         System.out.println("-----------------------");  
  4.         for (Cookie cookie : list) {  
  5.             System.out.println(cookie);  
  6.         }  
  7.         System.out.println("-----------------------");  
 清除所有cookie:

 

 

Java代码  收藏代码
  1. cookieStore.clear();  
 发送自定义cookie:(new了一个对象之后可以设置多种属性。)

 

 

Java代码  收藏代码
  1. BasicClientCookie cookie = new BasicClientCookie("name""value");  
  2.         // new a cookie  
  3.         cookie.setDomain("domain");  
  4.         cookie.setExpiryDate(new Date());  
  5.         // set the properties of the cookie  
  6.                 cookieStore.addCookie(cookie);  
 最后通过按得到addCookie将其加入cookieStore。(如有相同的name的cookie将会覆盖,个人觉得类似hashmap的put操作。)

 

 

六:管理header:

在平常抓取过程中,经常需要在请求中加入许多header伪装成一个正常的浏览器。以免被服务器认出是爬虫而被封。

设置一些常见header:

Java代码  收藏代码
  1. post.setHeader("User-Agent",  
  2.                 "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36");  
  3.         post.setHeader("Connection""keep-alive");  

注意:下载某些网站的资源时,服务器会获取你的来源站,并发出对应的相应。如果来源站不对,可能会被服务器拒绝。此时只需要在请求中加个header就行。

Java代码  收藏代码
  1. get1.setHeader("Referer""http://www.a.com");  

  

 

ps:

1、爬虫也要遵守基本法,在多次请求的之中为了不给对方服务器造成负担(避免被封),尽量在请求间sleep一个随机数值。

2、爬取非英文网站时注意编码格式,国内一般为utf-8,也有一些是gb2312.获取时注意转码。

3、多获得一些可靠IP(备胎),一旦自身ip被封,赶快去找备胎。附带一个简单的判断网站是否需要代理方法:

Java代码  收藏代码
  1. // 判断访问目标网站是否需要代理  
  2.     private boolean isNeedProxy() {  
  3.         boolean result = true;  
  4.         URL url;  
  5.         try {  
  6.             url = new URL("http://apkpure.com/");  
  7.             HttpURLConnection connection = (HttpURLConnection) url.openConnection();  
  8.             connection.setConnectTimeout(6000);  
  9.             // int i = connection.getResponseCode();  
  10.             int i = connection.getContentLength();  
  11.             if (i > 0) {  
  12.                 result = false;  
  13.             }  
  14.         } catch (IOException e) {  
  15.             e.printStackTrace();  
  16.         }  
  17.         return result;  
  18.     } 
原创粉丝点击