1、Jsoup是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
2、Jsoup 的主要功能,如下所示:
1)、从一个URL,文件或字符串中解析HTML;
2)、使用DOM或CSS选择器来查找、取出数据;
3)、可操作HTML元素、属性、文本;
4)、Jsoup 是基于MIT协议发布的,可放心使用于商业项目。
3、httpClient 结合Jsoup 获取到网页内容进行解析,首先需要引入httpClient和Jsoup的依赖,如下所示:
1 <project xmlns="http://maven.apache.org/POM/4.0.0" 2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 4 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.bie</groupId> 8 <artifactId>jsoup</artifactId> 9 <version>0.0.1-SNAPSHOT</version> 10 <packaging>jar</packaging> 11 12 <name>jsoup</name> 13 <url>http://maven.apache.org</url> 14 15 <properties> 16 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 17 </properties> 18 19 <dependencies> 20 <!-- 添加httpclient支持 --> 21 <dependency> 22 <groupId>org.apache.httpcomponents</groupId> 23 <artifactId>httpclient</artifactId> 24 <version>4.5.2</version> 25 </dependency> 26 <!-- jsoup版本依赖 --> 27 <dependency> 28 <groupId>org.jsoup</groupId> 29 <artifactId>jsoup</artifactId> 30 <version>1.8.3</version> 31 </dependency> 32 </dependencies> 33 </project>
虽然使用Jsoup可以替代HttpClient直接发起请求解析数据,但是往往不会这样用,因为实际的开发过程中,需要使用到多线程,连接池,代理等等技术,而jsoup对这些技术的支持并不是很好,所以jsoup一般仅仅作为Html解析工具使用。
1 package com.bie.spider.jsoup; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.net.MalformedURLException; 6 import java.net.URL; 7 8 import org.apache.commons.io.FileUtils; 9 import org.jsoup.Jsoup; 10 import org.jsoup.nodes.Document; 11 import org.jsoup.nodes.Element; 12 13 /** 14 * 15 * @author 16 * 17 */ 18 public class JsoupDocument { 19 20 /** 21 * 虽然使用Jsoup可以替代HttpClient直接发起请求解析数据,但是往往不会这样用, 22 * 因为实际的开发过程中,需要使用到多线程,连接池,代理等等技术, 23 * 而jsoup对这些技术的支持并不是很好, 所以jsoup一般仅仅作为Html解析工具使用 24 * 25 * @throws MalformedURLException 26 * @throws IOException 27 */ 28 public static void inputUrl() throws MalformedURLException, IOException { 29 // Jsoup可以直接输入url,它会发起请求并获取数据,封装为Document对象 30 // 使用jsoup解析url 31 Document doc = Jsoup.parse(new URL("https://www.autohome.com.cn/bestauto/"), 10000); 32 33 // 把获取的内容输出为文件 34 FileUtils.writeStringToFile(new File("D:/test.html"), doc.toString(), "UTF-8"); 35 36 // 获取title 37 Element element = doc.getElementsByTag("title").first(); 38 39 // 打印title内容 40 System.out.println(element.text()); 41 } 42 43 /** 44 * 输入字符串,Jsoup可以直接输入字符串,并封装为Document对象 45 * 46 * @throws MalformedURLException 47 * @throws IOException 48 */ 49 public static void inputCharacter() throws MalformedURLException, IOException { 50 // 读取文件,获取字符串 51 String html = FileUtils.readFileToString(new File("D:/test.html"), "UTF-8"); 52 53 // 解析字符串 54 Document doc = Jsoup.parse(html); 55 56 // 获取title标签 57 Element element = doc.getElementsByTag("title").first(); 58 59 // 打印title内容 60 System.out.println(element.text()); 61 } 62 63 /** 64 * 输入文件,Jsoup可以直接输入文件,并封装为Document对象 65 * 66 * @throws MalformedURLException 67 * @throws IOException 68 */ 69 public static void inputFile() throws MalformedURLException, IOException { 70 // 使用jsoup解析文件 71 Document doc = Jsoup.parse(new File("D:/test.html"), "UTF-8"); 72 73 // 获取title标签 74 Element element = doc.getElementsByTag("title").first(); 75 76 // 打印title内容 77 System.out.println(element.text()); 78 } 79 80 public static void main(String[] args) throws MalformedURLException, IOException { 81 // 输入url 82 inputUrl(); 83 // 输入字符串 84 inputCharacter(); 85 // 输入文件 86 inputFile(); 87 } 88 89 }
httpClient 结合Jsoup 获取到网页内容进行解析,具体代码,如下所示:
1 package com.bie.jsoup; 2 3 import java.io.IOException; 4 5 import org.apache.http.Header; 6 import org.apache.http.HttpEntity; 7 import org.apache.http.ParseException; 8 import org.apache.http.StatusLine; 9 import org.apache.http.client.ClientProtocolException; 10 import org.apache.http.client.methods.CloseableHttpResponse; 11 import org.apache.http.client.methods.HttpGet; 12 import org.apache.http.impl.client.CloseableHttpClient; 13 import org.apache.http.impl.client.HttpClients; 14 import org.apache.http.util.EntityUtils; 15 import org.jsoup.Jsoup; 16 import org.jsoup.nodes.Document; 17 import org.jsoup.nodes.Element; 18 import org.jsoup.select.Elements; 19 20 public class HttpClientToJsoup { 21 22 // 设置请求头消息 User-Agent 模拟浏览器 23 private static String UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0"; 24 25 /** 26 * HttpGet请求操作 27 */ 28 public static void httpGetRequest() { 29 // 第一步,获取到httpClient客户端实例,获取到一个可关闭的httpClient客户端实例。 30 CloseableHttpClient httpClient = HttpClients.createDefault(); 31 // 第二步,创建HttpGet或者HttpPost实例。 32 String uri = "https://www.cnblogs.com/biehongli"; 33 HttpGet httpGet = new HttpGet(uri); 34 // 设置请求头消息 User-Agent 模拟浏览器 35 httpGet.setHeader("User-Agent", UserAgent); 36 37 // 定义一个可响应的实例对象。 38 CloseableHttpResponse response = null; 39 try { 40 // 第三步,发布一个请求,使用httpClient实例发送一个http协议的Get请求。 41 response = httpClient.execute(httpGet); 42 // 获取到响应的状态 43 StatusLine statusLine = response.getStatusLine(); 44 System.out.println("响应状态: " + statusLine.toString() + ", 响应码: " + statusLine.getStatusCode()); 45 } catch (ClientProtocolException e) { 46 // http协议异常 47 e.printStackTrace(); 48 } catch (IOException e) { 49 // io异常 50 e.printStackTrace(); 51 } 52 // 第四步,获取到返回的实体对象 53 HttpEntity entity = response.getEntity(); 54 // 获取响应内容类型 Content-Type,获取到响应类型,从而过滤一些不想要的东西 55 Header contentType = entity.getContentType(); 56 // 打印响应信息 57 System.out.println("name : " + contentType.getName() + " , value: " + contentType.getValue()); 58 59 // 将返回结果转换为字符串进行查看(网页内容),参数一是请求返回的entity,参数二是字符集编码 60 String result = null; 61 try { 62 result = EntityUtils.toString(entity, "UTF-8"); 63 } catch (ParseException e) { 64 e.printStackTrace(); 65 } catch (IOException e) { 66 e.printStackTrace(); 67 } 68 // 打印请求返回的结果 69 // System.out.println(result.toString()); 70 71 // 讲获取到网页转换成为jsoup进行处理,返回结果为Document文档 72 Document document = Jsoup.parse(result); 73 Elements elements = document.getElementsByTag("title"); 74 Element element = elements.get(0); 75 System.out.println("获取到的标题內容: " + element.text().toString()); 76 77 // 获取到自己的博客题目名称内容 78 Elements elementsByClass = document.getElementsByClass("postTitle2"); 79 for (Element e : elementsByClass) { 80 System.out.println("获取到的标题内容是: " + e.text()); 81 } 82 83 // 第五步,关闭流,释放资源 84 try { 85 response.close(); 86 httpClient.close(); 87 } catch (IOException e) { 88 e.printStackTrace(); 89 } 90 } 91 92 public static void main(String[] args) { 93 HttpClientToJsoup.httpGetRequest(); 94 } 95 96 }
4、Jsoup的主要作用是,用HttpClient获取到网页后,具体的网页提取需要的信息的时候 ,就用到Jsoup,Jsoup可以使用强大的类似Jquery,css选择器,来获取需要的数据;
Jsoup官方地址:https://jsoup.org/
Jsoup最新下载:https://jsoup.org/download
Jsoup学习文档:https://jsoup.org/cookbook/introduction/parsing-a-document
5、Jsoup查找DOM元素的主要方法,如下所示:
1)、getElementById(String id) 根据 id 来查询 DOM。
2)、getElementsByTag(String tagName) 根据 tag 名称来查询 DOM。
3)、getElementsByClass(String className) 根据样式名称来查询 DOM。
4)、getElementsByAttribute(String key) 根据属性名,标签的属性元素来查询 DOM。
5)、getElementsByAttributeValue(String key,String value) 根据属性名和属性值来查询 DOM。
如果满足不了自己的需求,可以使用Jsoup 的选择器语法查找 DOM 元素,如下所示:
1 package com.bie.jsoup; 2 3 import java.io.IOException; 4 5 import org.apache.http.Header; 6 import org.apache.http.HttpEntity; 7 import org.apache.http.ParseException; 8 import org.apache.http.StatusLine; 9 import org.apache.http.client.ClientProtocolException; 10 import org.apache.http.client.methods.CloseableHttpResponse; 11 import org.apache.http.client.methods.HttpGet; 12 import org.apache.http.impl.client.CloseableHttpClient; 13 import org.apache.http.impl.client.HttpClients; 14 import org.apache.http.util.EntityUtils; 15 import org.jsoup.Jsoup; 16 import org.jsoup.nodes.Document; 17 import org.jsoup.nodes.Element; 18 import org.jsoup.select.Elements; 19 20 public class HttpClientToJsoup { 21 22 // 设置请求头消息 User-Agent 模拟浏览器 23 private static String UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0"; 24 25 /** 26 * HttpGet请求操作 27 */ 28 public static void httpGetRequest() { 29 // 第一步,获取到httpClient客户端实例,获取到一个可关闭的httpClient客户端实例。 30 CloseableHttpClient httpClient = HttpClients.createDefault(); 31 // 第二步,创建HttpGet或者HttpPost实例。 32 String uri = "https://www.cnblogs.com/biehongli"; 33 HttpGet httpGet = new HttpGet(uri); 34 // 设置请求头消息 User-Agent 模拟浏览器 35 httpGet.setHeader("User-Agent", UserAgent); 36 37 // 定义一个可响应的实例对象。 38 CloseableHttpResponse response = null; 39 try { 40 // 第三步,发布一个请求,使用httpClient实例发送一个http协议的Get请求。 41 response = httpClient.execute(httpGet); 42 // 获取到响应的状态 43 StatusLine statusLine = response.getStatusLine(); 44 System.out.println("响应状态: " + statusLine.toString() + ", 响应码: " + statusLine.getStatusCode()); 45 } catch (ClientProtocolException e) { 46 // http协议异常 47 e.printStackTrace(); 48 } catch (IOException e) { 49 // io异常 50 e.printStackTrace(); 51 } 52 // 第四步,获取到返回的实体对象 53 HttpEntity entity = response.getEntity(); 54 // 获取响应内容类型 Content-Type,获取到响应类型,从而过滤一些不想要的东西 55 Header contentType = entity.getContentType(); 56 // 打印响应信息 57 System.out.println("name : " + contentType.getName() + " , value: " + contentType.getValue()); 58 59 // 将返回结果转换为字符串进行查看(网页内容),参数一是请求返回的entity,参数二是字符集编码 60 String result = null; 61 try { 62 result = EntityUtils.toString(entity, "UTF-8"); 63 } catch (ParseException e) { 64 e.printStackTrace(); 65 } catch (IOException e) { 66 e.printStackTrace(); 67 } 68 // 打印请求返回的结果 69 // System.out.println(result.toString()); 70 71 // 讲获取到网页转换成为jsoup进行处理,返回结果为Document文档 72 Document document = Jsoup.parse(result); 73 Elements elements = document.getElementsByTag("title"); 74 Element element = elements.get(0); 75 System.out.println("获取到的标题內容: " + element.text().toString()); 76 77 // 通过选择器查找所有博客链接DOM,获取到自己的博客题目名称内容 78 // 使用Jsoup的选择器 79 Elements select = document.select("#centercontent .day .postTitle .postTitle2"); 80 for (Element e : select) { 81 System.out.println("博客标题:" + e.text()); 82 } 83 84 // 带有href属性的a元素 85 Elements selectHref = document.select(".postTitle a[href]"); 86 for (Element e : selectHref) { 87 System.out.println("博客标题:" + e.text()); 88 } 89 90 // 查找扩展名为.png的图片DOM节点 91 Elements imgElements = document.select("img[src$=.png]"); 92 for (Element e : imgElements) { 93 System.out.println(e.toString()); 94 } 95 96 // 获取tag是title的所有DOM元素 97 Element first = document.getElementsByTag("title").first(); 98 String title = first.text(); // 返回元素的文本 99 System.out.println("网页标题是:" + title); 100 101 // 第五步,关闭流,释放资源 102 try { 103 response.close(); 104 httpClient.close(); 105 } catch (IOException e) { 106 e.printStackTrace(); 107 } 108 } 109 110 public static void main(String[] args) { 111 HttpClientToJsoup.httpGetRequest(); 112 } 113 114 }
6、使用选择器语法查找元素,Jsoup elements对象支持类似于CSS (或jquery)的选择器语法,来实现非常强大和灵活的查找功能。这个select 方法在Document, Element,或Elements对象中都可以使用。且是上下文相关的,因此可实现指定元素的过滤,或者链式选择访问。Select方法将返回一个Elements集合,并提供一组方法来抽取和处理结果。如下所示:
1 package com.bie.jsoup; 2 3 import java.io.IOException; 4 5 import org.apache.http.Header; 6 import org.apache.http.HttpEntity; 7 import org.apache.http.ParseException; 8 import org.apache.http.StatusLine; 9 import org.apache.http.client.ClientProtocolException; 10 import org.apache.http.client.methods.CloseableHttpResponse; 11 import org.apache.http.client.methods.HttpGet; 12 import org.apache.http.impl.client.CloseableHttpClient; 13 import org.apache.http.impl.client.HttpClients; 14 import org.apache.http.util.EntityUtils; 15 import org.jsoup.Jsoup; 16 import org.jsoup.nodes.Document; 17 import org.jsoup.nodes.Element; 18 import org.jsoup.select.Elements; 19 20 public class HttpClientToJsoup { 21 22 // 设置请求头消息 User-Agent 模拟浏览器 23 private static String UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0"; 24 25 /** 26 * HttpGet请求操作 27 */ 28 public static void httpGetRequest() { 29 // 第一步,获取到httpClient客户端实例,获取到一个可关闭的httpClient客户端实例。 30 CloseableHttpClient httpClient = HttpClients.createDefault(); 31 // 第二步,创建HttpGet或者HttpPost实例。 32 String uri = "https://www.cnblogs.com/biehongli"; 33 HttpGet httpGet = new HttpGet(uri); 34 // 设置请求头消息 User-Agent 模拟浏览器 35 httpGet.setHeader("User-Agent", UserAgent); 36 37 // 定义一个可响应的实例对象。 38 CloseableHttpResponse response = null; 39 try { 40 // 第三步,发布一个请求,使用httpClient实例发送一个http协议的Get请求。 41 response = httpClient.execute(httpGet); 42 // 获取到响应的状态 43 StatusLine statusLine = response.getStatusLine(); 44 System.out.println("响应状态: " + statusLine.toString() + ", 响应码: " + statusLine.getStatusCode()); 45 } catch (ClientProtocolException e) { 46 // http协议异常 47 e.printStackTrace(); 48 } catch (IOException e) { 49 // io异常 50 e.printStackTrace(); 51 } 52 // 第四步,获取到返回的实体对象 53 HttpEntity entity = response.getEntity(); 54 // 获取响应内容类型 Content-Type,获取到响应类型,从而过滤一些不想要的东西 55 Header contentType = entity.getContentType(); 56 // 打印响应信息 57 System.out.println("name : " + contentType.getName() + " , value: " + contentType.getValue()); 58 59 // 将返回结果转换为字符串进行查看(网页内容),参数一是请求返回的entity,参数二是字符集编码 60 String result = null; 61 try { 62 result = EntityUtils.toString(entity, "UTF-8"); 63 } catch (ParseException e) { 64 e.printStackTrace(); 65 } catch (IOException e) { 66 e.printStackTrace(); 67 } 68 // 打印请求返回的结果 69 // System.out.println(result.toString()); 70 71 // 讲获取到网页转换成为jsoup进行处理,返回结果为Document文档 72 Document document = Jsoup.parse(result); 73 74 // Jsoup 使用selector选择器 75 Elements linkElements = document.select("#centercontent .day .postTitle .postTitle2"); // 通过选择器查找所有博客链接DOM 76 for (Element e : linkElements) { 77 System.out.println("博客标题:" + e.text()); 78 System.out.println("博客地址:" + e.attr("href")); 79 // System.out.println("target:" + e.attr("target")); 80 } 81 82 // Jsoup 使用selector选择器 83 Element linkElement = document.select(".postTitle2").first(); 84 System.out.println("纯文本内容:" + linkElement.text()); 85 System.out.println("Html内容:" + linkElement.html()); 86 87 // 第五步,关闭流,释放资源 88 try { 89 response.close(); 90 httpClient.close(); 91 } catch (IOException e) { 92 e.printStackTrace(); 93 } 94 } 95 96 public static void main(String[] args) { 97 HttpClientToJsoup.httpGetRequest(); 98 } 99 100 }
1 1、Selector选择器概述,如下所示: 2 1)、tagname: 通过标签查找元素,比如:a。 3 2)、ns|tag: 通过标签在命名空间查找元素,比如:可以用 fb|name 语法来查找 <fb:name> 元素。 4 3)、#id: 通过ID查找元素,比如:#logo。 5 4)、.class: 通过class名称查找元素,比如:.masthead。 6 5)、[attribute]: 利用属性查找元素,比如:[href]。 7 6)、[attr=value]: 利用属性值来查找元素,比如:[width=500]。 8 9 10 // 案例使用,使用选择器 11 // tagname: 通过标签查找元素,比如:a 12 str = doc.select("a").first().text(); 13 14 // ns|tag: 通过标签在命名空间查找元素,比如:可以用 fb|name 语法来查找 <fb:name> 元素 15 str = doc.select("jsoup|li").first().text(); 16 17 // #id: 通过ID查找元素,比如:#logo 18 str = doc.select("#auto-header-fenzhan").first().text(); 19 20 // .class: 通过class名称查找元素,比如:.masthead 21 str = doc.select(".orangelink").first().text(); 22 23 // [attribute]: 利用属性查找元素,比如:[href] 24 str = doc.select("[abc]").first().text(); 25 26 // [attr=value]: 利用属性值来查找元素,比如:[width=500] 27 str = doc.select("[class=vlli]").first().text(); 28 29 30 2、Selector选择器组合使用,如下所示: 31 1)、el#id: 元素+ID,比如: div#logo。 32 2)、el.class: 元素+class,比如: div.masthead。 33 3)、el[attr]: 元素+属性名,比如: a[href]。 34 4)、任意组合,比如:a[href].highlight。 35 5)、ancestor child: 查找某个元素下子元素,比如:.body p 查找"body"下的所有 p。 36 6)、parent > child: 查找某个父元素下的直接子元素,比如:div.content > p 查找 p。 37 7)、parent > * 查找某个父元素下所有直接子元素。 38 39 40 // 案例使用,组合选择器 41 // el#id: 元素+ID,比如: div#logo 42 str = doc.select("li#auto-header-fenzhan").first().text(); 43 44 // el.class: 元素+class,比如: div.masthead 45 str = doc.select("a.greylink").first().text(); 46 47 // el[attr]: 元素+属性,比如: a[href] 48 str = doc.select("a[href]").first().attr("href"); 49 50 // 任意组合,比如:a[href].highlight 51 str = doc.select("a[href].greylink").first().attr("href"); 52 53 // ancestor child: 查找某个元素下子元素,比如:可以用.body p 查找"body"下的所有 p 54 str = doc.select("div.mini-left a").text(); 55 56 // parent > child: 查找某个父元素下的直接子元素,比如:div.content > p 查找 p 57 str = doc.select("div.mini-left ul > li").text(); 58 59 // parent > * 查找某个父元素下所有直接子元素 60 Elements elements = doc.select("div.mini-left > *"); 61 for (Element ele : elements) { 62 System.out.println(ele.tagName()); 63 }