使用java開源工具httpClient及jsoup抓取解析網頁數據

使用java開源工具httpClient及jsoup抓取解析網頁數據

今天作項目的時候遇到這樣一個需求,須要在網頁上展現今日黃曆信息,數據格式以下html

  •   公曆時間:2016年04月11日 星期一
  •   農曆時間:猴年三月初五
  •   天干地支:丙申年 壬辰月 癸亥日
  •   宜:求子 祈福 開光 祭祀 安牀
  •   忌:玉堂(黃道)危日,忌出行

  主要包括公曆/農曆日期,以及忌宜信息的等。可是手裏並無現成的數據可供使用,怎麼辦呢?java

革命前輩曾經說過,沒有槍,沒有炮,敵(wang)人(luo)給咱們造!網絡上有不少現成的在線node

萬年曆應用可供使用,雖然沒有現成接口,可是咱們能夠伸出手來,本身去拿。也就是所謂的數據jquery

抓取。程序員

  這裏介紹兩個使用的工具,httpClient以及jsoup,簡介以下:apache

 

  HttpClient是Apache Jakarta Common下的子項目,用來提供高效的、最新的、功能豐富的支持HTTP協議的客戶端編程工具包,而且它支持HTTP協議最新的版本和建議。HttpClient已經應用在不少的項目中,好比Apache Jakarta上很著名的另外兩個開源項目Cactus和HTMLUnit都使用了HttpClient。編程

  httpClient使用方法以下:網絡

  1. 建立HttpClient對象。app

  2. 建立請求方法的實例,並指定請求URL。框架

  3. 調用HttpClient對象的execute(HttpUriRequest request)發送請求,該方法返回一個HttpResponse。

  4. 調用HttpResponse相關方法獲取相應內容。

  5. 釋放鏈接。

 

  jsoup 是一款 Java 的 HTML 解析器,可直接解析某個 URL 地址、HTML 文本內容。它提供了一套很是省力的 API,可經過 DOM,CSS 以及相似於 jQuery 的操做方法來取出和操做數據。

 

  須要更多信息能夠參見官網

  httpClient:http://hc.apache.org/httpcomponents-client-5.0.x/index.html

  jsoup:http://jsoup.org/

  

  接下來咱們直接上代碼,這裏咱們抓取2345在線萬年曆的數據 http://tools.2345.com/rili.htm

  首先咱們定義一個實體類Almanac來存儲黃曆數據

  Almanac.java

複製代碼
 1 package com.likx.picker.util.bean;  2   3 /**  4  * 萬年曆工具實體類  5  *   6  * @author 溯源blog  7  * 2016年4月11日  8  */  9 public class Almanac { 10     private String solar;        /* 陽曆 e.g.2016年 4月11日 星期一 */ 11     private String lunar;        /* 陰曆 e.g. 猴年 三月初五*/ 12     private String chineseAra;    /* 天干地支紀年法 e.g.丙申年 壬辰月 癸亥日*/ 13     private String should;        /* 宜e.g. 求子 祈福 開光 祭祀 安牀*/ 14     private String avoid;        /* 忌 e.g. 玉堂(黃道)危日,忌出行*/ 15  16     public String getSolar() { 17         return solar; 18     } 19  20     public void setSolar(String date) { 21         this.solar = date; 22     } 23  24     public String getLunar() { 25         return lunar; 26     } 27  28     public void setLunar(String lunar) { 29         this.lunar = lunar; 30     } 31  32     public String getChineseAra() { 33         return chineseAra; 34     } 35  36     public void setChineseAra(String chineseAra) { 37         this.chineseAra = chineseAra; 38     } 39  40     public String getAvoid() { 41         return avoid; 42     } 43  44     public void setAvoid(String avoid) { 45         this.avoid = avoid; 46     } 47  48     public String getShould() { 49         return should; 50     } 51  52     public void setShould(String should) { 53         this.should = should; 54     } 55  56     public Almanac(String solar, String lunar, String chineseAra, String should, 57             String avoid) { 58         this.solar = solar; 59         this.lunar = lunar; 60         this.chineseAra = chineseAra; 61         this.should = should; 62         this.avoid = avoid; 63     } 64 }
複製代碼

 

  而後是抓取解析的主程序,寫程序以前須要在官網下載須要的jar包

  AlmanacUtil.java

複製代碼
package com.likx.picker.util; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date;  import org.apache.http.HttpEntity; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; 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 org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; /**  *<STRONG>類描述</STRONG> :  2345萬年曆信息爬取工具<p>  *     * @version 1.0 <p>  * @author 溯源blog  *   * <STRONG>建立時間</STRONG> : 2016年4月11日 下午14:15:44<p>  * <STRONG>修改歷史</STRONG> :<p>  *<pre>  * 修改人                   修改時間                     修改內容  * ---------------         -------------------         -----------------------------------  *</pre>  */ public class AlmanacUtil {          /**      * 單例工具類      */     private AlmanacUtil() {     }     /**      * 獲取萬年曆信息      * @return      */     public static Almanac getAlmanac(){         String url="http://tools.2345.com/rili.htm";         String html=pickData(url);         Almanac almanac=analyzeHTMLByString(html);         return almanac;     }          /*      * 爬取網頁信息      */     private static String pickData(String url) {         CloseableHttpClient httpclient = HttpClients.createDefault();         try {             HttpGet httpget = new HttpGet(url);             CloseableHttpResponse response = httpclient.execute(httpget);             try {                 // 獲取響應實體                 HttpEntity entity = response.getEntity();                 // 打印響應狀態                 if (entity != null) {                     return EntityUtils.toString(entity);                 }             } finally {                 response.close();             }         } catch (ClientProtocolException e) {             e.printStackTrace();         } catch (ParseException e) {             e.printStackTrace();         } catch (IOException e) {             e.printStackTrace();         } finally {             // 關閉鏈接,釋放資源             try {                 httpclient.close();             } catch (IOException e) {                 e.printStackTrace();             }         }         return null;     }          /*      * 使用jsoup解析網頁信息      */     private static Almanac analyzeHTMLByString(String html){         String solarDate,lunarDate,chineseAra,should,avoid=" ";         Document document = Jsoup.parse(html);         //公曆時間         solarDate=getSolarDate();         //農曆時間         Element eLunarDate=document.getElementById("info_nong");         lunarDate=eLunarDate.child(0).html().substring(1,3)+eLunarDate.html().substring(11);         //天干地支紀年法         Element eChineseAra=document.getElementById("info_chang");         chineseAra=eChineseAra.text().toString();             //         should=getSuggestion(document,"yi");         //         avoid=getSuggestion(document,"ji");         Almanac almanac=new Almanac(solarDate,lunarDate,chineseAra,should,avoid);         return almanac;     }     /*      * 獲取忌/宜      */     private static String getSuggestion(Document doc,String id){         Element element=doc.getElementById(id);         Elements elements=element.getElementsByTag("a");         StringBuffer sb=new StringBuffer();         for (Element e : elements) {             sb.append(e.text()+" ");         }         return sb.toString();     }      /*      * 獲取公曆時間,用yyyy年MM月dd日 EEEE格式表示。      * @return yyyy年MM月dd日 EEEE      */     private static String getSolarDate() {         Calendar calendar = Calendar.getInstance();         Date solarDate = calendar.getTime();         SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日 EEEE");         return formatter.format(solarDate);     }  }
複製代碼

 

  爲了簡單明瞭我把抓取解析抽象成了幾個獨立的方法,

  其中pickData()方法使用httpClient來抓取數據到一個字符串中(就是在網頁上點擊查看源代碼看到的HTML源碼),

analyzeHTMLByString()方法來解析抓取到的字符串,getSuggestion方法把抓取方法相似的宜忌數據抽象到了

一塊兒,另外由於公曆時間能夠很容易的本身生成就沒有在網頁上爬取。

 

  而後下面是一個測試類簡單測試下效果:

 AlmanacUtilTest.java

複製代碼
package com.likx.picker.util.test;  public class AlmanacUtilTest {          public static void main(String args[]){         Almanac almanac=AlmanacUtil.getAlmanac();         System.out.println("公曆時間:"+almanac.getSolar());         System.out.println("農曆時間:"+almanac.getLunar());         System.out.println("天干地支:"+almanac.getChineseAra());         System.out.println("宜:"+almanac.getShould());         System.out.println("忌:"+almanac.getAvoid());     } }
複製代碼

 

  運行結果以下:

 

  集成到實際項目中效果是這樣的:

 

  

 

  另外最近博客一直沒怎麼更新,由於最近考慮到技術氛圍的緣由,離開了對日外包行業,前往

一家互聯網公司就任。說一下最近的感覺,那就是一個程序員最核心的競爭力不是學會了多少框架,

掌握多少種工具(固然這些對於程序員也不可或缺),而是紮實的基礎以及快速學習的能力,好比今天

這個項目,從對httpClient,jsoup工具一無所知到編寫出Demo代碼總計大概1個多小時,在以前對於

我來講是不可想象的,在技術氛圍濃厚的地方快速get技能的感受,很是好。

  固然本例只是一個很是淺顯的小例子,網頁上內容也很容易抓取,httpClient及jsoup工具更多強大

的地方沒有體現到,好比httpClient不只能夠發送get請求,並且能夠發送post請求,提交表單,傳送

文件,還好比jsoup最強大的地方在於它支持仿jquery的選擇器。本例僅僅使用了最簡單的document.getElementById()

匹配元素,實際上jsoup的選擇器異常強大,能夠說它就是java版的jquery,好比這樣:

 

Elements links = doc.select("a[href]"); // a with href Elements pngs = doc.select("img[src$=.png]");   // img with src ending .png Element masthead = doc.select("div.masthead").first();   // div with class=masthead Elements resultLinks = doc.select("h3.r > a"); // direct a after h3

相關文章
相關標籤/搜索