2025最新Java爬虫教程:如何高效抓取网页数据?(含完整实例)
一、Java爬虫抓取网页数据的背景与价值
在大数据时代,网页数据是企业决策、产品优化、学术研究的重要数据源(例如电商平台的商品价格、社交媒体的用户评论、行业网站的资讯信息)。手动复制粘贴数据效率极低,而Java爬虫作为一种自动化数据获取工具,能快速、批量地从网页中提取结构化数据,解决了“数据获取难”的痛点。
Java之所以成为爬虫开发的热门选择,主要得益于其跨平台性(支持Windows、Linux、Mac)、稳定性(Java虚拟机的内存管理和异常处理机制)以及丰富的生态库(如Jsoup解析HTML、HttpClient发送HTTP请求、MyBatis存储数据)。这些优势让Java爬虫能应对复杂的网页结构和高并发的爬取需求。
二、Java爬虫开发前的准备工作
在开始写爬虫之前,需要完成以下环境搭建和依赖引入:
1. 环境搭建
JDK安装:推荐使用JDK 17及以上版本(下载地址:Oracle JDK ),安装后配置JAVA_HOME环境变量。
IDE选择:推荐使用IntelliJ IDEA(社区版免费,下载地址:JetBrains IDEA ),支持代码自动补全、调试等功能。
2. 依赖库引入
通过Maven或Gradle引入以下核心依赖(以Maven为例):
依赖库 作用 Maven依赖代码
Jsoup 解析HTML文档,提取数据 <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.17.2</version></dependency>
Apache HttpClient 发送HTTP请求,获取网页内容 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.14</version></dependency>
OpenCSV 存储数据到CSV文件 <dependency><groupId>com.opencsv</groupId><artifactId>opencsv</artifactId><version>5.7.1</version></dependency>
三、Java爬虫抓取网页数据的核心流程
Java爬虫的工作流程可分为发送HTTP请求→解析网页内容→存储数据三大步骤,以下是具体实现:
1. 发送HTTP请求,获取网页内容
要抓取网页数据,首先需要向目标URL发送HTTP请求(通常是GET请求),获取网页的HTML源代码。这里以Apache HttpClient为例,模拟浏览器发送请求:
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;
public class HttpDemo {
public static void main(String[] args) throws Exception {
// 创建HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault;
// 目标URL(豆瓣电影Top250)
String url = "https://movie.douban.com/top250";
// 创建GET请求
HttpGet httpGet = new HttpGet(url);
// 设置请求头(模拟浏览器,避免被反爬)
httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36");
// 发送请求并获取响应
CloseableHttpResponse response = httpClient.execute(httpGet);
// 判断响应状态(200表示成功)
if (response.getStatusLine.getStatusCode == 200) {
// 提取网页HTML内容
String html = EntityUtils.toString(response.getEntity, "UTF-8");
System.out.println(" 网页内容获取成功:" + html.substring(0, 100)); // 打印前100字符
}
// 关闭资源
response.close;
httpClient.close;
}
}
注意:设置User-Agent是反爬的基础,它告诉服务器“我是浏览器,不是爬虫”,避免被直接拦截。
2. 解析网页内容,提取目标数据
获取HTML后,需要从混乱的标签中提取结构化数据(例如电影名称、评分、链接)。这里使用Jsoup(Java的HTML解析库),通过CSS选择器定位元素:
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class JsoupDemo {
public static void main(String[] args) throws Exception {
// 假设已获取豆瓣Top250的HTML内容(html变量)
String html = "..."; // 省略,可从上面的HttpDemo中获取
// 解析HTML为Document对象
Document doc = Jsoup.parse(html);
// 使用CSS选择器定位电影条目(class="item")
Elements movieItems = doc.select(".item");
// 遍历每个电影条目,提取数据
for (Element item : movieItems) {
// 电影名称(class="title"的第一个元素)
String title = item.select(".title").first.text;
// 电影评分(class="rating_num")
String rating = item.select(".rating_num").text;
// 评价人数(class="star"下的最后一个span)
String votes = item.select(".star span:last-child").text;
// 电影链接(a标签的href属性)
String link = item.select(".hd a").attr("href");
// 打印结果
System.out.printf(" 电影名称:%s,评分:%s,评价人数:%s,链接:%s%n", title, rating, votes, link);
}
}
}
说明:Jsoup的select方法支持CSS选择器(如.class、#id、element),能快速定位目标元素。例如.item表示所有class为item的元素,.title表示class为title的元素。
3. 存储数据(CSV/数据库)
提取数据后,需要将其存储到文件或数据库中,方便后续分析。以下是两种常见的存储方式:
(1)存储到CSV文件(OpenCSV)
CSV是一种通用的文本文件格式,适合存储结构化数据:
import com.opencsv.CSVWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
public class CsvStorageDemo {
public static void main(String[] args) throws Exception {
// 假设已提取电影数据(movieList)
List<Movie> movieList = new ArrayList<>;
movieList.add(new Movie("肖申克的救赎", "9.7", "260万", "https://movie.douban.com/subject/1292052/"));
movieList.add(new Movie("霸王别姬", "9.6", "200万", "https://movie.douban.com/subject/1291546/"));
// 创建CSVWriter对象(指定文件路径)
CSVWriter writer = new CSVWriter(new FileWriter("douban_top250.csv"));
// 写入表头
writer.writeNext(new String[]{"电影名称", "评分", "评价人数", "链接"});
// 写入数据
for (Movie movie : movieList) {
writer.writeNext(new String[]{movie.getTitle, movie.getRating, movie.getVotes, movie.getLink});
}
// 关闭资源
writer.close;
System.out.println(" 数据已存储到douban_top250.csv");
}
// 电影实体类
static class Movie {
private String title;
private String rating;
private String votes;
private String link;
// 构造方法、getter/setter省略
}
}
(2)存储到数据库(MyBatis-Plus)
如果需要长期存储或复杂查询,可以将数据存储到MySQL等关系型数据库。使用MyBatis-Plus(简化MyBatis开发的框架):
步骤1:定义Movie实体类(映射到数据库表)。
步骤2:创建Mapper接口(继承BaseMapper)。
步骤3:使用IService的saveBatch方法批量存储数据。
示例代码(省略配置文件):
// Movie实体类
@TableName("movie")
public class Movie {
@TableId(type = IdType.AUTO)
private Long id;
private String title;
private String rating;
private String votes;
private String link;
// getter/setter省略
}
// Mapper接口
public interface MovieMapper extends BaseMapper<Movie> {
}
// 服务类
@Service
public class MovieService extends ServiceImpl<MovieMapper, Movie> {
// 批量存储数据
public void saveMovies(List<Movie> movieList) {
this.saveBatch(movieList);
}
}
四、实战案例:抓取豆瓣电影Top250完整数据
以下是一个完整的Java爬虫实例,实现从豆瓣电影Top250抓取数据并存储到CSV文件:
1. 需求分析
目标:获取豆瓣电影Top250的电影名称、评分、评价人数、导演、演员、电影链接。
2. 实现步骤
(1)发送HTTP请求:使用HttpClient获取豆瓣Top250的HTML内容(注意分页,每页25条,共10页)。
(2)解析HTML:使用Jsoup提取每个电影条目的目标数据。
(3)存储数据:使用OpenCSV将数据写入CSV文件。
3. 完整代码
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 org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import com.opencsv.CSVWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
public class DoubanSpider {
// 豆瓣Top250首页URL(分页参数:start=0表示第一页,start=25表示第二页,依此类推)
private static final String BASE_URL = "https://movie.douban.com/top250?start=";
// User-Agent(模拟Chrome浏览器)
private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36";
public static void main(String[] args) throws Exception {
// 创建HttpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault;
// 存储所有电影数据的列表
List<Movie> movieList = new ArrayList<>;
// 遍历10页(每页25条,共250条)
for (int i = 0; i < 10; i++) {
int start = i * 25;
String url = BASE_URL + start;
System.out.println(" 正在抓取第" + (i+1) + "页:" + url);
// 发送HTTP请求
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("User-Agent", USER_AGENT);
CloseableHttpResponse response = httpClient.execute(httpGet);
// 解析HTML
if (response.getStatusLine.getStatusCode == 200) {
String html = EntityUtils.toString(response.getEntity, "UTF-8");
Document doc = Jsoup.parse(html);
Elements movieItems = doc.select(".item");
// 提取每个电影的数据
for (Element item : movieItems) {
String title = item.select(".title").first.text; // 电影名称
String rating = item.select(".rating_num").text; // 评分
String votes = item.select(".star span:last-child").text; // 评价人数
String directorActor = item.select(".bd p:first-child").text; // 导演和演员(格式:导演: 张艺谋 演员: 周润发 巩俐)
String link = item.select(".hd a").attr("href"); // 电影链接
// 分割导演和演员(可选,根据需求处理)
String[] daArray = directorActor.split(" / ");
String director = daArray.replace("导演: ", ""); // 导演
String actors = daArray.length > 1 ? daArray.replace("演员: ", "") : ""; // 演员
// 添加到电影列表
movieList.add(new Movie(title, rating, votes, director, actors, link));
}
}
// 关闭响应
response.close;
// 间隔1秒(避免频繁请求被反爬)
Thread.sleep(1000);
}
// 关闭HttpClient
httpClient.close;
// 存储数据到CSV文件
saveToCsv(movieList, "douban_top250_full.csv");
System.out.println(" 抓取完成,共获取" + movieList.size + "条数据!");
}
/**
* 将电影数据存储到CSV文件
* @param movieList 电影列表
* @param filePath 文件路径
*/
private static void saveToCsv(List<Movie> movieList, String filePath) throws Exception {
CSVWriter writer = new CSVWriter(new FileWriter(filePath));
// 写入表头
writer.writeNext(new String[]{"电影名称", "评分", "评价人数", "导演", "演员", "电影链接"});
// 写入数据
for (Movie movie : movieList) {
writer.writeNext(new String[]{
movie.getTitle,
movie.getRating,
movie.getVotes,
movie.getDirector,
movie.getActors,
movie.getLink
});
}
// 关闭资源
writer.close;
}
/**
* 电影实体类
*/
static class Movie {
private String title; // 电影名称
private String rating; // 评分
private String votes; // 评价人数
private String director; // 导演
private String actors; // 演员
private String link; // 电影链接
// 构造方法
public Movie(String title, String rating, String votes, String director, String actors, String link) {
this.title = title;
this.rating = rating;
this.votes = votes;
this.director = director;
this.actors = actors;
this.link = link;
}
// getter/setter省略
}
}
4. 运行结果
运行代码后,会生成douban_top250_full.csv 文件,内容如下(部分示例):
电影名称 评分 评价人数 导演 演员 电影链接
肖申克的救赎 9.7 260万 弗兰克·德拉邦特 蒂姆·罗宾斯 摩根·弗里曼 https://movie.douban.com/subject/1292052/
霸王别姬 9.6 200万 陈凯歌 张国荣 张丰毅 巩俐 https://movie.douban.com/subject/1291546/
阿甘正传 9.5 180万 罗伯特·泽米吉斯 汤姆·汉克斯 罗宾·怀特 https://movie.douban.com/subject/1292720/
五、Java爬虫的注意事项与反爬技巧
遵守robots协议:查看目标网站的robots.txt 文件(例如https://movie.douban.com/robots.txt ),避免抓取禁止的路径(如/login、/register)。
模拟浏览器行为:除了设置User-Agent,还可以设置Referer(来源页面)、Cookie(保持登录状态),让请求更接近真实用户。
控制爬取频率:不要频繁发送请求(例如每秒超过10次),可通过Thread.sleep 设置间隔(1-3秒/次),避免给服务器造成压力。
处理动态内容:如果网页使用JavaScript动态加载数据(例如滚动加载、点击加载更多),需要使用Selenium或Puppeteer模拟浏览器渲染(搜索结果11 提到)。
避免IP封禁:如果需要大量爬取,可以使用代理IP(如阿布云、芝麻代理),轮换IP地址。
合规性:不要抓取** copyrighted 内容**(如电影、音乐)、个人隐私数据(如用户身份证号、手机号),遵守《中华人民共和国网络安全法》。
六、总结
Java爬虫是获取网页数据的高效工具,通过发送HTTP请求→解析HTML→存储数据的流程,能快速提取结构化数据。本文通过豆瓣电影Top250的实战案例,展示了Java爬虫的完整实现,希望能帮助你快速入门。
在实际开发中,需要根据目标网站的结构调整解析方式(例如处理动态内容、应对反爬),同时注意合规性。如果想深入学习,可以尝试爬取更复杂的网站(如电商平台的商品数据、社交媒体的用户评论),提升自己的爬虫技能。
提示:本文代码仅用于学习交流,请勿用于商业用途或恶意爬取。