2025最新Java爬虫教程:如何高效抓取网页数据?(含完整实例)

一、Java爬虫抓取网页数据的背景与价值

2025最新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")); 

2025最新Java爬虫教程:如何高效抓取网页数据

        // 写入表头 

        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);  

2025最新Java爬虫教程:如何高效抓取网页数据

                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爬虫的完整实现,希望能帮助你快速入门。

在实际开发中,需要根据目标网站的结构调整解析方式(例如处理动态内容、应对反爬),同时注意合规性。如果想深入学习,可以尝试爬取更复杂的网站(如电商平台的商品数据、社交媒体的用户评论),提升自己的爬虫技能。

提示:本文代码仅用于学习交流,请勿用于商业用途或恶意爬取。


《2025最新Java爬虫教程:如何高效抓取网页数据》.doc
将本文下载保存,方便收藏和打印
下载文档