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);
}
完結,以上內容如果有誤,歡迎指正!