Java Jsoup使用詳解

1.Jsoup介紹

jsoup 是一款Java 的HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似於jQuery的操作方法來取出和操作數據。——引自百度百科對Jsoup的介紹


前置

引入Jsoup依賴

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.11.3</version>
</dependency>

2.使用Jsoup解析HTML

以下代碼是使用Jsoup對html進行解析,這裏的html只是一個小測試,可以使用HttpClient請求並獲取響應的HTML,再通過Jsoup完成解析。

這裏選擇的是兩個參數的解析,第二個參數爲HTML的URL路徑,當我們的HTML中有相對路徑時,我們可以通過URL路徑將相對路徑轉換爲絕對路徑。

此外,Jsoup還提供了其他參數的解析,如設置解析超時時間,還可以自定義解析器,設置解析的一些參數,如允許標籤或屬性的大小寫。—— 一般這兩個參數就夠了。

StringBuilder htmlSB = new StringBuilder();
htmlSB.append("<html>")
        .append("<head>")
        .append("<title>標題</title>")
        .append("</head>")
        .append("<body>")
        .append("<img src=\"/test.png\"></img>")
        .append("</body>")
        .append("</html>");
Document document = Jsoup.parse(htmlSB.toString(), "http://www.baidu.com");

解析過程:簡單來說就是按字符不斷遍歷HTML,解析成一個個Element並追加到Document對象。
以下一整塊可以認爲是一個Document,<head>…</head>則是一個Element,每個Element包含其父Element(最多1個)和子Elements(可以多個)

<html>...</html>
----<head>...</head>
--------<title>...</title>
----<body>...</body>
--------<img>...</img>

比如我們要獲取HTML中所有圖片的鏈接。這裏使用的是cssQuery選擇器語法,搜索文檔中img帶有src屬性的Element,再打印圖片路徑(實際情況肯定要對路徑處理,這裏偷懶了)。

for (Element element : document.select("img[src]")) {
    System.out.println(element.baseUri() + element.attr("src"));
}

Jsoup還提供給我們類似JavaScript的一些方法,能讓我們方便的篩選出需要的元素。

document.getElementsByTag("");
document.getElementsByClass("");
document.getElementById("");
document.getElementsByAttribute("");

3.使用Jsoup發送HTTP請求

3.1GET請求

以下兩種方式均可實現GET請求調用,主要兩個方法返回的類型不同,這裏將請求返回的HTML打印出來。

String url = "http://www.baidu.com";
Connection.Response response = Jsoup.connect(url).execute();
System.out.println(response.body());
Document document = Jsoup.connect(url).get();
System.out.println(document.html());

攜帶參數的GET請求,這裏寫了一個本地接口

@RequestMapping("/user")
@RestController
public class UserController {
    @GetMapping("/myself")
    public String myself(String name, int age) {
        return "姓名:" + name + ",年齡:" + age;
    }
}
String url = "http://localhost:8080/user/myself";
Connection.Response response = Jsoup
        .connect(url)
        .data("name", "張三")
        .data("age", "20")
        .execute();
System.out.println(response.body());
3.2POST請求

攜帶參數的POST請求,這裏寫了一個本地接口

@RequestMapping("/user")
@RestController
public class UserController {
    @PostMapping("/login")
    public ResponseVo login(@RequestBody UserLoginReq userLoginReq) {
        return ResponseVo.getSuccess(userLoginReq);
    }
}

注意這裏有一個ignoreContentType(true),意思是忽略響應返回的類型,這兒不加會拋出org.jsoup.UnsupportedMimeTypeException異常

String url = "http://localhost:8080/user/login";
Connection connection = Jsoup.connect(url);
connection
        .ignoreContentType(true)
        .header("Content-Type", "application/json")
        .requestBody("{\"username\": \"123123\",\"password\": \"123123\"}");
System.out.println(connection.post().text());
3.3額外請求屬性

除了可以設置請求頭,請求體,參數等,Jsoup還支持設置代理、請求超時、Cookie等。

下面模擬一個請求,請求簡書需要登錄的頁面https://www.jianshu.com/my/paid_notes
(1)登錄簡書後,進入到該頁面。
(2)按F12後刷新頁面,請求頭有一個remember_user_token,擁有這個值就可以認爲我們已經登錄了簡書
在這裏插入圖片描述

String url = "https://www.jianshu.com/my/paid_notes";
Connection.Response response = Jsoup
        .connect(url)
        .cookie("remember_user_token", "我這兒省略了!!!")
        .execute();
System.out.println(response.body());

如果我們註釋掉這個cookie,那麼簡書就會響應給我們一個登錄頁面要求我們進行登錄。

4.Jsoup提供的另外兩個方法

clean:支持兩個功能,第一個就是講HTML的body體中的相對路徑轉換爲絕對路徑,第二個就是可以過濾掉一些HTML標籤和屬性,可以通過使用白名單設置保留的標籤和屬性。

StringBuilder htmlSB = new StringBuilder();
htmlSB.append("<html>")
        .append("<head>")
        .append("<title>標題</title>")
        .append("</head>")
        .append("<body>")
        .append("<img src=\"/test.png\"></img>")
        .append("</body>")
        .append("</html>");
Whitelist whitelist = new Whitelist()
        .addTags("head", "body", "img")
        .addAttributes("img", "src")
        .addProtocols("img", "src", "http", "https");
String html = Jsoup.clean(htmlSB.toString(), "http://www.baidu.com/", whitelist);
System.out.println(html);

打印結果,注意這裏是沒有<html>的,因爲是對body裏面的內容進行處理。

<body>
 標題
 <img src="http://www.baidu.com/test.png">
</body>

isValid:這個方法是判斷HTML的body是否符合白名單

public static boolean isValid(String bodyHtml, Whitelist whitelist) {
    return new Cleaner(whitelist).isValidBodyHtml(bodyHtml);
}

完結,以上內容如果有誤,歡迎指正!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章