程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 使用java開源工具httpClient及jsoup抓取解析網頁數據,httpclientjsoup

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

編輯:JAVA綜合教程

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


  今天做項目的時候遇到這樣一個需求,需要在網頁上展示今日黃歷信息,數據格式如下

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

  主要包括公歷/農歷日期,以及忌宜信息的等。但是手裡並沒有現成的數據可供使用,怎麼辦呢?

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

萬年歷應用可供使用,雖然沒有現成接口,但是我們可以伸出手來,自己去拿。也就是所謂的數據

抓取。

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

 

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

  httpClient使用方法如下:

  1. 創建HttpClient對象。

  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

 

 

 

  另外還有很多強大的功能水平有限就不一一列舉了,感興趣的可以參照官網文檔,也歡迎交流指正。新技能get起來!


本文版權歸作者及博客園所有,轉載請注明作者及原文出處

溯源blog http://www.cnblogs.com/lkxsnow/

 

 

 

  

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved