Java网络爬虫学习


Java网络爬虫学习

原创 已于 2025-08-07 15:33:05 修改 · 粉丝可见 · 122 阅读 · 0 · 0 GEO检测 · 编辑
文章链接:https://blog.csdn.net/hacker_51/article/details/142664968

Java是一种广泛使用的编程语言,尤其在企业级应用和大型系统中应用广泛。
Java在处理大规模数据和并发性能方面表现出色,这对于需要高性能网络爬虫的情况可能更有优势。

一、准备环境

引入pom坐标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
</dependency>


<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>

</dependencies>
1
在resources文件资源创建log4j.properties
1
2
3
4
5
6
7
8
# log4j.properties
log4j.rootLogger=DEBUG, stdout

log4j.logger.org.mybatis.example.BlogMapper=TRACE

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

测试发送

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
package com.angindem.test;

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;

import java.io.IOException;

public class CrawlerFirst {
public static void main(String[] args) throws IOException, ParseException {
// 1、打开浏览器
CloseableHttpClient httpClient = HttpClients.createDefault();


// 2、输入网址,发起get请求创建 HttpGet 对象
HttpGet httpGet = new HttpGet("https://www.baidu.com/");


// 3、按回车,发起请求, 获取响应
CloseableHttpResponse response = httpClient.execute(httpGet);


// 4、解析响应,获取数据
// 判断状态码是否是 200
if(response.getCode() == 200){

// 获取响应实体
HttpEntity httpEntity = response.getEntity();

// 利用client5 提供的 实体类工具 解析响应转为 String
String content = EntityUtils.toString(httpEntity, "UTF-8");

System.out.println(content);
}else{
System.out.println("500");
}

response.close();
httpClient.close();
}
}

运行代码

获取到了ok状态,发送并获取数据成功。

二、初识Java网络爬虫

1、Get请求带参数

通过 new  URIBuilder 构造出 URI 对象,通过对象的setParam方法加入对应参数

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
package com.angindem.test;

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.net.URIBuilder;

import java.io.IOException;
import java.net.URISyntaxException;

public class HttpGetParamsTest {
public static void main(String[] args) throws IOException, ParseException, URISyntaxException {

CloseableHttpClient httpClient = HttpClients.createDefault();

// 设置请求地址是:http://yun.itheima.com/search?key=java
// 创建 URIBuilder
URIBuilder uriBuilder = new URIBuilder("http://yun.itheima.com/search");

// 设置参数
uriBuilder.setParameter("key", "java");

HttpGet httpGet = new HttpGet(uriBuilder.build());

// 发起请求的信息
// System.out.println(httpGet);

CloseableHttpResponse response = httpClient.execute(httpGet);

int code = response.getCode();

// System.out.println("code = " + code);

if(code == 200){
System.out.println(code);
String content = EntityUtils.toString(response.getEntity(),"UTF-8");
System.out.println(content.length());
}else System.out.println(500);

response.close();
httpClient.close();
}
}

2、无参Post 请求

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
package com.angindem.test;

import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;

import java.io.IOException;

public class HttpPostTest {
public static void main(String[] args) throws IOException, ParseException {

CloseableHttpClient httpClient = HttpClients.createDefault();

HttpPost httpPost = new HttpPost("http://www.itcast.cn");


CloseableHttpResponse response = httpClient.execute(httpPost);

int code = response.getCode();

System.out.println("code = " + code);

if (code == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content.length());
} else System.out.println(500);

response.close();
httpClient.close();
}
}

3、带参数Post请求

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
package com.angindem.test;

import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

public class HttpPostParamsTest {
public static void main(String[] args) throws IOException, ParseException {

CloseableHttpClient httpClient = HttpClients.createDefault();

HttpPost httpPost = new HttpPost("http://yun.itheima.com/search");

// 声明 List 集合,封装表单中的参数
List<NameValuePair> params = new ArrayList<>();

// 设置请求地址是:http://yun.itheima.com/search?key=java
params.add(new BasicNameValuePair("key","java"));

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

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

CloseableHttpResponse response = httpClient.execute(httpPost);

int code = response.getCode();

System.out.println("code = " + code);

if (code == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content.length());
} else System.out.println(500);

response.close();
httpClient.close();
}
}

4、配置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
package com.angindem.test;

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;

import java.io.IOException;

public class HttpClientPoolTest {

public static void main(String[] args) {
// 1、创建连接池管理器
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

// 设置最大连接数
cm.setMaxTotal(100);

// 设置每个主机的最大连接数
cm.setDefaultMaxPerRoute(10);

try {

doGet(cm);

doGet(cm);

} catch (IOException e) {
throw new RuntimeException(e);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}

private static void doGet(PoolingHttpClientConnectionManager cm) throws IOException, ParseException {

CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();

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

CloseableHttpResponse response = httpClient.execute(httpGet);

String content = EntityUtils.toString(response.getEntity(), "UTF-8");

System.out.println(content.length());
// 响应需要自己关闭
response.close();

// 注意这里不能关闭 httpClient(客户端) ,又连接池自动管理的
// httpClient.close();
}
}

三、了解Java网路爬虫

jsoup 是一款Java 的HTML解析器,可直接解析某个 URL地址、HTML 文本内容。

它提供了一套非常省力的 API,可通过DOM,CSS 以及类似于jQuery 的操作方法来取出和操作数据。
jsoup的主要功能如下:
1、从一个URL,文件或字符串中解析 HTML;
2、使用DOM或CSS选择器来查找、取出数据;
3、可操作 HTML元素、属性、文本;

1、Jsoup工具

引入Jsoup的 pom坐标

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.15.3</version>
</dependency>

引入Junit 的 pom 坐标

1
2
3
4
5
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

引入 commons-io 的 pom 坐标  用一些io工具类,比如 fileUtils

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>

引入 commons-lang3 的 pom 坐标  用一些String工具类,比如 StringUtils

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>

测试Jsoup类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package jsoup;

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

import java.io.IOException;
import java.net.URL;

public class JsoupTest {

@Test
public void testUrl() throws IOException {

// 解析 url 地址, 第一个参数是访问的url,第二个参数是访问时候的超时时间
Document doc = Jsoup.parse(new URL("http://www.itcast.cn"), 1000);

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

System.out.println(title);
}
}

PS:

虽然使用Jsoup可以替代Httpclient 直接发起请求解析数据,

但是往往不会这样用,因为实际的开发过程中,需要使用到多线程,连接池,代理等等方式,

而 jsoup 对这些的支持并不是很好,所以我们一般把jsoup 仅仅作为 Html解析工具使用。

2、解析字符串

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
<htmL>

<head>
<title>AngindemTestHtml</title>
</head>

<body>
<div class="city">
<h3 id="city_bj">北京中心</h3>
<fb:img src="/2018czgw/images/slogan.jpg" class="slogan" />
<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="s_name">北京</span></a>
</li>
<li>
<a href="http://sh.itcast.cn" target=" blank"><span class="s_name">上海</span></a>

</li>
<li>
<a href="http://gz.itcast.cn" target=" blank"><span abc="123" class="s_name">广州</span></a>
</li>
<ul>
<li>天津</li>
</ul>
</ul>
</div>
</div>
</body>

</html>
</div>

通过Jsoup解析web结构字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
    @Test
public void testString() throws IOException {
// 使用工具类读取文件,获取字符串
String content = FileUtils.readFileToString(new File("D:\\Java_workSpace\\StudyWebSpider\\src\\main\\resources\\test.html"), "UTF-8");

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


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

System.out.println(title);
}

3、解析文件

通过Jsoup解析web文件

1
2
3
4
5
6
7
8
9
    @Test
public void testFile() throws IOException {
// 解析文件
Document doc = Jsoup.parse(new File("D:\\Java_workSpace\\StudyWebSpider\\src\\main\\resources\\test.html"), "UTF-8");

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

System.out.println(title);
}

4、使用Dom方式获取元素数据

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
65
66
67
68
69
70
71
72
73
74
75
76
package jsoup;

import org.apache.commons.io.FileUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.net.URL;

public class JsoupTest {

@Test
public void testUrl() throws IOException {

// 解析 url 地址, 第一个参数是访问的url,第二个参数是访问时候的超时时间
Document doc = Jsoup.parse(new URL("http://www.itcast.cn"), 1000);

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

System.out.println(title);
}

@Test
public void testString() throws IOException {
// 使用工具类读取文件,获取字符串
String content = FileUtils.readFileToString(new File("D:\\Java_workSpace\\StudyWebSpider\\src\\main\\resources\\test.html"), "UTF-8");

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


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

System.out.println(title);
}

@Test
public void testFile() throws IOException {
// 解析文件
Document doc = Jsoup.parse(new File("D:\\Java_workSpace\\StudyWebSpider\\src\\main\\resources\\test.html"), "UTF-8");

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

System.out.println(title);
}

@Test
public void testDom() throws IOException {
// 解析文件
Document doc = Jsoup.parse(new File("D:\\Java_workSpace\\StudyWebSpider\\src\\main\\resources\\test.html"), "UTF-8");

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

// 2、根据标签获取元素 getElementsByTag
// Element element = doc.getElementsByTag("span").get(1);

// 3、根据class获取元素 getElementsByClass
// Element element = doc.getElementsByClass("class_a class_b").get(0);
// Element element = doc.getElementsByClass("class_a").get(0);
// Element element = doc.getElementsByClass("class_b").get(0);

// 4、根据属性获取元素 getElementsByAttribute
// Element element = doc.getElementsByAttribute("abc").get(0);
Element element = doc.getElementsByAttributeValue("href","http://sh.itcast.cn").get(0);

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

}
}

5、使用 attributes 属性 方式获取元素数据

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 testData() throws IOException {
//解析文件,获取Document
Document doc = Jsoup.parse(new File("D:\\Java_workSpace\\StudyWebSpider\\src\\main\\resources\\test.html"), "UTF-8");

Element element = doc.getElementById("test");

String result = "";

// 元素中获取数据
// 1、从元素中获取id
// result = element.id();

// 2、从元素中获取className
// result = element.className();

// Set<String> classSet = element.classNames();
// classSet.forEach(className-> System.out.println("classNames have :" + className));

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

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

// 5、从元素中获取文本内容text
result = element.text();
System.out.println("获取到的数据是:" + result);
}

6、使用Select选择器方式获取元素数据

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
@Test
public void testSelector() throws IOException {
// 解析html文件,获取document数据
Document doc = Jsoup.parse(new File("D:\\Java_workSpace\\StudyWebSpider\\src\\main\\resources\\test.html"), "UTF-8");

// tagname:通过标签查找元素,比如:span
// Elements elements = doc.select("span");
// elements.forEach(element -> System.out.println(element.text()));

// #id:通过ID查找元素,比如:#city_bj
// Element element = doc.select("#city_bj").first();
// System.out.println(element.text());

// .class:通过class名称查找元素,比如:.class
// Elements elements = doc.select(".class_a");
// elements.forEach(element -> System.out.println(element.text()));

// [attribute]:利用属性查找元素,比如:[abc]
// Elements elements = doc.select("[abc]");
// elements.forEach(element -> System.out.println(element.text()));

// [attr=value]:利用属性值来查找元素,比如:[class=s_name]
Elements elements = doc.select("[class=s_name]");
elements.forEach(element -> System.out.println(element.text()));
}

7、使用 Select 任意组合方式获取元素数据

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 IOException {
// 解析html文件,获取document数据
Document doc = Jsoup.parse(new File("D:\\Java_workSpace\\StudyWebSpider\\src\\main\\resources\\test.html"), "UTF-8");

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

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

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

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

// ancestor child :查找某个元素下子元素,比如 :.city_con li 查找"city_con"下的所有li
// Elements elements = doc.select(".city_con li");
// elements.forEach(element1 -> System.out.println(element1.text()));

// parent > child :查找某个父元素下的直接子元素,比如 :
// .city_con >ul >li 查找city_con第一级(直接子元素)的ul,再找所有ul下的第一级li
// Elements elements = doc.select(".city_con > li");
// Elements elements = doc.select(".city_con > ul > li");
// elements.forEach(element1 -> System.out.println(element1.text()));

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

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

觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭

微信二维码

wechat pay

支付宝二维码

ali pay

Java网络爬虫学习
http://blog.angindem.cn/2025/08/07/Angindem-CSDN博客/162_162/
作者
Angindem
发布于
2025年8月7日
许可协议