Jsoup介绍
jsoup是一款Java的HTMIL解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。.
jsoup的主要功能如下:
- 从一个URL,文件(HTML文件)或字符串中解析HTML;
- 使用DOM 或 CSS选择器来查找、取出数据;
- 可操作HTML元素、属性、文本;
####相应依赖
<!-- jsoup-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.2</version>
</dependency>
<!-- commons-io:用于操作文件-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- commons-lang3:使用StringUtils工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
使用
1. 解析url地址(使用比较少):
public void testUrl() throws Exception{
// 解析url地址,第一个参数是访问的url,第二个参数是访问的时候的超时时间
Document doc= Jsoup.parse(new URL("http://www.itcast.cn"), 1000);
// 使用标签选择器,获取title标签中的内容 .first():表示的为第一个element .text():表示获得文档中的内容
String title = doc.getElementsByTag("title").first().text();
// 打印测试
System.out.println(title);
}
为什么要使用httpclient发出http请求解析数据,而不是直接使用jsoup?
虽然使用Jsoup可以替代HttpClient直接发起请求解析数据,但是往往不会这样用,因为实际的开发过程中,需要使用到多线程,连接池,代理等等方式,而jsoup对这些的支持并不是很好,所以我们一般把jsoup 仅仅作为 Html解析工具使用。
2. 解析字符串(使用比较少):
public void testString() throws Exception{
// 使用工具类读取文件,获取字符串
String content = FileUtils.readFileToString(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");
// 解析字符串
Document document = Jsoup.parse(content);
// 获得title的内容
String title = document.getElementsByTag("title").first().text();
System.out.println(title);
}
3. 解析html文件(使用比较少):
public void testFile() throws Exception{
// 解析文件
Document doc = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");
String title = doc.getElementsByTag("title").first().text();
System.out.println(title);
}
4. 使用dom方式遍历文档
元素获取:
- 根据id查询元素getElementByld
- 根据标签获取元素getElementsByTag
- 根据class获取元素getElementsByClass
- 根据属性获取元素getElementsByAttribute
public void testDom() throws Exception{
// 解析文件,获取Document对象
Document document = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");
//1. 根据id查询元素getElementByld
//Element element = document.getElementById("city_bj");
//2. 根据标签获取元素getElementsByTag
//Element element = document.getElementsByTag("span").first();
//3. 根据class获取元素getElementsByClass
//Element element = document.getElementsByClass("class_a class_b").first();
//4. 根据属性获取元素getElementsByAttribute
//Element element = document.getElementsByAttribute("abc").first();
//5. 通过属性+属性值获取元素
Element element = document.getElementsByAttributeValue("href", "http://www.gz.itcast.cn").first();
//打印元素的内容
System.out.println("获取到的元素内容==>"+element.text());
}
从元素中获取数据
- 从元素中获取id
- 从元素中获取className.
- 从元素中获取属性的值 attr
- 从元素中获取所有属性attributes
- 从元素中获取文本内容text
// 解析文件,获得Document文档
Document document = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");
// 根据id获取元素
Element element = document.getElementById("test");
String str = null;
//从元素中获取数据
//1. 从元素中获取id
str = element.id();
//2. 从元素中获取className
str = element.className();
// Set<String> classSet = element.classNames();
// for (String s : classSet) {
// System.out.println(s);
// }
//3. 从元素中获取属性的值 attr
str = element.attr("class");
//4. 从元素中获取所有属性attributes
Attributes attributes = element.attributes();
System.out.println(attributes.toString());
//5. 从元素中获取文本内容text
str = element.text();
//打印获取到的内容
System.out.println("获取到的数据是=>"+str);
}
5. 使用Selector选择器进行文档的解析
Selector选择器的简单使用
- tagname:通过标签查找元素, 比如: span
- #id:通过ID查找元素, 比如: #city_bj
- .class:通过class名称查找元素, 比如: .class_a
- [attribute]:利用属性查找元素, 比如:[abc]
- [attr=value]:利用属性值来查找元素, 比如: [class=s_name]
public void testSelector() throws Exception{
//解析html文件,获得document对象
Document document = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");
//1. tagname:通过标签查找元素, 比如: span
Elements elements = document.select("span");
// for (Element element : elements) {
// System.out.println(element.text());
// }
//2. #id:通过ID查找元素, 比如: #city_bj
//Element element = document.select("#city_bj").first();
//3. .class:通过class名称查找元素, 比如: .class_a
//Element element = document.select(".class_a").first();
//4. [attribute]:利用属性查找元素, 比如:[abc]
//Element element = document.select("[abc]").first();
//5. [attr=value]:利用属性值来查找元素, 比如: [class=s_name]
Elements elements1 = document.select("[class=s_name]");
for (Element element : elements1) {
System.out.println(element.text());
}
//打印结果
//System.out.println("获取到的结果是=>"+element.text());
}
Selector选择器组合使用
el#id:元素+ID:
比如:h3tcity_bj
el.class:元素+class:
比如:li.class_au
el[attr]:元素+属性名:
比如:span[abc]
任意组合:
比如: span[abc].s_name
ancestor child:查找某个元素下子元素:
比如: .city_con li查找"city_con"下的所有li
parent > child:查找某个父元素下的直接子元素:
比如:.city_con >ul>li查找city_con第一级(直接子元紊)的ul,再找所有ul下的第一级li
parent >*:查找某个父元素下所有直接子元素。
public void testSelector2() throws Exception{
//解析html文件,获得document对象
Document document = Jsoup.parse(new File("C:\\Users\\ZRE\\Desktop\\test.html"), "utf8");
// el#id:元素+ID:
// 比如:h3#city_bj
//Element element = document.select("h3#city_bj").first();
// el.class:元素+class:
// 比如:li.class_a
Element element = document.select("li.class_a").first();
// el[attr]:元素+属性名:
// 比如:span[abc]
element = document.select("span[abc]").first();
// 任意组合:
// 比如: span[abc].s_name
element = document.select("span[abc].s_name").first();
// 父子关系查询
// ancestor child:查找某个元素下子元素:
// 比如: .city_con li查找class为"city_con"下的所有li
Elements elements = document.select(".city_con li");
for (Element element1 : elements) {
System.out.println("遍历的结果=>" + element1.text());
}
//直接子元素
// parent > child:查找某个父元素下的直接子元素:
// 比如:.city_con >ul>li查找city_con第一级(直接子元紊)的ul,再找所有ul下的第一级li
Elements directElements = document.select(".city_con > ul > li");
for (Element directElement : directElements) {
System.out.println("直接子元素遍历=> " + directElement.text());
}
// parent >*:查找某个父元素下所有直接子元素。
Elements allElements = document.select(".city_con > ul > *");
for (Element allElement : allElements) {
System.out.println("父元素下的所有的子元素=>"+ allElement.text());
}
System.out.println("获取到的内容为=>"+element.text());
}
HttpClientUtil工具类
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
@Component
public class HttpUtils {
/**
* 创建连接池管理器(通过构造方法)
*/
private PoolingHttpClientConnectionManager cm;
public HttpUtils() {
this.cm = new PoolingHttpClientConnectionManager();
//指定连接池的连接数、
//设置最大连接数
this.cm.setMaxTotal(100);
//设置每个主机的最大连接数
this.cm.setDefaultMaxPerRoute(10);
}
/**
* 根据请求地址下载页面数据
* @param url
* @return 页面数据
*/
public String doGetHtml(String url){
//获取httpClient对象
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
//创建httpClient请求对象,设置url地址
HttpGet httpGet = new HttpGet(url);
//设置请求信息
httpGet.setConfig(this.getConfig());
CloseableHttpResponse response = null;
try {
//使用httpCLient发起请求,获取相应
response = httpClient.execute(httpGet);
//解析相应,返回结果
if (response.getStatusLine().getStatusCode() == 200){
//判断响应体Entity是否不为空,如果不为空,则可以使用EntityUtils
if (response.getEntity() != null){
String content = EntityUtils.toString(response.getEntity(), "utf8");
//返回结果
return content;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭response
if (response != null){
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//返回空串
return "";
}
/***
* 下载图片
* @param url
* @return 图片名称
*/
public String doGetImage(String url){
//获取httpClient对象
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
//创建httpClient请求对象,设置url地址
HttpGet httpGet = new HttpGet(url);
//设置请求信息
httpGet.setConfig(this.getConfig());
CloseableHttpResponse response = null;
try {
//使用httpCLient发起请求,获取相应
response = httpClient.execute(httpGet);
//解析相应,返回结果
if (response.getStatusLine().getStatusCode() == 200){
if(response.getEntity() != null){
// 下载图片
// 获取图片后缀
String extName = url.substring(url.lastIndexOf("."));
// 创建图片名,重命名图片
String picName = UUID.randomUUID().toString()+extName;
// 下载图片
// 声明outputStream
OutputStream outputStream = new FileOutputStream(new File("C:\\Users\\ZRE\\Desktop\\images\\"+picName));
response.getEntity().writeTo(outputStream);
// 返回图片名称
return picName;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭response
if (response != null){
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//如果下载失败,则返回空串
return "";
}
/***
* 设置请求信息
* @return requestConfig
*/
private RequestConfig getConfig() {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(1000) //创建连接的最长时间
.setConnectionRequestTimeout(500) //获取连接的最长时间
.setSocketTimeout(10*1000) //数据传输的最长时间
.build();
return requestConfig;
}
}