HttpClient和Jsoup详解

1. 网络爬虫简介

网络爬虫(web crawler),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。

1.1 爬虫入门程序

  1. JDK1.8
  2. IntelliJ IDEA
  3. DEA自带的Maven
环境准备

创建Maven工程itbuild-crawler-first并往pom.xml文件中添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cn.itbuild</groupId>
<artifactId>itbuild-crawler-first</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--引入jar包-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
</project>

添加log4j.properties

1
2
3
4
5
6
7
# A1 在控制台显示日志
log4j.rootLogger=DEBUG,A1
log4j.logger.cn.itbuild=INFO

log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH??ss,SSS} [%t] [%c]-[%p] %m%n
编写代码

CrawlerFirst.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package cn.itbuild.crawler.test;

import org.apache.http.HttpEntity;
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.util.EntityUtils;

import java.io.IOException;
/**
* @Date 2020/12/21 19:03
* @Version 10.21
* @Author DuanChaojie
*/
public class CrawlerFirst {
public static void main(String[] args) throws IOException {
/**
* 1.打开浏览器——创建httpClient对象
*/
CloseableHttpClient httpClient = HttpClients.createDefault();

/**
* 2.输入网址,发起get请求——创建HttpGet对象
*/
HttpGet httpGet = new HttpGet("http://www.itcast.cn/");
/**
* 3.发送请求返回响应
*/
CloseableHttpResponse response = httpClient.execute(httpGet);

/**
* 4.解析响应获取数据
* 判断状态码是否是 200
*/
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
String content = EntityUtils.toString(entity, "utf-8");
System.out.println(content);
}
}

}

1.2 网络爬虫介绍

​ 在大数据时代,信息的采集是一项重要的工作,而互联网中的数据是海量的,如果单纯靠人力进行信息采集,不仅低效繁琐,搜集的成木也会提高。如何自动高效地获取互联网中我们感兴趣的信息并为我们所用是一个重要的问题,而爬虫技术就是为了解决这些问题而生的。

​ 网络爬虫(Web crawler)也叫做网络机器人,可以代替人们自动地在互联网中进行数据信息的采集与整理。它是一种按照一定的规则,自动地抓取万维网信息的程序或者脚木,可以自动采集所有其能够访问到的页面内容,以获取相关数据。

​ 从功能上来讲,爬虫一般分为数据采集,处理,储存三个部分。爬虫从一个或若干初始网页的URL开始,获得初始网页上的URL,在抓取网页的过程中,不断从当前页面上抽取新的URL放入队列,直到满足系统的一定停止条件。

1.3 为什么要学习网络爬虫

​ 我们初步认识了网络爬虫,但是为什么要学习网络爬虫呢?只有清晰地知道我们的学习目的,才能够更好地学习这一项知识。在此,总结了4种常见的学习爬虫的原因:

可以实现搜索引擎

​ 我们学会了爬虫编写之后,就可以利用爬虫自动地采集互联网中的信息,采集回来后进行相应的存储或处理,在需要检索某些信息的时候,只需在采集回来的信息中进行检索,即实现了私人的搜索引擎。

大数据时代,可以让我们获取更多的数据源

​ 在进行大数据分析或者进行数据挖掘的时候,需要有数据源进行分析。我们可以从某些提供数据统计的网站获得,也可以从某些文献或内部资料中获得,但是这些获得数据的方式,有时很难满足我们对数据的需求,而手动从互联网中去寻找这些数据,则耗费的精力过大。此时就可以利用爬虫技术,自动地从互联网中获取我们感兴趣的数据内容,并将这些数据内容爬取回来,作为我们的数据源,再进行更深层次的数据分析,并获得更多有价值的信息。

可以更好地进行搜索引擎优化 (SEO)

​ 对于很多SEO从业者来说,为了更好的完成工作,那么就必须要对搜索引擎的工作原理非常清楚,同时也需要掌握搜索引擎爬虫的工作原理。

​ 而学习爬虫,可以更深层次地理解搜索引擎爬虫的工作原理,这样在进行搜索引擎优化时,才能知己知彼,百战不殆。

有利于就业, 爬虫工程师需求量大, 发展空间广

​ 从就业来说,爬虫工程师方向是不错的遥择之一,因为目前爬虫工程师的需求越来越大,而能够胜任这方面岗位的人员较少,所以属于一个比较紧缺的职业方向,并且随着大数据时代和人工智能的来临,爬虫技术的应用将越来越广泛,在未来会拥有很好的发展空间。

2. HttpClient

网络爬虫就是用程序帮助我们访问网络上的资源,我们一直以来都是使用HTTP协议访问互联网的网页,网络爬虫需要编写程序,在这里使用同样的HTTP协议访问网页。

这里我们使用Java 的 HTTP协议客户端HttpClient这个技术,来实现抓取网页数据。

2.1 Get请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package cn.itbuild.crawler.test;

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.util.EntityUtils;

import java.io.IOException;

/**
* @Date 2020/12/21 19:16
* @Version 10.21
* @Author DuanChaojie
*/
public class HttpGetTest {
public static void main(String[] args) {
// 1.创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();

// 2.创建HttpGet对象, 设置url访问地址
HttpGet httpGet = new HttpGet("http://www.itcast.cn");

// 3.使用 HttpClient 发起请求, 获取 response
CloseableHttpResponse response = null;

try {
response = httpClient.execute(httpGet);
// 4.解析响应
if (response.getStatusLine().getStatusCode() == 200){
String content = EntityUtils.toString(response.getEntity(), "utf-8");
System.out.println(content.length());
System.out.println(content);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
// 5.关闭资源
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

2.2 带参数的Get请求

在传智中搜索学习视频,地址为http://yun.itheima.com/search?keys=Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package cn.itbuild.crawler.test;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;


/**
* @Date 2020/12/21 19:16
* @Version 10.21
* @Author DuanChaojie
*/
public class HttpGetParamTest {
public static void main(String[] args) throws Exception {
// 1.创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();

// 设置请求地址是: http://yun.itheima.com/search?keys=Java
// 创建uriBuilder
URIBuilder uriBuilder = new URIBuilder("http://yun.itheima.com/search");
// 多个参数,使用连式编程
uriBuilder.setParameter("keys","Java");

// 2.创建HttpGet对象, 设置url访问地址☆
HttpGet httpGet = new HttpGet(uriBuilder.build());

System.out.println("发送请求的信息:");

// 3.使用 HttpClient 发起请求, 获取 response
CloseableHttpResponse response = httpClient.execute(httpGet);
// 4.解析响应
if (response.getStatusLine().getStatusCode() == 200){
String content = EntityUtils.toString(response.getEntity(), "utf-8");
System.out.println(content.length());
System.out.println(content);
}

}
}

2.3 Post请求

使用POST 请求访问传智官网,请求url地址:http://www.itcast.cn/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package cn.itbuild.crawler.test;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

/**
* @Date 2020/12/21 19:16
* @Version 10.21
* @Author DuanChaojie
*/
public class HttpPostTest {
public static void main(String[] args) {
// 1.创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();

// 2.创建HttpPost对象, 设置url访问地址
HttpPost httpPost = new HttpPost("http://www.itcast.cn");


// 3.使用 HttpClient 发起请求, 获取 response
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpPost);
// 4.解析响应
if (response.getStatusLine().getStatusCode() == 200){
String content = EntityUtils.toString(response.getEntity(), "utf-8");
System.out.println(content.length());
System.out.println(content);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
// 5.关闭资源
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (httpClient != null) {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}

2.4 带参数的Post请求

在传智中搜索学习视频,使用POST请求,url地址为:http://yun.itheima.com/search

url地址没有参数,参数 keys=java放到表单中进行提交。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package cn.itbuild.crawler.test;

import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.util.ArrayList;
import java.util.List;

/**
* @Date 2020/12/21 19:16
* @Version 10.21
* @Author DuanChaojie
*/
public class HttpPostParamTest {
public static void main(String[] args) throws Exception {
// 1.创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();

// 2.创建HttpPost对象, 设置url访问地址
HttpPost httpPost = new HttpPost("http://yun.itheima.com/search");

/** 声明List集合, 封装表单中的参数
* public interface NameValuePair {
* String getName();
*
* String getValue();
* }
*/
List<NameValuePair> params = new ArrayList<NameValuePair>();

// 注意BasicNameValuePair是NameValuePair唯一的实现类
params.add(new BasicNameValuePair("keys","Java"));

// 创建表单的Entity对象, 第一个参数就是封装好的表单数据, 第二个参数就是编码
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params,"utf-8");

// 设置表单的Entity对象到 Post 请求中
httpPost.setEntity(formEntity);

// 3.使用 HttpClient 发起请求, 获取 response
CloseableHttpResponse response = httpClient.execute(httpPost);

// 4.解析响应
if (response.getStatusLine().getStatusCode() == 200){
String content = EntityUtils.toString(response.getEntity(), "utf-8");
System.out.println(content.length());
}
}
}

2.5 连接池

如果每次请求都要创建HttpClient,会有频繁创建和销毁的问题,可以使用连接池来解决这个问题。

测试以下代码,并断点查看每次获取的HttpClient都是不一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package cn.itbuild.crawler.test;

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 java.io.IOException;

/**
* @Date 2020/12/21 20:08
* @Version 10.21
* @Author DuanChaojie
*/
public class HttpClientPoolTest {
public static void main(String[] args) {
// 创建连接池管理器
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
// 设置连接数
cm.setMaxTotal(100);
// 设置每个主机的最大连接数
cm.setDefaultMaxPerRoute(10);

// 使用连接池管理器发起请求
doGet(cm);
doGet(cm);
}

/**
* @param cm
*/
private static void doGet(PoolingHttpClientConnectionManager cm) {
// 不是每次创建新的HttpClient, 而是从连接池中获取 HttpClient 对象
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();

HttpGet httpGet = new HttpGet("http://www.itcast.cn");

CloseableHttpResponse response = null;
try {
// 使用 HttpClient 发起请求, 获取 response
response = httpClient.execute(httpGet);
// 解析响应
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "utf8");
System.out.println(content.length());
}
} catch(IOException e) {
e.printStackTrace();
} finally {
// 关闭 response
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
// 不能关闭 HttpClient, 由连接池管理 HttpClient
// httpClient. close();
}
}
}
}

2.6 请求参数

有时候因为网络,或者目标服务器的原因,请求需要更长的时间才能完成,我们需要自定义相关时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package cn.itbuild.crawler.test;

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.util.EntityUtils;

/**
* @Date 2020/12/21 20:12
* @Version 10.21
* @Author DuanChaojie
*/
public class HttpConfigTest {
public static void main(String[] args) throws Exception{
// 1. 创建HttpClient对象
CloseableHttpClient httpClient = HttpClients.createDefault();

// 2. 创建HttpGet对象, 设置url访问地址
HttpGet httpGet = new HttpGet("http://yun.itheima.com/search?keys=Java");

// 3. 配置请求信息
RequestConfig config = RequestConfig.custom().setConnectTimeout(1000) // 创建连接的最长时间, 单位是毫秒
.setConnectionRequestTimeout(500) // 设置获取连接的最长时间, 单位是毫秒
.setSocketTimeout(10 * 1000) // 设置数据传输的最长时间, 单位是毫秒
.build();

// 4. 给请求设置请求信息
httpGet.setConfig(config);

// 5. 使用 HttpClient 发起请求, 获取 response
CloseableHttpResponse response = httpClient.execute(httpGet);

// 6. 解析响应
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "utf8");
System.out.println(content.length());
}
}
}

3. Jsoup

我们抓取到页面之后,还需要对页面进行解析。可以使用字符串处理工具解析页面,也可以使用正则表达式,但是这些方法都会带来很大的开发成本,所以我们需要使用一款专门解析html页面的技术—Jsoup。

3.1 Jsoup介绍

jsoup是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文木内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

jsoup的主要功能如下:

  1. 从一个URL,文件或字符串中解析HTML;
  2. 使用DOM或CSS选择器来查找、取出数据;
  3. 可操作HTML元素、属性、文本。

添加jsoup相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cn.itbuild</groupId>
<artifactId>itbuild-crawler-first</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--引入jar包-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
<!--Jsoup-->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--操作文件FileUtils-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!--操作字符串StringUtils-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
</project>

3.2 解析Url

虽然使用Jsoup可以替代HttpClient直接发起请求解析数据,但是往往不会这样用,因为实际的开发过程中,需要使用到多线程,连接池,代理等等方式,而 jsoup 对这些的支持并不是很好,所以我们一般把jsoup 仅仅作为 Html解析工具使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package cn.itbuild.test;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.junit.Test;

import java.net.URL;

/**
* @Date 2020/12/21 22:53
* @Version 10.21
* @Author DuanChaojie
*/
public class JsoupTest {
@Test
public void testUrl() throws Exception {
// 1. 解析url地址, 第一个参数是访问的url, 第二个参数时访问时候的超时时间
Document doc = Jsoup.parse(new URL("http://www.itcast.cn"), 1000);

// 2. 使用标签选择器, 获取title标签中的内容
String title = doc.getElementsByTag("title").first().text();

// 3.打印
System.out.println(title);
}
}

将test.html的路径在JsoupTest中先定义好

1
private static final String TESTHTML = "E:\\file\\gitee\\itbuild-crawler-first\\src\\main\\java\\cn\\itbuild\\crawler\\test\\test.html";

test.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>传智教育官网-好口碑IT培训机构,一样的教育,不一样的品质</title>
<style>
.class_a{

}
.class_b{

}
.a_name{

}
</style>
</head>
<body>
<div class="city">
<h3 id="city_bj">北京中心</h3>

<div class="city_in">
<div class="city_con" style="display:none;">
<ul>
<li id="test" class="class_a class_b">
<a href="http://www.itcast.cn" target="_blank" >
<span class="a_name">北京</span>
</a>
</li>
<li>
<a href="http://sh.itcast.cn" target="_blank">
<span class="a_name">上海</span>
</a>
</li>
<li>
<a href="http://gz.itcast.cn" target="_blank">
<span abc="123" class="a_name">广东</span>
</a>
</li>
</ul>
<ul>
<li>天津</li>
</ul>
</div>
</div>
</div>
</body>
</html>

3.3 解析字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void testString() throws Exception {
// 1. 使用工具类读取文件, 获取字符串
String content = FileUtils.readFileToString(new File(TESTHTML), "utf8");

// 2. 解析字符串
Document doc = Jsoup.parse(content);

String title = doc.getElementsByTag("title").first().text();

// 3.打印
System.out.println(title);

}

3.4 解析文件

1
2
3
4
5
6
7
8
9
@Test
public void testFile() throws Exception {
// 1. 解析文件
Document doc = Jsoup.parse(new File(TESTHTML), "utf8");

String title = doc.getElementsByTag("title").first().text();

System.out.println(title);
}

3.5 使用DOM方式遍历文档

元素获取:

  1. 根据id查询元素 getElementByld
  2. 根据标签获取元素getElementsByTag
  3. 根据class获取元素getElementsByClass
  4. 根据属性获取元素getElementsByAttribute
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@Test
public void testDom() throws Exception {
// 解析文件, 获取Document对象
Document doc = Jsoup.parse(new File(TESTHTML), "utf8");

// 1.根据id查询元素getElementById
Element element = doc.getElementById("city_bj");

// 2.根据标签获取元素getElementsByTag
Elements spans = doc.getElementsByTag("span");

// 3.根据class获取元素getElementsByClass
Element clazz = doc.getElementsByClass("class_a class_b").first();

// 4.根据属性获取元素getElementsByAttribute
Element abc = doc.getElementsByAttribute("abc").first();

// 5.根据属性与属性值筛选
Element href = doc.getElementsByAttributeValue("href", "http://sh.itcast.cn").first();

// 打印元素内容
System.out.println("获取到的元素内容是: " + element.text());
for (Element span : spans) {
System.out.println(span.text());
}

System.out.println(clazz.text());
System.out.println("abc.text() = " + abc.text());
System.out.println("href.text() = " + href.text());
}

元素中获取数据:

  1. 从元素中获取id
  2. 从元素中获取className
  3. 从元素中获取属性的值 attr
  4. 从元素中获取所有属性attributes
  5. 从元紊中获取文本内容 text
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Test
public void testDate() throws IOException {
// 1.解析文件获取Document
Document doc = Jsoup.parse(new File(TESTHTML), "utf8");

// 2.根据id获取元素
Element element = doc.getElementById("test");

String str = "";

//元素中获取数据:
// 1. 从元素中获取id
str = element.id();
// 2. 从元素中获取className
str = element.className();
Set<String> sets = element.classNames();
for (String set : sets) {
System.out.println("set = " + set);
}

// 3. 从元素中获取属性的值 attr
str = element.attr("id");
str = element.attr("class");

// 4. 从元素中获取所有属性attributes
Attributes attributes = element.attributes();
System.out.println("attributes = " + attributes.toString());

// 5. 从元紊中获取文本内容 text
str = element.text();

// 打印获取到的内容
System.out.println("获取到的数据:" + str);
}

3.6 Selector选择器概述

tagname:通过标签查找元素,比如: span

#id:通过ID查找元素,比如:#city_bj
.class:通过 class名称查找元素,比如:.class_a

[attribute]:利用属性查找元素,比如:[abc]

[attr=value]:利用属性值来查找元素,比如:[class=s_name]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void testSelector() throws Exception{
// 解析html文件,获取Document对象
Document doc = Jsoup.parse(new File(TESTHTML), "utf8");


Elements spans = doc.select("span");
for (Element span : spans) {
System.out.println(span.text());
}

Element element = doc.select("#city_bj").first();

element = doc.select(".class_a").first();

element = doc.select("[abc]").first();

element = doc.select("[class=a_name]").first();

System.out.println("获取到的结果为:" + element.text());
}

3.7 Selector选择器组合使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Test
public void testSelector2() throws Exception {
// 解析html文件, 获取Document对象
Document doc = Jsoup.parse(new File(TESTHTML), "utf8");

//el#id: 元素+ID,比如: h3#city_bj
//Element element = doc.select("h3#city_bj").first();

//el.class: 元素+class,比如: li.class_a
//Element element = doc.select("li.class_a").first();

//el[attr]: 元素+属性名,比如: span[abc]
//Element element = doc.select("span[abc]").first();

//任意组合: 比如:span[abc].s_name
Element element = doc.select("span[abc].a_name").first();

// 后代选择器
//Elements elements = doc.select(".city_con li");

// 父子选择器
//Elements elements = doc.select(".city_con > ul > li");

//parent > *: 查找某个父元素下所有直接子元素
Elements elements = doc.select(".city_con > ul > *");

// 打印
System.out.println("获取到的内容是: " + element.text());

for (Element ele : elements) {
System.out.println("遍历的结果: " + ele.text());
}
}