小心別讓日子把你給混了

          光榮在于平淡...艱巨在于漫長(zhǎng)...
          posts - 26, comments - 7, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          由于項(xiàng)目需求,需要采集一些網(wǎng)站的內(nèi)容。在JAVA領(lǐng)域中,已經(jīng)存在很多良好的框架用于該應(yīng)用,如httpclient,webharvest還有更多強(qiáng)大的框架。但由于本身項(xiàng)目比較單純,且為了良好的自我控制,就決定直接用JDK中的HttpUrlConnection類來抓取網(wǎng)頁內(nèi)容。并不是說那些框架不好,而只是不適用本項(xiàng)目。

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

          一、HttpUrlConnection連接之模擬瀏覽器

          在諸多的網(wǎng)站中,特別是大型的網(wǎng)站,設(shè)置了必須是瀏覽器的請(qǐng)求才會(huì)回應(yīng)。之所以這樣設(shè)置,就是為了防止我們這種項(xiàng)目給他產(chǎn)生無意義的請(qǐng)求(往往這種請(qǐng)求都是大批量,對(duì)其服務(wù)器產(chǎn)生負(fù)荷)。那為了解決這個(gè)問題,我們需要在http請(qǐng)求中,添加屬性。

          HttpURLConnection urlConn;

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

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

           

          二、完整的設(shè)置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,有什么用呢,你不是在訪問網(wǎng)站,你是在采集。嘿嘿。減輕別人的壓力,也是減輕自己。

                  urlConn.setUseCaches(false);//不要用cache,用了也沒有什么用,因?yàn)槲覀儾粫?huì)經(jīng)常對(duì)一個(gè)鏈接頻繁訪問。(針對(duì)程序)
                  urlConn.setConnectTimeout(6 * 1000);
                  urlConn.setReadTimeout(6*1000);
                  urlConn.setDoOutput(true);
                  urlConn.setDoInput(true);

          有什么疑問的話,可以查看JDK的API文檔,這個(gè)可以實(shí)時(shí)看。至于為什么要設(shè)置 gzip,而又不設(shè)置deflate,原因如下,有些網(wǎng)站他不管你能接受什么壓縮格式,統(tǒng)統(tǒng)也會(huì)壓縮網(wǎng)頁內(nèi)容傳給你。當(dāng)然IE,F(xiàn)F能處理好這些內(nèi)容。所以我們通過瀏覽器查看的時(shí)候完全正常。一般gzip的壓縮可以將一個(gè)33K的文件壓縮成7K,這樣會(huì)節(jié)約不少帶寬,但服務(wù)器的負(fù)荷并沒有減輕,因?yàn)樗獕嚎s文件呀。至于為什么不用deflate,是由于絕大多數(shù)網(wǎng)站的壓縮方式是用gzip,而在有些網(wǎng)站中,明明是用的gzip卻返回deflate的壓縮標(biāo)識(shí)。這有什么意義呢,所以干脆就告訴服務(wù)器,我不接受deflate,因?yàn)樗罅耍珠L(zhǎng),哪像gzip這么潮呀。呵呵,對(duì)于瀏覽量大的靜態(tài)網(wǎng)頁服務(wù)器,這樣做很是必要。100M的獨(dú)享服務(wù)器,他也只有100M呀。

          三、開始采集某個(gè)網(wǎng)頁的內(nèi)容

          該方法就是傳入一個(gè)HttpUrlConnection的鏈接,和該文件的字符集編碼,就可以返回其網(wǎng)頁內(nèi)容了。

          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();
              }

          至此一個(gè)簡(jiǎn)單的采集工具類誕生了,他的優(yōu)美在于,代碼少,不用引入任何包。純JDK,一樣能干許多事。有時(shí)不希望把本來簡(jiǎn)單的事情搞得復(fù)雜化。雖然不要?jiǎng)?chuàng)造重復(fù)的輪子,但我們不能純拿來主義,就像這樣一個(gè)簡(jiǎn)單的功能,不需要搞得太復(fù)雜。只要不DRY就可以了,這樣自己也能一點(diǎn)點(diǎn)地進(jìn)步。

          以上有什么錯(cuò)誤,還請(qǐng)包涵。。。。。。該文章來自:樂樂日志(記下每個(gè)快樂的日子)。


          評(píng)論

          # re: [原創(chuàng)]用HttpUrlConnection抓取網(wǎng)頁內(nèi)容  回復(fù)  更多評(píng)論   

          2015-03-06 23:31 by 覆蓋
          主站蜘蛛池模板: 景洪市| 十堰市| 双流县| 图片| 东兰县| 新源县| 崇信县| 琼中| 石泉县| 江口县| 南充市| 金湖县| 曲阳县| 威远县| 澳门| 日土县| 定日县| 舒城县| 靖州| 焦作市| 砚山县| 伊春市| 新宁县| 米泉市| 武宁县| 石渠县| 曲沃县| 邳州市| 兴安县| 拜城县| 舟山市| 淮北市| 内乡县| 安丘市| 南澳县| 金寨县| 文化| 若羌县| 雅安市| 莱阳市| 枣阳市|