Jsoup簡介
Java爬蟲解析HTML文件的工具有:htmlparser
, Jsoup
。本文將會詳細介紹Jsoup
的使用方法,10分鐘搞定Java爬蟲HTML解析。
Jsoup
可以直接解析某個URL地址、HTML文字內容,它提供非常豐富的處理Dom樹的API。如果你使用過JQuery
,那你一定會非常熟悉。
Jsoup
最強大的莫過於它的CSS選擇器支援了。比如:document.select("div.content > div#image > ul > li:eq(2)
。
包引入方法
Maven
新增下面的依賴宣告即可,最新版本是(1.12.1)
<dependency>
<!-- jsoup HTML parser library @ https://jsoup.org/ -->
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
Gradle
// jsoup HTML parser library @ https://jsoup.org/
compile 'org.jsoup:jsoup:1.11.3'
原始碼安裝
當然也可以直接把jar包下載下來,下載地址:https://jsoup.org/download
# git獲取程式碼
git clone https://github.com/jhy/jsoup.git
cd jsoup
mvn install
# 下載程式碼
curl -Lo jsoup.zip https://github.com/jhy/jsoup/archive/master.zip
unzip jsoup.zip
cd jsoup-master
mvn install
Jsoup解析方法
Jsoup
支援四種方式解析Document,即可以輸入四種內容得到一個Document:
- 解析字串
- 解析
body
片段 - 從一個URL解析
- 從一個檔案解析
字串解析示例
字串中必須包含head
和body
元素。
String html = "<html><head><title>First parse</title></head>"
+ "<body><p>Parsed HTML into a doc.</p></body></html>";
Document doc = Jsoup.parse(html);
HTML片段解析
String html = "<div><p>Lorem ipsum.</p>";
Document doc = Jsoup.parseBodyFragment(html);
Element body = doc.body();
從URL解析
Document doc = Jsoup.connect("http://example.com/").get();
String title = doc.title();
還可以攜帶cookie等引數:
Document doc = Jsoup.connect("http://example.com")
.data("query", "Java")
.userAgent("Mozilla")
.cookie("auth", "token")
.timeout(3000)
.post();
從檔案解析
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");
Jsoup遍歷DOM樹的方法
使用標準的DOM方法
Jsoup
封裝並實現了DOM裡面常用的元素遍歷方法:
- 根據id查詢元素:
getElementById(String id)
- 根據標籤查詢元素:
getElementsByTag(String tag)
- 根據class查詢元素:
getElementsByClass(String className)
- 根據屬性查詢元素:
getElementsByAttribute(String key)
- 兄弟遍歷方法:
siblingElements()
,firstElementSibling()
,lastElementSibling()
;nextElementSibling()
,previousElementSibling()
- 層級之間遍歷:
parent()
,children()
,child(int index)
這些方法會返回Element
或者Elements
節點物件,這些物件可以使用下面的方法獲取一些屬性:
attr(String key)
: 獲取某個屬性值attributes()
: 獲取節點的所有屬性id()
: 獲取節點的idclassName()
: 獲取當前節點的class名稱classNames()
: 獲取當前節點的所有class名稱text()
: 獲取當前節點的textNode內容html()
: 獲取當前節點的 inner HTMLouterHtml()
: 獲取當前節點的 outer HTMLdata()
: 獲取當前節點的內容,用於script
或者style
標籤等tag()
: 獲取標籤tagName()
: 獲取當前節點的標籤名稱
有了這些API,就像JQuery
一樣很便利的操作DOM。
強大的CSS選擇器支援
你可能會說htmlparse
支援xpath
,可以很方便的定位某個元素,而不用一層一層地遍歷DOM樹。呼叫方法如下:
document.select(String selector)
: 選擇匹配選擇器的元素,返回是Elements
物件document.selectFirst(String selector)
: 選擇匹配選擇器的第一個元素,返回是一個Element
物件element.select(String selector)
: 也可以直接在Element
物件上執行選擇方法
Jsoup
能夠完美的支援CSS的選擇器語法,可以說對應有前端經驗的開發者來說簡直是福音,不用特意去學習XPath的語法。
比如一個XPath: //*[@id="docs"]/div[1]/h4/a
, 可以轉成等效的CSS選擇器語法: document.select("#docs > div:eq(1) > h4 > a").attr("href");
。
看下面的示例:
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://baidu.com/");
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
下面列出一些常見的選擇器:
- 標籤選擇(如
div
):tag
- id選擇(
#logo
):#id
- class選擇(
.head
):.class
- 屬性選擇(
[href]
):[attribute]
- 屬性值選擇:
[attr=value]
- 屬性字首匹配:
[^attr]
- 屬性簡單正則匹配:
[attr^=value], [attr$=value], [attr*=value], [attr~=regex]
另外還支援下面的組合選擇器:
element#id
: (div#logo
: 選取id
為logo
的div
元素)element.class
: (div.content
: 選擇class
包括content
的div
元素)element[attr]
: (a[href]
: 選擇包含href
的a
元素)ancestor child
: (div p
: 選擇div
元素的所有p後代元素)parent > child
: (p > span
: 選擇p
元素的直接子元素中的span
元素)siblingA + siblingB
: (div.head + div
: 選取div.head
的下一個兄弟div
元素)siblingA ~ siblingX
: (h1 ~ p
: 選取h1
後面的所有p
兄弟元素)el, el, el
: (div.content, div.footer
: 同時選取div.content
和div.footer
)
當然,還支援偽元素選擇器:
:lt(n)
: (div#logo > li:lt(2)
: 選擇id
為logo
的div
元素的前3個li
子元素):gt(n)
:eq(n)
:has(selector)
:not(selector)
:contains(text)
詳細可參考官方選擇器語法文件: https://jsoup.org/cookbook/extracting-data/selector-syntax
Jsoup修改DOM樹結構
當然Jsoup
還支援修改DOM樹結構,真的很像JQuery
。
// 設定屬性
doc.select("div.comments a").attr("rel", "nofollow");
// 設定class
doc.select("div.masthead").attr("title", "jsoup").addClass("round-box");
//
下面的API可以直接操作DOM樹結構:
text(String value)
: 設定內容html(String value)
: 直接替換HTML結構append(String html)
: 元素後面新增節點prepend(String html)
: 元素前面新增節點appendText(String text)
,prependText(String text)
appendElement(String tagName)
,prependElement(String tagName)
參考文件
Jsoup
官網地址: https://jsoup.org/Jsoup
官網指導文件: https://jsoup.org/cookbook/Jsoup
jar包下載地址: https://jsoup.org/downloadJsoup
CSS選擇器參考: https://jsoup.org/cookbook/extracting-data/selector-syntax