httpclient的使用&htmlcleaner的使用

 httpclient :-------------------

今天說:httpclient,他是apache下的, 目前用它採集同步網站, 

那麼首先看這個代碼之前,一定要先對request response 有所瞭解,這樣可以更好懂一些,httpclient是對網絡編程 也就是net包下的封裝,因爲URLConnection類 ,雖然也可以採集到東西,但是畢竟是原生的, 我先把異常拋出到main上 ,這樣代碼少一些

一會什麼簡介啦,ppt和我們老師上的視頻都有的

 

一會我把所需要的jar包,放到百度網盤中 ,當然 可以添加maven依賴

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.2</version>
</dependency>

 

 

//@Test
    public void fun() throws Exception{
        CloseableHttpClient httpClient = HttpClients.createDefault(); //創建實例對象
        HttpGet httpGet = new HttpGet("https://www.tinaya.com/"); //這裏面放需要鏈接的地址即可
        httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36"); //爲什麼這裏要設置請求頭?

因爲某些網站,是有反爬蟲措施的, 這麼設置,只是爲了模擬人的操作而已,不然有可能封你的ip地址

/*
         得到response之後,我們就需要對response進行解析了
         */
        CloseableHttpResponse response = httpClient.execute(httpGet); ///執行http協議的get請求
        HttpEntity entity = response.getEntity(); //得到實體
        System.out.println("網頁源碼如下:");
        String src = EntityUtils.toString(entity, "utf-8"); //以什麼形式看源碼?? 一般的網頁在meta標籤中都有一個content-type請求頭,與那個對應即可
        System.out.println(src);
        //關流
        response.close();
        httpClient.close();
    }

/*
     爲什麼要得到content-type?
    
     根據具體的MIME類型 ,來過濾
    
     爲什麼要得到狀態碼?
     因爲200代表 成功, 404代表找不到,
     如果不是200,那麼下面的爬蟲代碼就不需要執行了
     */

//得到此頁面的MIME類型
        String value = entity.getContentType().getValue();
        System.out.println(value); //輸出content-type的值
        
        //得到此頁面的狀態碼
        StatusLine line = response.getStatusLine();
        System.out.println(line);//HTTP/1.1 200 OK 這個是把那一條信息都返回回來了
        //但是我們一般只需要狀態碼,用它判斷即可
        int code = line.getStatusCode();
        System.out.println(code);

 

 

2  HttpClient 抓取圖片:

public void fun() throws Exception{
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet("http://xxxx/gg/sxt2.gif"); //只不過改爲了圖片地址而已
        httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36");
        CloseableHttpResponse response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        if(entity!=null){
            System.out.println(entity.getContentType().getValue());
            InputStream input = entity.getContent();//以流的形式(因爲照片是字節,當然以流的形式傳輸和寫入)
            FileUtils.copyInputStreamToFile(input, new File("C:\\sxt.gif"));//這時你看,我保存的時候怎麼知道文件是什麼後綴,我可以上面寫一個String imageHref  變量, 因爲我知道我傳入的圖片路徑 而路徑中有名字,截取一下即可

這個方法是Commons.io包中的一個方法而已
      
        }

 

 

設置代理ip

在爬取網頁的時候,有的目標站點有反爬蟲機制,對於頻繁訪問站點以及規則性訪問站點的行爲,會採集屏蔽IP措施。

 

這時候,代理IP就派上用場了。

 

關於代理IP的話 也分幾種 透明代理、匿名代理、混淆代理、高匿代理

透明代理:雖然透明代理可以直接“隱藏”你的IP地址,但是還是可以查到你是誰

匿名代理比透明代理進步了一點:別人只能知道你用了代理,無法知道你是誰。

混淆代理,別人還是能知道你在用代理,但是會得到一個假的IP地址,僞裝的更逼真:

高匿代理讓別人根本無法發現你是在用代理,所以是最好的選擇。我們使用的是高匿代理,

 

代理IP 從哪裏搞呢 很簡單  百度一下,你就知道 一大堆代理IP站點。  一般都會給出一些免費的,

 

     CloseableHttpClient httpClient=HttpClients.createDefault(); // 創建httpClient實例

        HttpGet httpGet=new HttpGet("https://www.taobao.com/"); // 創建httpget實例

        HttpHost proxy=new HttpHost("116.226.217.54"9999); //用來設置代理ip

/*

       這個類位於 org.apache.http.client.config包下,主要用於獲取和配置一些外部的網絡環境,它下面有一個嵌套類 RequestConfig.Builder

使用方法是:先用 RequestConfig類的靜態方法custom()獲取requestConfig.Builder“配置器”,然後再用其下各種方法配置網絡環境;

 

*/

        RequestConfig requestConfig=RequestConfig.custom().setProxy(proxy).build();

        httpGet.setConfig(requestConfig);

        httpGet.setHeader("User-Agent""Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");

        CloseableHttpResponse response=httpClient.execute(httpGet); // 執行http get請求

        HttpEntity entity=response.getEntity(); // 獲取返回實體

        System.out.println("網頁內容:"+EntityUtils.toString(entity, "utf-8")); // 獲取網頁內容

        response.close(); // response關閉

        httpClient.close(); // httpClient關閉

 

 

  一般如果是你如果採集網站遇到403 ,那麼可能就是被屏蔽了,這時你就應該換一個代理ip了
     思路:
     先做一個小爬蟲,專門去 這些免費代理ip網站,得到 這ip和端口這兩個數據
     把代理ip和 端口 放到一個map中(隊列中) 也可以
     加一個判斷,如果是403,取出下一個map的鍵值對並且移除掉這個ip
     然後那麼就會一直取,一直移除,再加一個判斷,如果ip不夠的時候,繼續運作爬蟲,爬取ip

 

httpClient在執行具體http請求時候 有一個連接的時間和讀取內容的時間;

 

所謂連接的時候 是HttpClient發送請求的地方開始到連接上目標url主機地址的時間,

線路越通暢越快,但是由於路由複雜交錯,往往連接上的時間都不固定,運氣不好連不上,HttpClient的默認連接時間,

默認是1分鐘,假如超過1分鐘 過一會繼續嘗試連接,這樣會有一個問題 假如遇到一個url老是連不上,會影響其他線程的線程進去,所以我們有必要進行特殊設置,比如設置10秒鐘 假如10秒鐘沒有連接上 我們就報錯,這樣我們就可以進行業務上的處理,

比如我們業務上控制 過會再連接試試看。並且這個特殊url寫到log4j日誌裏去。方便管理員查看。

ttpClient讀取時間

所謂讀取的時間 是HttpClient已經連接到了目標服務器,然後進行內容數據的獲取,一般情況 讀取數據都是很快速的,

但是假如讀取的數據量大,或者是目標服務器本身的問題(比如讀取數據庫速度慢,併發量大等等..)也會影響讀取時間。

同上,我們還是需要來特殊設置下,比如設置10秒鐘 假如10秒鐘還沒讀取完,就報錯,同上,我們可以業務上處理。

 

   如果連接超時 ,報的是connect  timed out
   如果讀取超時 ,報的是read timed out

 

CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet("https://www.tuicool.com/");
        
        
        RequestConfig config = RequestConfig.custom()
                            .setConnectTimeout(10000)//設置連接超時時間
                            .setSocketTimeout(10000)//設置讀取超時時間
                            .build();

        httpGet.setConfig(config);
        httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36");
        CloseableHttpResponse response = httpClient.execute(httpGet);
        HttpEntity entity = response.getEntity();
        System.out.println("網頁源碼如下:");
        String src = EntityUtils.toString(entity, "utf-8");
        System.out.println(src);
        //關流
        response.close();
        httpClient.close();

 

/=====================================================

其實httpclient能做很多的事情,但是我們目前用它做這麼多就可以,做別的喲也有別的比他做得更好,

以後你們會知道的

當解析到源碼之後呢? 我們是不是就可以解析其中的內容了呢? 當然可以

但是你考慮過嗎? 某些網站的前臺人員代碼寫的不好,那麼就有可能會出現,標籤不能成對出現或者短標籤的情況

這是htmlcleaner 或者htmlparser 登場了

個人推薦用htmlcleaner,更好用一點

HtmlCleaner clean = new HtmlCleaner();
        TagNode tagNode = clean.clean(src); //就是這麼用

 

他其中支持xpath ,我們可以用他解析內容

//標題
           Object[] titles = tagNode.evaluateXPath("xpath表達式");

 

然後獲取就行了

 

htmlcleaner還可以將源碼轉換成dom樹 我們就可以用dom4j  來解析了,但是還是有點麻煩呀,因爲它自帶xpath了,何必再new一個xpathFacotry呢?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章