前言
其實前面寫的那一點點東西都是輕輕點水,其實HttpClient還有很多強大的功能:
一、HttpClient使用代理IP
1.1、前言
在爬取網頁的時候,有的目標站點有反爬蟲機制,對於頻繁訪問站點以及規則性訪問站點的行為,會采集屏蔽IP措施。
這時候,代理IP就派上用場了。可以使用代理IP,屏蔽一個就換一個IP。
關於代理IP的話 也分幾種 透明代理、匿名代理、混淆代理、高匿代理,一般使用高匿代理。
1.2、幾種代理IP
1)透明代理(Transparent Proxy)
REMOTE_ADDR = Proxy IP
HTTP_VIA = Proxy IP
HTTP_X_FORWARDED_FOR = Your IP
透明代理雖然可以直接“隱藏”你的IP地址,但是還是可以從HTTP_X_FORWARDED_FOR來查到你是誰。
2)匿名代理(Anonymous Proxy)
REMOTE_ADDR = proxy IP
HTTP_VIA = proxy IP
HTTP_X_FORWARDED_FOR = proxy IP
匿名代理比透明代理進步了一點:別人只能知道你用了代理,無法知道你是誰。
還有一種比純匿名代理更先進一點的:混淆代理
3)混淆代理(Distorting Proxies)
REMOTE_ADDR = Proxy IP
HTTP_VIA = Proxy IP
HTTP_X_FORWARDED_FOR = Random IP address
如上,與匿名代理相同,如果使用了混淆代理,別人還是能知道你在用代理,但是會得到一個假的IP地址,偽裝的更逼真。
4)高匿代理(Elite proxy或High Anonymity Proxy)
REMOTE_ADDR = Proxy IP
HTTP_VIA = not determined
HTTP_X_FORWARDED_FOR = not determined
可以看出來,高匿代理讓別人根本無法發現你是在用代理,所以是最好的選擇。
一般我們搞爬蟲 用的都是 高匿的代理IP;
那代理IP 從哪里搞呢 很簡單 百度一下,你就知道 一大堆代理IP站點。 一般都會給出一些免費的,但是花點錢搞收費接口更加方便。
1.3、實例來使用代理Ip
使用 RequestConfig.custom().setProxy(proxy).build() 來設置代理IP
package com.jxlg.study.httpclient; import com.sun.org.apache.regexp.internal.RE; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; 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.util.EntityUtils; import java.io.IOException; public class UseProxy { public static void main(String[] args) throws IOException { //創建httpClient實例 CloseableHttpClient httpClient = HttpClients.createDefault(); //創建httpGet實例 HttpGet httpGet = new HttpGet("http://www.tuicool.com"); //設置代理IP,設置連接超時時間 、 設置 請求讀取數據的超時時間 、 設置從connect Manager獲取Connection超時時間、 HttpHost proxy = new HttpHost("58.60.255.82",8118); RequestConfig requestConfig = RequestConfig.custom() .setProxy(proxy) .setConnectTimeout(10000) .setSocketTimeout(10000) .setConnectionRequestTimeout(3000) .build(); httpGet.setConfig(requestConfig); //設置請求頭消息 httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"); CloseableHttpResponse response = httpClient.execute(httpGet); if (response != null){ HttpEntity entity = response.getEntity(); //獲取返回實體 if (entity != null){ System.out.println("網頁內容為:"+ EntityUtils.toString(entity,"utf-8")); } } if (response != null){ response.close(); } if (httpClient != null){ httpClient.close(); } } }
1.4、實際開發中怎么去獲取代理ip
我們可以使用HttpClient來 爬取 http://www.xicidaili.com/ 上最新的20條的高匿代理IP,來保存到 鏈表中,當一個IP被屏蔽之后獲取連接超時時,
就接着取出 鏈表中的一個IP,以此類推,可以判斷當鏈表中的數量小於5的時候,就重新爬取 代理IP 來保存到鏈表中。
1.5、HttpClient連接超時及讀取超時
httpClient在執行具體http請求時候 有一個連接的時間和讀取內容的時間;
1)HttpClient連接時間
所謂連接的時候 是HttpClient發送請求的地方開始到連接上目標url主機地址的時間,理論上是距離越短越快,
線路越通暢越快,但是由於路由復雜交錯,往往連接上的時間都不固定,運氣不好連不上,HttpClient的默認連接時間,據我測試,
默認是1分鍾,假如超過1分鍾 過一會繼續嘗試連接,這樣會有一個問題 假如遇到一個url老是連不上,會影響其他線程的線程進去,說難聽點,
就是蹲着茅坑不拉屎。所以我們有必要進行特殊設置,比如設置10秒鍾 假如10秒鍾沒有連接上 我們就報錯,這樣我們就可以進行業務上的處理,
比如我們業務上控制 過會再連接試試看。並且這個特殊url寫到log4j日志里去。方便管理員查看。
2)HttpClient讀取時間
所謂讀取的時間 是HttpClient已經連接到了目標服務器,然后進行內容數據的獲取,一般情況 讀取數據都是很快速的,
但是假如讀取的數據量大,或者是目標服務器本身的問題(比如讀取數據庫速度慢,並發量大等等..)也會影響讀取時間。
同上,我們還是需要來特殊設置下,比如設置10秒鍾 假如10秒鍾還沒讀取完,就報錯,同上,我們可以業務上處理。
比如我們這里給個地址 http://central.maven.org/maven2/,這個是國外地址 連接時間比較長的,而且讀取的內容多 。很容易出現連接超時和讀取超時。
我們如何用代碼實現呢?
HttpClient給我們提供了一個RequestConfig類 專門用於配置參數比如連接時間,讀取時間以及前面講解的代理IP等。
例子:
package com.jxlg.study.httpclient; import org.apache.http.HttpEntity; 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.util.EntityUtils; import java.io.IOException; public class TimeSetting { public static void main(String[] args) throws IOException { CloseableHttpClient httpClient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet("http://central.maven.org/maven2/"); RequestConfig config = RequestConfig.custom() .setConnectTimeout(5000) .setSocketTimeout(5000) .build(); httpGet.setConfig(config); httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"); CloseableHttpResponse response = httpClient.execute(httpGet); if (response != null){ HttpEntity entity = response.getEntity(); System.out.println("網頁內容為:"+ EntityUtils.toString(entity,"UTF-8")); } if (response != null){ response.close(); } if (httpClient != null){ httpClient.close(); } } }