jsoup是一款Java的HTML解析器,主要用來對HTML解析。在爬蟲的時候,當我們用HttpClient之類的架構,擷取到網頁源碼之後,需要從網頁源碼中取出我們想要的内容,就可以使用jsoup這類HTML解析器了。可以非常輕松的實作。
雖然jsoup也支援從某個位址直接去爬取網頁源碼,但是隻支援HTTP,HTTPS協定,支援不夠豐富。是以,主要還是用來對HTML進行解析。
#Jsoup位址
https://www.open-open.com/jsoup/
#在maven中央倉庫的位址
https://mvnrepository.com/artifact/org.jsoup/jsoup/1.11.3
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
Jsoup使用起來類似于JQuery,都是通過id、class、标簽來進行DOM操作
public static void main(String[] args) throws IOException {
Document doc = Jsoup.connect("https://www.bilibili.com/").get();
//标題
System.out.println(doc.title());
//keyword
System.out.println(doc.text());
//擷取class為t的DOM集合
Elements elements = doc.getElementsByClass("t");
for (Element element : elements) {
System.out.println(element.html());
}
}
其中Jsoup.connect("xxx")方法傳回一個org.jsoup.Connection對象。
在Connection對象中,可以執行get或者post來執行請求。但是在執行請求之前,可以使用Connection對象來設定一些請求資訊。比如:頭資訊,cookie,請求等待時間,代理等等來模拟浏覽器的行為。
Map<String,String> header = new HashMap<>();
header.put("Server","Apache ");
header.put("Date","Tue, 03 Dec 2019 06:37:08 GMT");
header.put("Content-Type","text/html;charset=UTF-8");
header.put("Transfer-Encoding","chunked");
header.put("Connection","keep-alive");
header.put("Vary","Accept-Encoding");
header.put("X-Han","shotFirst");
header.put("Content-Language","en-ENGLISH");
header.put("Set-Cookie","org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=en_ENGLISH; Path=/");
header.put("Expires","Mon, 01 Jan 1999 00:00:00 GMT");
header.put("Pragma","no-cache");
header.put("Cteonnt-Length","164070");
header.put("Content-Encoding","gzip");
header.put("referer","http://localhost/");
Document doc = Jsoup.connect("https://homestarlight.manufacturer.globalsources.com/si/6008853576646/Homepage.htm?source=GSOLBigPP_A")
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
.headers(header)
.timeout(30000)
.get();
注:以上請求頭都是抄PostMan抄來的,一般抄PostMan就能擷取到絕大多數網站的DOM結構
Document中提供了兩類方法來擷取注定的元素:1:DOM法、2:類JQuery法
1:DOM法
Document doc = Jsoup.connect("url").get();
//通過id來擷取
doc.getElementById("username");
//通過标簽名字來擷取
doc.getElementsByTag("a");
//通過類名來擷取
doc.getElementsByClass("nav-item");
//通過屬性名字來擷取
doc.getElementsByAttribute("id");
//通過指定的屬性名字,屬性值來擷取
doc.getElementsByAttributeValue("class", "nav-item");
//擷取所有元素
Elements allElements = doc.getAllElements();
2、通過類似于css或jQuery的選擇器來查找元素
public Elements select(String cssQuery)
File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");
//帶有href屬性的a元素
Elements links = doc.select("a[href]");
//擴充名為.png的圖檔
Elements pngs = doc.select("img[src$=.png]");
//class等于masthead的div标簽
Element masthead = doc.select("div.masthead").first();
//在h3元素之後的a元素
Elements resultLinks = doc.select("h3.r > a");
//查找class為nav-link-ul的<ul>标簽下帶href屬性的<a>标簽
Elements elements = doc.select("ul.nav-link-ul a[href]");
如果一個标簽有多個class如何查詢,如下圖所示<ul>有兩個class

//多個class之間用.連接配接
Elements select = document.select("ul.spNav.clear
擷取到元素後,可以通過如下方法讀取該元素的屬性、值、html内容
attr(String key)擷取屬性attr(String key, String value)設定屬性
attributes()擷取所有屬性
id(), className() and classNames()
text()擷取文本内容text(String value) 設定文本内容
html()擷取元素内HTMLhtml(String value)設定元素内的HTML内容
outerHtml()擷取元素外HTML内容
data()擷取資料内容(例如:script和style标簽)
tag() and tagName()
删除DOM裡的某個标簽或class(Document或Element都能用):
//删除element裡全部div标簽
element.select("div").remove();
//删除document裡所有<div class="spContact clearfix"></div>标簽
document.select("div.spContact.clearfix").remove();
//删除所有div裡class屬性
document.select("div").removeAttr("class")
例如爬取B站頭部導航:
public static void main(String[] args) throws IOException {
Map<String, String> header = new HashMap<>();
header.put("Server", "Apache ");
header.put("Date", "Tue, 03 Dec 2019 06:37:08 GMT");
header.put("Content-Type", "text/html;charset=UTF-8");
header.put("Transfer-Encoding", "chunked");
header.put("Connection", "keep-alive");
header.put("Vary", "Accept-Encoding");
header.put("X-Han", "shotFirst");
header.put("Content-Language", "en-ENGLISH");
header.put("Set-Cookie", "org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=en_ENGLISH; Path=/");
header.put("Expires", "Mon, 01 Jan 1999 00:00:00 GMT");
header.put("Pragma", "no-cache");
header.put("Cteonnt-Length", "164070");
header.put("Content-Encoding", "gzip");
header.put("referer", "http://localhost/");
Document doc = Jsoup.connect("https://www.bilibili.com/")
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
.headers(header)
.timeout(30000)
.get();
//查找class為nav-link-ul的<ul>标簽下帶href的<a>标簽
Elements elements = doc.select("ul.nav-link-ul a[href]");
for (Element element : elements) {
System.out.println("html:" + element.html());
System.out.println("text:" + element.text());
System.out.println("attributes:" + element.attributes());
System.out.println("attr:" + element.attr("href"));
System.out.println("tag:" + element.tag());
System.out.println("tagName:" + element.tagName());
System.out.println("=====================");
}
}