在這篇文章中舒裤,將詳細(xì)介紹 Jsoup 的相關(guān)知識喳资,包括其功能與特點(diǎn)、基本用法腾供、高級應(yīng)用仆邓、原理分析、相關(guān)工具及框架等方面伴鳖。
一节值、功能與特點(diǎn)
Jsoup 是一個用于解析 HTML 的 Java 庫,提供了一組易于使用的 API 和方法榜聂,能夠方便地從網(wǎng)頁中提取出所需數(shù)據(jù)搞疗,以便于 Web 抓取和數(shù)據(jù)挖掘等領(lǐng)域的應(yīng)用。其主要功能如下:
解析 HTML:Jsoup 可以將 HTML 文檔解析成一個 DOM 樹须肆,便于后續(xù)操作匿乃。
查找元素:Jsoup 提供了多種查找元素的方法桩皿,包括根據(jù)標(biāo)簽名、屬性名幢炸、類名泄隔、ID 等查找方式。
獲取元素信息:Jsoup 可以獲取元素的屬性和文本內(nèi)容宛徊。
操作 DOM 樹:Jsoup 可以對 DOM 樹進(jìn)行添加佛嬉、刪除、修改節(jié)點(diǎn)等操作闸天。
支持 CSS 選擇器:Jsoup 可以使用 CSS 選擇器語法查找元素暖呕。
支持鏈?zhǔn)秸{(diào)用:Jsoup 的 API 設(shè)計(jì)簡單易用,支持鏈?zhǔn)秸{(diào)用号枕,代碼清晰簡潔缰揪。
支持 UTF-8 編碼:Jsoup 默認(rèn)采用 UTF-8 編碼處理文本,能夠處理中文等特殊字符葱淳。
二钝腺、基本用法
- 導(dǎo)入 Jsoup
在 Java 代碼中使用 Jsoup 需要先導(dǎo)入 Jsoup 相關(guān)的依賴庫,可以通過 Maven 或手動安裝兩種方式來實(shí)現(xiàn)赞厕。例如使用 Maven 導(dǎo)入 Jsoup:
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>x.x.x</version>
</dependency>
其中 x.x.x 表示需要使用的 Jsoup 版本號艳狐。
- 連接 URL
Jsoup.connect(String url)
方法用于連接指定 URL,并返回一個 Connection
對象皿桑,其后可以鏈?zhǔn)秸{(diào)用其他參數(shù)設(shè)置方法進(jìn)行個性化定制毫目。例如:
Connection conn = Jsoup.connect("http://example.com/")
.userAgent("Mozilla")
.timeout(5000)
.referrer("http://google.com")
.header("Accept-Language", "en-US");
常用參數(shù)設(shè)置方法如下:
- userAgent(String userAgent):設(shè)置用戶代理
- timeout(int milliseconds):設(shè)置連接超時(shí)時(shí)間
- ignoreHttpErrors(boolean ignore):是否忽略 HTTP 錯誤(404、500 等)
- ignoreContentType(boolean ignore):是否忽略內(nèi)容類型
- referrer(String referrer):設(shè)置 Referrer
- headers(Map<String, String> headers):設(shè)置請求頭
- 獲取HTML內(nèi)容
Connection.get()
方法用于獲取與此連接對應(yīng)的 HTML 文檔诲侮,并返回一個 Document
對象镀虐。例如:
Document doc = Jsoup.connect("http://example.com/").get();
如果需要使用 POST 請求模聋,則可以使用 Connection.post()
方法:
Document doc = Jsoup.connect("http://example.com/login")
.data("username", "admin")
.data("password", "123456")
.post();
需要注意的是叮盘,如果提交表單時(shí)需要使用 enctype=”multipart/form-data” 類型耿战,則不能使用 Connection.data()
方法衅谷。
- 解析HTML內(nèi)容
Jsoup 提供了許多方法和工具來解析 HTML 內(nèi)容,例如根據(jù)標(biāo)簽名/屬性名/類名查找元素矿微、遍歷 DOM 樹座慰、獲取元素的屬性和文本內(nèi)容等仑氛。
-
解析 HTML 字符串:
parse(String html)
方法可用于解析一個 HTML 字符串坝疼,并將其轉(zhuǎn)換為Document
對象搜贤。例如:String html = "<html><head><title>Jsoup Example</title></head><body><p>Hello World!</p></body></html>"; Document doc = Jsoup.parse(html);
-
查找元素:
-
Document.select(String cssQuery)
方法可以根據(jù) CSS 選擇器選取元素,返回一個Elements
對象钝凶。例如:Elements links = doc.select("a[href]");
-
Element.getElementsByTag(String tag)
方法可用于根據(jù)標(biāo)簽名選取元素仪芒,返回一個Elements
對象。例如:Elements paragraphs = doc.getElementsByTag("p");
-
Element.getElementsByAttribute(String key)
方法可用于根據(jù)屬性名選取元素,返回一個Elements
對象桌硫。例如:Elements links = doc.getElementsByAttribute("href");
-
Element.getElementsByAttributeValue(String key, String value)
方法可用于根據(jù)屬性名和屬性值選取元素夭咬,返回一個Elements
對象。例如:Elements links = doc.getElementsByAttributeValue("rel", "nofollow");
-
Element.getElementsByClass(String className)
方法可用于根據(jù)類名選取元素铆隘,返回一個Elements
對象。例如:Elements images = doc.getElementsByClass("image");
-
-
獲取元素信息:
-
Element.attr(String attributeKey)
方法可用于獲取元素的屬性值南用。例如:String href = link.attr("href");
-
Element.text()
方法可用于獲取元素的文本內(nèi)容膀钠。例如:String text = paragraph.text();
-
-
迭代元素:
-
Elements.eachText()
方法將返回所有元素的文本內(nèi)容,以字符串形式返回裹虫。例如:String allText = doc.select("body").eachText().toString();
-
Elements.iterator()
方法返回一個迭代器肿嘲,用于遍歷元素集合。例如:Iterator<Element> iter = doc.select("a[href]").iterator(); while (iter.hasNext()) { Element link = iter.next(); String href = link.attr("href"); System.out.println(href); }
-
- 操作DOM樹
Jsoup 提供了許多方法和工具來操作 DOM 樹筑公,例如添加雳窟、刪除、修改節(jié)點(diǎn)等操作匣屡。
-
添加節(jié)點(diǎn):
-
Element.append(String html)
方法可用于向元素的末尾添加子元素封救。例如:Element div = doc.select("div").first(); div.append("<p>Hello Jsoup</p>");
-
Element.prepend(String html)
方法可用于向元素的開頭添加子元素。例如:Element div = doc.select("div").first(); div.prepend("<p>Hello Jsoup</p>");
-
Element.html(String html)
方法可用于替換元素內(nèi)部的 HTML 內(nèi)容捣作。例如:Element div = doc.select("div").first(); div.html("<p>Hello Jsoup</p>");
-
Element.text(String text)
方法可用于替換元素內(nèi)部的文本內(nèi)容誉结。例如:Element div = doc.select("div").first(); div.text("Hello Jsoup");
-
-
刪除節(jié)點(diǎn):
-
Element.empty()
方法可用于刪除元素內(nèi)部的所有子元素。例如:Element div = doc.select("div").first(); div.empty();
-
Element.remove()
方法可用于刪除元素本身券躁。例如:Element div = doc.select("div").first(); div.remove();
-
-
修改節(jié)點(diǎn):
-
Element.attr(String attributeKey, String attributeValue)
方法可用于修改元素的屬性值惩坑。例如:Element link = doc.select("a[href]").first(); link.attr("href", "http://example.com");
-
Element.addClass(String className)
方法可用于向元素添加類名。例如:Element div = doc.select("div").first(); div.addClass("highlight");
-
Element.removeClass(String className)
方法可用于刪除元素的類名也拜。例如:Element div = doc.select("div").first(); div.removeClass("highlight");
-
三以舒、高級應(yīng)用
- 處理錯誤和異常
在解析 HTML 時(shí),有可能會出現(xiàn)各種錯誤和異常慢哈,例如網(wǎng)絡(luò)超時(shí)蔓钟、HTTP 錯誤、HTML 解析錯誤等岸军。為了保證程序的健壯性和穩(wěn)定性奋刽,需要對這些錯誤進(jìn)行處理。
可以使用 try-catch 塊來捕獲異常艰赞,并采取相應(yīng)的措施進(jìn)行處理佣谐。例如:
try {
Document doc = Jsoup.connect("http://example.com/").get();
} catch (IOException e) {
System.err.println("IO Exception: " + e.getMessage());
} catch (IllegalArgumentException e) {
System.err.println("Illegal Argument Exception: " + e.getMessage());
}
- 使用代理服務(wù)器
在實(shí)際應(yīng)用中,有時(shí)需要使用代理服務(wù)器來訪問互聯(lián)網(wǎng)方妖,以便實(shí)現(xiàn)一些特殊需求狭魂,例如爬蟲、數(shù)據(jù)挖掘等〈瞥危可以使用 Proxy
類來設(shè)置代理服務(wù)器斋泄。
String proxyHost = "proxy.example.com";
int proxyPort = 8080;
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
Document doc = Jsoup.connect("http://example.com/").proxy(proxy).get();
- 加載本地 HTML 文件
除了從 URL 加載 HTML 文檔外,還可以從本地文件系統(tǒng)加載 HTML 文件镐牺,以便進(jìn)行離線處理炫掐。可以使用 File
類來指定本地文件路徑睬涧,并使用 Jsoup.parse(File in, String charsetName)
方法來解析文件募胃。
File input = new File("input.html");
Document doc = Jsoup.parse(input, "UTF-8");
- 處理 AJAX 網(wǎng)頁
在一些新型的網(wǎng)站中,由于采用了 AJAX 技術(shù)畦浓,頁面內(nèi)容可能會動態(tài)生成痹束,而不是直接從服務(wù)器端加載。這時(shí)候讶请,需要使用一些高級技巧來處理 AJAX 網(wǎng)頁祷嘶,例如 PhantomJS、Selenium 等技術(shù)夺溢。
四论巍、原理分析
Jsoup 的內(nèi)部實(shí)現(xiàn)原理比較復(fù)雜,主要涉及到 HTML 解析器企垦、DOM 樹構(gòu)建器环壤、字符編碼處理器等組件。其中钞诡,HTML 解析器是核心組件之一郑现,實(shí)現(xiàn)了對 HTML 語法的解析和分詞,將 HTML 文檔轉(zhuǎn)換成一個 DOM 樹荧降。
具體而言接箫,HTML 解析器采用了一種基于狀態(tài)轉(zhuǎn)移的解析算法,即根據(jù)當(dāng)前狀態(tài)和輸入字符朵诫,確定下一步的狀態(tài)和動作辛友,并將解析過程記錄在一個狀態(tài)棧中。當(dāng)解析完成后剪返,棧中保存的狀態(tài)信息即為最終的 DOM 樹結(jié)構(gòu)废累。
DOM 樹構(gòu)建器則負(fù)責(zé)將解析完成的狀態(tài)棧轉(zhuǎn)換成一個 DOM 樹對象,以方便后續(xù)操作脱盲。字符編碼處理器則負(fù)責(zé)將 HTML 文檔中的特殊字符(例如中文邑滨、符號等)進(jìn)行編碼和解碼,以保證在解析過程中不會出現(xiàn)亂碼或錯誤钱反。
五掖看、相關(guān)工具及框架
除了 Jsoup 之外匣距,還有許多其他的 HTML 解析工具和框架可供選擇,具體如下:
- Jsoup:一款輕量級的 Java HTML 解析器
- NekoHTML:一款基于 Xerces 的輕量級 HTML 解析器哎壳,支持 SAX 和 DOM 模式
- HTML Parser:一款基于 Java 的 HTML 解析器毅待,支持 SAX 和 DOM 模式
- Jericho HTML Parser:一款開源的 HTML 解析器,可以解析標(biāo)準(zhǔn) HTML归榕、XHTML尸红、XML 等格式
- TagSoup:一款開源的 HTML/XML 解析器,可以處理 HTML5蹲坷、XML 等格式
- Selenium:一款自動化測試工具驶乾,可以模擬瀏覽器行為,支持處理 AJAX 和 JavaScript 網(wǎng)頁
- PhantomJS:一種無界面的 WebKit 瀏覽器循签,支持處理 AJAX 和 JavaScript 網(wǎng)頁,可以嵌入到 Java 程序中進(jìn)行使用