1. 程式人生 > 其它 >Jsoup入門學習一

Jsoup入門學習一

技術標籤:jsjavapythonhtml大資料

1、Jsoup是一款Java 的HTML解析器,可直接解析某個URL地址、HTML文字內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似於jQuery的操作方法來取出和操作資料。

2、Jsoup 的主要功能,如下所示:

  1)、從一個URL,檔案或字串中解析HTML;
  2)、使用DOM或CSS選擇器來查詢、取出資料;
  3)、可操作HTML元素、屬性、文字;
  4)、Jsoup 是基於MIT協議釋出的,可放心使用於商業專案。

3、httpClient 結合Jsoup 獲取到網頁內容進行解析,首先需要引入httpClient和Jsoup的依賴,如下所示:

 1 <project xmlns="http://maven.apache.org/POM/4.0.0"
 2     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
 4       http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6 
 7     <groupId>com.bie</groupId>
 8     <artifactId>jsoup</artifactId>
 9     <version>0.0.1-SNAPSHOT</version>
10     <packaging>jar</packaging>
11 
12     <name>jsoup</name>
13     <url>http://maven.apache.org</url>
14 
15     <properties>
16         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
17     </properties>
18 
19     <dependencies>
20         <!-- 新增httpclient支援 -->
21         <dependency>
22             <groupId>org.apache.httpcomponents</groupId>
23             <artifactId>httpclient</artifactId>
24             <version>4.5.2</version>
25         </dependency>
26         <!-- jsoup版本依賴 -->
27         <dependency>
28             <groupId>org.jsoup</groupId>
29             <artifactId>jsoup</artifactId>
30             <version>1.8.3</version>
31         </dependency>
32     </dependencies>
33 </project>

雖然使用Jsoup可以替代HttpClient直接發起請求解析資料,但是往往不會這樣用,因為實際的開發過程中,需要使用到多執行緒,連線池,代理等等技術,而jsoup對這些技術的支援並不是很好,所以jsoup一般僅僅作為Html解析工具使用。

 1 package com.bie.spider.jsoup;
 2 
 3 import java.io.File;
 4 import java.io.IOException;
 5 import java.net.MalformedURLException;
 6 import java.net.URL;
 7 
 8 import org.apache.commons.io.FileUtils;
 9 import org.jsoup.Jsoup;
10 import org.jsoup.nodes.Document;
11 import org.jsoup.nodes.Element;
12 
13 /**
14  * 
15  * @author
16  *
17  */
18 public class JsoupDocument {
19 
20     /**
21      * 雖然使用Jsoup可以替代HttpClient直接發起請求解析資料,但是往往不會這樣用,
22      * 因為實際的開發過程中,需要使用到多執行緒,連線池,代理等等技術,
23      * 而jsoup對這些技術的支援並不是很好, 所以jsoup一般僅僅作為Html解析工具使用
24      * 
25      * @throws MalformedURLException
26      * @throws IOException
27      */
28     public static void inputUrl() throws MalformedURLException, IOException {
29         // Jsoup可以直接輸入url,它會發起請求並獲取資料,封裝為Document物件
30         // 使用jsoup解析url
31         Document doc = Jsoup.parse(new URL("https://www.autohome.com.cn/bestauto/"), 10000);
32 
33         // 把獲取的內容輸出為檔案
34         FileUtils.writeStringToFile(new File("D:/test.html"), doc.toString(), "UTF-8");
35 
36         // 獲取title
37         Element element = doc.getElementsByTag("title").first();
38 
39         // 列印title內容
40         System.out.println(element.text());
41     }
42 
43     /**
44      * 輸入字串,Jsoup可以直接輸入字串,並封裝為Document物件
45      * 
46      * @throws MalformedURLException
47      * @throws IOException
48      */
49     public static void inputCharacter() throws MalformedURLException, IOException {
50         // 讀取檔案,獲取字串
51         String html = FileUtils.readFileToString(new File("D:/test.html"), "UTF-8");
52 
53         // 解析字串
54         Document doc = Jsoup.parse(html);
55 
56         // 獲取title標籤
57         Element element = doc.getElementsByTag("title").first();
58 
59         // 列印title內容
60         System.out.println(element.text());
61     }
62 
63     /**
64      * 輸入檔案,Jsoup可以直接輸入檔案,並封裝為Document物件
65      * 
66      * @throws MalformedURLException
67      * @throws IOException
68      */
69     public static void inputFile() throws MalformedURLException, IOException {
70         // 使用jsoup解析檔案
71         Document doc = Jsoup.parse(new File("D:/test.html"), "UTF-8");
72 
73         // 獲取title標籤
74         Element element = doc.getElementsByTag("title").first();
75 
76         // 列印title內容
77         System.out.println(element.text());
78     }
79 
80     public static void main(String[] args) throws MalformedURLException, IOException {
81         // 輸入url
82         inputUrl();
83         // 輸入字串
84         inputCharacter();
85         // 輸入檔案
86         inputFile();
87     }
88 
89 }

httpClient 結合Jsoup 獲取到網頁內容進行解析,具體程式碼,如下所示:

 1 package com.bie.jsoup;
 2 
 3 import java.io.IOException;
 4 
 5 import org.apache.http.Header;
 6 import org.apache.http.HttpEntity;
 7 import org.apache.http.ParseException;
 8 import org.apache.http.StatusLine;
 9 import org.apache.http.client.ClientProtocolException;
10 import org.apache.http.client.methods.CloseableHttpResponse;
11 import org.apache.http.client.methods.HttpGet;
12 import org.apache.http.impl.client.CloseableHttpClient;
13 import org.apache.http.impl.client.HttpClients;
14 import org.apache.http.util.EntityUtils;
15 import org.jsoup.Jsoup;
16 import org.jsoup.nodes.Document;
17 import org.jsoup.nodes.Element;
18 import org.jsoup.select.Elements;
19 
20 public class HttpClientToJsoup {
21 
22     // 設定請求頭訊息 User-Agent 模擬瀏覽器
23     private static String UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0";
24 
25     /**
26      * HttpGet請求操作
27      */
28     public static void httpGetRequest() {
29         // 第一步,獲取到httpClient客戶端例項,獲取到一個可關閉的httpClient客戶端例項。
30         CloseableHttpClient httpClient = HttpClients.createDefault();
31         // 第二步,建立HttpGet或者HttpPost例項。
32         String uri = "https://www.cnblogs.com/biehongli";
33         HttpGet httpGet = new HttpGet(uri);
34         // 設定請求頭訊息 User-Agent 模擬瀏覽器
35         httpGet.setHeader("User-Agent", UserAgent);
36 
37         // 定義一個可響應的例項物件。
38         CloseableHttpResponse response = null;
39         try {
40             // 第三步,釋出一個請求,使用httpClient例項傳送一個http協議的Get請求。
41             response = httpClient.execute(httpGet);
42             // 獲取到響應的狀態
43             StatusLine statusLine = response.getStatusLine();
44             System.out.println("響應狀態: " + statusLine.toString() + ", 響應碼: " + statusLine.getStatusCode());
45         } catch (ClientProtocolException e) {
46             // http協議異常
47             e.printStackTrace();
48         } catch (IOException e) {
49             // io異常
50             e.printStackTrace();
51         }
52         // 第四步,獲取到返回的實體物件
53         HttpEntity entity = response.getEntity();
54         // 獲取響應內容型別 Content-Type,獲取到響應型別,從而過濾一些不想要的東西
55         Header contentType = entity.getContentType();
56         // 列印響應資訊
57         System.out.println("name : " + contentType.getName() + " , value: " + contentType.getValue());
58 
59         // 將返回結果轉換為字串進行檢視(網頁內容),引數一是請求返回的entity,引數二是字符集編碼
60         String result = null;
61         try {
62             result = EntityUtils.toString(entity, "UTF-8");
63         } catch (ParseException e) {
64             e.printStackTrace();
65         } catch (IOException e) {
66             e.printStackTrace();
67         }
68         // 列印請求返回的結果
69         // System.out.println(result.toString());
70 
71         // 講獲取到網頁轉換成為jsoup進行處理,返回結果為Document文件
72         Document document = Jsoup.parse(result);
73         Elements elements = document.getElementsByTag("title");
74         Element element = elements.get(0);
75         System.out.println("獲取到的標題內容: " + element.text().toString());
76 
77         // 獲取到自己的部落格題目名稱內容
78         Elements elementsByClass = document.getElementsByClass("postTitle2");
79         for (Element e : elementsByClass) {
80             System.out.println("獲取到的標題內容是: " + e.text());
81         }
82 
83         // 第五步,關閉流,釋放資源
84         try {
85             response.close();
86             httpClient.close();
87         } catch (IOException e) {
88             e.printStackTrace();
89         }
90     }
91 
92     public static void main(String[] args) {
93         HttpClientToJsoup.httpGetRequest();
94     }
95 
96 }

4、Jsoup的主要作用是,用HttpClient獲取到網頁後,具體的網頁提取需要的資訊的時候 ,就用到Jsoup,Jsoup可以使用強大的類似Jquery,css選擇器,來獲取需要的資料;

Jsoup官方地址:https://jsoup.org/Jsoup最新下載:https://jsoup.org/downloadJsoup學習文件:https://jsoup.org/cookbook/introduction/parsing-a-document

5、Jsoup查詢DOM元素的主要方法,如下所示:

  1)、getElementById(String id) 根據 id 來查詢 DOM。  2)、getElementsByTag(String tagName) 根據 tag 名稱來查詢 DOM。  3)、getElementsByClass(String className) 根據樣式名稱來查詢 DOM。  4)、getElementsByAttribute(String key) 根據屬性名,標籤的屬性元素來查詢 DOM。  5)、getElementsByAttributeValue(String key,String value) 根據屬性名和屬性值來查詢 DOM。

如果滿足不了自己的需求,可以使用Jsoup 的選擇器語法查詢 DOM 元素,如下所示:

  1 package com.bie.jsoup;
  2 
  3 import java.io.IOException;
  4 
  5 import org.apache.http.Header;
  6 import org.apache.http.HttpEntity;
  7 import org.apache.http.ParseException;
  8 import org.apache.http.StatusLine;
  9 import org.apache.http.client.ClientProtocolException;
 10 import org.apache.http.client.methods.CloseableHttpResponse;
 11 import org.apache.http.client.methods.HttpGet;
 12 import org.apache.http.impl.client.CloseableHttpClient;
 13 import org.apache.http.impl.client.HttpClients;
 14 import org.apache.http.util.EntityUtils;
 15 import org.jsoup.Jsoup;
 16 import org.jsoup.nodes.Document;
 17 import org.jsoup.nodes.Element;
 18 import org.jsoup.select.Elements;
 19 
 20 public class HttpClientToJsoup {
 21 
 22     // 設定請求頭訊息 User-Agent 模擬瀏覽器
 23     private static String UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0";
 24 
 25     /**
 26      * HttpGet請求操作
 27      */
 28     public static void httpGetRequest() {
 29         // 第一步,獲取到httpClient客戶端例項,獲取到一個可關閉的httpClient客戶端例項。
 30         CloseableHttpClient httpClient = HttpClients.createDefault();
 31         // 第二步,建立HttpGet或者HttpPost例項。
 32         String uri = "https://www.cnblogs.com/biehongli";
 33         HttpGet httpGet = new HttpGet(uri);
 34         // 設定請求頭訊息 User-Agent 模擬瀏覽器
 35         httpGet.setHeader("User-Agent", UserAgent);
 36 
 37         // 定義一個可響應的例項物件。
 38         CloseableHttpResponse response = null;
 39         try {
 40             // 第三步,釋出一個請求,使用httpClient例項傳送一個http協議的Get請求。
 41             response = httpClient.execute(httpGet);
 42             // 獲取到響應的狀態
 43             StatusLine statusLine = response.getStatusLine();
 44             System.out.println("響應狀態: " + statusLine.toString() + ", 響應碼: " + statusLine.getStatusCode());
 45         } catch (ClientProtocolException e) {
 46             // http協議異常
 47             e.printStackTrace();
 48         } catch (IOException e) {
 49             // io異常
 50             e.printStackTrace();
 51         }
 52         // 第四步,獲取到返回的實體物件
 53         HttpEntity entity = response.getEntity();
 54         // 獲取響應內容型別 Content-Type,獲取到響應型別,從而過濾一些不想要的東西
 55         Header contentType = entity.getContentType();
 56         // 列印響應資訊
 57         System.out.println("name : " + contentType.getName() + " , value: " + contentType.getValue());
 58 
 59         // 將返回結果轉換為字串進行檢視(網頁內容),引數一是請求返回的entity,引數二是字符集編碼
 60         String result = null;
 61         try {
 62             result = EntityUtils.toString(entity, "UTF-8");
 63         } catch (ParseException e) {
 64             e.printStackTrace();
 65         } catch (IOException e) {
 66             e.printStackTrace();
 67         }
 68         // 列印請求返回的結果
 69         // System.out.println(result.toString());
 70 
 71         // 講獲取到網頁轉換成為jsoup進行處理,返回結果為Document文件
 72         Document document = Jsoup.parse(result);
 73         Elements elements = document.getElementsByTag("title");
 74         Element element = elements.get(0);
 75         System.out.println("獲取到的標題內容: " + element.text().toString());
 76 
 77         // 通過選擇器查詢所有部落格連結DOM,獲取到自己的部落格題目名稱內容
 78         // 使用Jsoup的選擇器
 79         Elements select = document.select("#centercontent .day .postTitle .postTitle2");
 80         for (Element e : select) {
 81             System.out.println("部落格標題:" + e.text());
 82         }
 83 
 84         // 帶有href屬性的a元素
 85         Elements selectHref = document.select(".postTitle a[href]");
 86         for (Element e : selectHref) {
 87             System.out.println("部落格標題:" + e.text());
 88         }
 89 
 90         // 查詢副檔名為.png的圖片DOM節點
 91         Elements imgElements = document.select("img[src$=.png]");
 92         for (Element e : imgElements) {
 93             System.out.println(e.toString());
 94         }
 95 
 96         // 獲取tag是title的所有DOM元素
 97         Element first = document.getElementsByTag("title").first();
 98         String title = first.text(); // 返回元素的文字
 99         System.out.println("網頁標題是:" + title);
100 
101         // 第五步,關閉流,釋放資源
102         try {
103             response.close();
104             httpClient.close();
105         } catch (IOException e) {
106             e.printStackTrace();
107         }
108     }
109 
110     public static void main(String[] args) {
111         HttpClientToJsoup.httpGetRequest();
112     }
113 
114 }

6、使用選擇器語法查詢元素,Jsoup elements物件支援類似於CSS (或jquery)的選擇器語法,來實現非常強大和靈活的查詢功能。這個select 方法在Document, Element,或Elements物件中都可以使用。且是上下文相關的,因此可實現指定元素的過濾,或者鏈式選擇訪問。Select方法將返回一個Elements集合,並提供一組方法來抽取和處理結果。如下所示:

  1 package com.bie.jsoup;
  2 
  3 import java.io.IOException;
  4 
  5 import org.apache.http.Header;
  6 import org.apache.http.HttpEntity;
  7 import org.apache.http.ParseException;
  8 import org.apache.http.StatusLine;
  9 import org.apache.http.client.ClientProtocolException;
 10 import org.apache.http.client.methods.CloseableHttpResponse;
 11 import org.apache.http.client.methods.HttpGet;
 12 import org.apache.http.impl.client.CloseableHttpClient;
 13 import org.apache.http.impl.client.HttpClients;
 14 import org.apache.http.util.EntityUtils;
 15 import org.jsoup.Jsoup;
 16 import org.jsoup.nodes.Document;
 17 import org.jsoup.nodes.Element;
 18 import org.jsoup.select.Elements;
 19 
 20 public class HttpClientToJsoup {
 21 
 22     // 設定請求頭訊息 User-Agent 模擬瀏覽器
 23     private static String UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0";
 24 
 25     /**
 26      * HttpGet請求操作
 27      */
 28     public static void httpGetRequest() {
 29         // 第一步,獲取到httpClient客戶端例項,獲取到一個可關閉的httpClient客戶端例項。
 30         CloseableHttpClient httpClient = HttpClients.createDefault();
 31         // 第二步,建立HttpGet或者HttpPost例項。
 32         String uri = "https://www.cnblogs.com/biehongli";
 33         HttpGet httpGet = new HttpGet(uri);
 34         // 設定請求頭訊息 User-Agent 模擬瀏覽器
 35         httpGet.setHeader("User-Agent", UserAgent);
 36 
 37         // 定義一個可響應的例項物件。
 38         CloseableHttpResponse response = null;
 39         try {
 40             // 第三步,釋出一個請求,使用httpClient例項傳送一個http協議的Get請求。
 41             response = httpClient.execute(httpGet);
 42             // 獲取到響應的狀態
 43             StatusLine statusLine = response.getStatusLine();
 44             System.out.println("響應狀態: " + statusLine.toString() + ", 響應碼: " + statusLine.getStatusCode());
 45         } catch (ClientProtocolException e) {
 46             // http協議異常
 47             e.printStackTrace();
 48         } catch (IOException e) {
 49             // io異常
 50             e.printStackTrace();
 51         }
 52         // 第四步,獲取到返回的實體物件
 53         HttpEntity entity = response.getEntity();
 54         // 獲取響應內容型別 Content-Type,獲取到響應型別,從而過濾一些不想要的東西
 55         Header contentType = entity.getContentType();
 56         // 列印響應資訊
 57         System.out.println("name : " + contentType.getName() + " , value: " + contentType.getValue());
 58 
 59         // 將返回結果轉換為字串進行檢視(網頁內容),引數一是請求返回的entity,引數二是字符集編碼
 60         String result = null;
 61         try {
 62             result = EntityUtils.toString(entity, "UTF-8");
 63         } catch (ParseException e) {
 64             e.printStackTrace();
 65         } catch (IOException e) {
 66             e.printStackTrace();
 67         }
 68         // 列印請求返回的結果
 69         // System.out.println(result.toString());
 70 
 71         // 講獲取到網頁轉換成為jsoup進行處理,返回結果為Document文件
 72         Document document = Jsoup.parse(result);
 73 
 74         // Jsoup 使用selector選擇器
 75         Elements linkElements = document.select("#centercontent .day .postTitle .postTitle2"); // 通過選擇器查詢所有部落格連結DOM
 76         for (Element e : linkElements) {
 77             System.out.println("部落格標題:" + e.text());
 78             System.out.println("部落格地址:" + e.attr("href"));
 79             // System.out.println("target:" + e.attr("target"));
 80         }
 81 
 82         // Jsoup 使用selector選擇器
 83         Element linkElement = document.select(".postTitle2").first();
 84         System.out.println("純文字內容:" + linkElement.text());
 85         System.out.println("Html內容:" + linkElement.html());
 86 
 87         // 第五步,關閉流,釋放資源
 88         try {
 89             response.close();
 90             httpClient.close();
 91         } catch (IOException e) {
 92             e.printStackTrace();
 93         }
 94     }
 95 
 96     public static void main(String[] args) {
 97         HttpClientToJsoup.httpGetRequest();
 98     }
 99 
100 }
 1 1、Selector選擇器概述,如下所示:
 2 1)、tagname: 通過標籤查詢元素,比如:a。
 3 2)、ns|tag: 通過標籤在名稱空間查詢元素,比如:可以用 fb|name 語法來查詢 <fb:name> 元素。
 4 3)、#id: 通過ID查詢元素,比如:#logo。
 5 4)、.class: 通過class名稱查詢元素,比如:.masthead。
 6 5)、[attribute]: 利用屬性查詢元素,比如:[href]。
 7 6)、[attr=value]: 利用屬性值來查詢元素,比如:[width=500]。
 8 
 9 
10 // 案例使用,使用選擇器
11 // tagname: 通過標籤查詢元素,比如:a
12 str = doc.select("a").first().text();
13 
14 // ns|tag: 通過標籤在名稱空間查詢元素,比如:可以用 fb|name 語法來查詢 <fb:name> 元素
15 str = doc.select("jsoup|li").first().text();
16 
17 // #id: 通過ID查詢元素,比如:#logo
18 str = doc.select("#auto-header-fenzhan").first().text();
19 
20 // .class: 通過class名稱查詢元素,比如:.masthead
21 str = doc.select(".orangelink").first().text();
22 
23 // [attribute]: 利用屬性查詢元素,比如:[href]
24 str = doc.select("[abc]").first().text();
25 
26 // [attr=value]: 利用屬性值來查詢元素,比如:[width=500]
27 str = doc.select("[class=vlli]").first().text();
28 
29 
30 2、Selector選擇器組合使用,如下所示:
31 1)、el#id: 元素+ID,比如: div#logo。
32 2)、el.class: 元素+class,比如: div.masthead。
33 3)、el[attr]: 元素+屬性名,比如: a[href]。
34 4)、任意組合,比如:a[href].highlight。
35 5)、ancestor child: 查詢某個元素下子元素,比如:.body p 查詢"body"下的所有 p。
36 6)、parent > child: 查詢某個父元素下的直接子元素,比如:div.content > p 查詢 p。
37 7)、parent > * 查詢某個父元素下所有直接子元素。
38 
39 
40 // 案例使用,組合選擇器
41 // el#id: 元素+ID,比如: div#logo
42 str = doc.select("li#auto-header-fenzhan").first().text();
43 
44 // el.class: 元素+class,比如: div.masthead
45 str = doc.select("a.greylink").first().text();
46 
47 // el[attr]: 元素+屬性,比如: a[href]
48 str = doc.select("a[href]").first().attr("href");
49 
50 // 任意組合,比如:a[href].highlight
51 str = doc.select("a[href].greylink").first().attr("href");
52 
53 // ancestor child: 查詢某個元素下子元素,比如:可以用.body p 查詢"body"下的所有 p
54 str = doc.select("div.mini-left a").text();
55 
56 // parent > child: 查詢某個父元素下的直接子元素,比如:div.content > p 查詢 p
57 str = doc.select("div.mini-left ul > li").text();
58 
59 // parent > * 查詢某個父元素下所有直接子元素
60 Elements elements = doc.select("div.mini-left > *");
61 for (Element ele : elements) {
62     System.out.println(ele.tagName());
63 }