用HttpUrlConnection抓取網頁內容

由於項目需求,需要採集一些網站的內容。在JAVA領域中,已經存在很多良好的框架用於該應用,如httpclient,webharvest還有更多強大的框架。但由於本身項目比較單純,且爲了良好的自我控制,就決定直接用JDK中的HttpUrlConnection類來抓取網頁內容。並不是說那些框架不好,而只是不適用本項目。

說明:本博的一切內容均可轉載,但必須注意出處。http://www.lelelog.com(樂樂日誌)

一、HttpUrlConnection連接之模擬瀏覽器

在諸多的網站中,特別是大型的網站,設置了必須是瀏覽器的請求才會迴應。之所以這樣設置,就是爲了防止我們這種項目給他產生無意義的請求(往往這種請求都是大批量,對其服務器產生負荷)。那爲了解決這個問題,我們需要在http請求中,添加屬性。

HttpURLConnection urlConn;

urlConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)");

這樣就設置好了,你可以隨意設置你的操作系統值,瀏覽器值,版本,只要正確就OK了。這樣就可以正常有效地訪問其網站了。他可不知道你是不是瀏覽器。你即使是條狗,他也不知道。

 

二、完整的設置HttpUrlConnection的屬性值

HttpURLConnection urlConn;

urlConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)");
        urlConn.setRequestProperty("Accept",
                "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*");
        urlConn.setRequestProperty("Accept-Language", "zh-cn");
        urlConn.setRequestProperty("UA-CPU", "x86");
        urlConn.setRequestProperty("Accept-Encoding", "gzip");//爲什麼沒有deflate呢
        urlConn.setRequestProperty("Content-type", "text/html");
        urlConn.setRequestProperty("Connection", "close"); //keep-Alive,有什麼用呢,你不是在訪問網站,你是在採集。嘿嘿。減輕別人的壓力,也是減輕自己。

        urlConn.setUseCaches(false);//不要用cache,用了也沒有什麼用,因爲我們不會經常對一個鏈接頻繁訪問。(針對程序)
        urlConn.setConnectTimeout(6 * 1000);
        urlConn.setReadTimeout(6*1000);
        urlConn.setDoOutput(true);
        urlConn.setDoInput(true);

有什麼疑問的話,可以查看JDK的API文檔,這個可以實時看。至於爲什麼要設置 gzip,而又不設置deflate,原因如下,有些網站他不管你能接受什麼壓縮格式,統統也會壓縮網頁內容傳給你。當然IE,FF能處理好這些內容。所以我們通過瀏覽器查看的時候完全正常。一般gzip的壓縮可以將一個33K的文件壓縮成7K,這樣會節約不少帶寬,但服務器的負荷並沒有減輕,因爲他要壓縮文件呀。至於爲什麼不用deflate,是由於絕大多數網站的壓縮方式是用gzip,而在有些網站中,明明是用的gzip卻返回deflate的壓縮標識。這有什麼意義呢,所以乾脆就告訴服務器,我不接受deflate,因爲他太醜了,又長,哪像gzip這麼潮呀。呵呵,對於瀏覽量大的靜態網頁服務器,這樣做很是必要。100M的獨享服務器,他也只有100M呀。

三、開始採集某個網頁的內容

該方法就是傳入一個HttpUrlConnection的鏈接,和該文件的字符集編碼,就可以返回其網頁內容了。

public static String getContentFromIn(HttpURLConnection urlConn, String charset) {
        BufferedReader br = null;
        StringBuilder content = new StringBuilder(200);
        InputStream in = null;
        try {
            if(null == urlConn){
                return "";
            }            
            if (StringTools.isNotEmpty(urlConn.getContentEncoding())) {
                String encode = urlConn.getContentEncoding().toLowerCase();
                if (StringTools.isNotEmpty(encode) && encode.indexOf("gzip") >= 0) {
                    in = new GZIPInputStream(urlConn.getInputStream());                    
                }
            }

            if (null == in) {
                in = urlConn.getInputStream();
            }
            if (null != in) {
                br = new BufferedReader(new InputStreamReader(in, charset));
                String line = "";
                while ((line = br.readLine()) != null) {
                    content.append(line);
                }
            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                in = null;
            }
            if (null != br) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                in = null;
            }
        }
        return content.toString();
    }

至此一個簡單的採集工具類誕生了,他的優美在於,代碼少,不用引入任何包。純JDK,一樣能幹許多事。有時不希望把本來簡單的事情搞得複雜化。雖然不要創造重複的輪子,但我們不能純拿來主義,就像這樣一個簡單的功能,不需要搞得太複雜。只要不DRY就可以了,這樣自己也能一點點地進步。

以上有什麼錯誤,還請包涵

發佈了6 篇原創文章 · 獲贊 5 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章