# 豆瓣电影Top250数据爬取与可视化分析实验报告
## 一、实验名称
豆瓣电影Top250数据爬取、分析及可视化实现
## 二、实验目的
1. 掌握基于Jsoup的Java网络爬虫开发方法,实现静态网页的目标数据提取与清洗;
2. 熟练运用Java Stream API进行数据的统计与分析,实现数据的多维度挖掘;
3. 学会使用OpenCSV实现结构化数据的CSV文件导出,完成数据的持久化存储;
4. 掌握XChart可视化工具的使用,实现柱状图、折线图、饼图的绘制与图片保存;
5. 理解面向对象思想在项目中的应用,完成实体类、工具类的分层设计与开发。
## 三、实验环境
1. **开发语言**:Java 22.0.1
2. **开发工具**:IntelliJ IDEA(或Eclipse)
3. **核心依赖**:
- Jsoup 1.17.2:网页解析与数据爬取
- OpenCSV 5.8:CSV文件导出
- XChart 3.8.7:数据可视化图表绘制
4. **运行系统**:Windows 10/11(兼容Linux/Mac OS)
5. **目标爬取网站**:豆瓣电影Top250([https://movie.douban.com/top250](https://movie.douban.com/top250))
## 四、实验原理
1. **网络爬虫原理**:通过Jsoup模拟浏览器发送HTTP请求,获取豆瓣电影Top250网页的HTML文档,利用CSS选择器定位目标标签,提取电影名称、导演、上映年份、评分、评价人数等原始数据,再通过正则表达式、字符串切割等方式完成数据清洗,得到结构化数据。
2. **数据处理原理**:基于Java Stream API对爬取的结构化数据进行流式操作,实现数据的过滤、排序、分组、统计,完成评分Top10、年份电影数量、评分分布等多维度分析。
3. **数据持久化原理**:通过OpenCSV将结构化的电影数据按指定字段格式写入CSV文件,实现数据的本地持久化,支持Excel/WPS等工具直接打开查看。
4. **数据可视化原理**:利用XChart工具将分析后的统计数据映射为柱状图、折线图、饼图,通过设置图表样式、坐标轴、标题等属性,将抽象数据转化为直观的图形,并保存为PNG图片格式。
## 五、实验内容与步骤
### (一)项目结构设计
采用面向对象分层设计思想,将项目分为**实体类、爬虫工具类、数据分析类、CSV导出类、可视化图表类、主程序类**,各模块职责单一,降低耦合度,项目最终结构如下:
```Plain Text
com.example.crawl/
├── Movie.java // 电影实体类,封装数据属性
├── DoubanCrawler.java // 爬虫工具类,实现数据爬取与清洗
├── DataAnalyzer.java // 数据分析类,实现数据统计分析
├── CsvExporter.java // CSV导出类,实现数据持久化
├── ChartGenerator.java // 可视化类,实现图表绘制与保存
└── Main.java // 主程序类,统一调用各模块功能
```
### (二)核心依赖配置
通过Maven管理项目依赖,在`pom.xml`中配置Jsoup、OpenCSV、XChart的依赖坐标,实现第三方库的自动导入,核心配置代码如下:
```XML
org.jsoup
jsoup
1.17.2
com.opencsv
opencsv
5.8
org.knowm.xchart
xchart
3.8.7
```
### (三)模块开发实现
#### 1. 电影实体类(Movie.java)
定义与电影数据对应的属性:电影名称、导演、上映年份、评分、评价人数,提供无参/全参构造方法、Getters/Setters方法及toString()方法,实现数据的封装与访问。
#### 2. 爬虫工具类(DoubanCrawler.java)
1. 定义豆瓣电影Top250基础请求URL,通过循环实现10页数据的分页爬取(每页25条,共250条);
2. 设置请求头`User-Agent`模拟浏览器,添加随机延时`Thread.sleep()`实现文明爬虫,避免请求过快被封;
3. 利用Jsoup CSS选择器定位目标标签,提取原始数据,解决豆瓣页面结构导致的元素定位问题;
4. 通过正则表达式提取上映年份、评价人数,通过字符串切割清洗导演信息,处理空指针异常,保证数据提取的稳定性;
5. 最终返回封装好的`List`结构化数据列表。
#### 3. 数据分析类(DataAnalyzer.java)
基于Java Stream API实现三大核心分析功能:
1. 数据总览:统计电影总数、计算平均评分;
2. 评分Top10:按评分降序排序,获取评分最高的10部电影;
3. 年份分布:按上映年份分组,统计各年份的电影产出数量,并按年份升序输出。
#### 4. CSV导出类(CsvExporter.java)
1. 定义CSV文件导出路径与表头(电影名称、导演、上映年份、豆瓣评分、评价人数);
2. 遍历`List`数据,将每部电影的属性按表头顺序写入CSV文件;
3. 实现CSV特殊字符转义处理,避免逗号、引号导致的文件格式错乱;
4. 完成数据的本地持久化,支持Excel/WPS直接打开。
#### 5. 可视化图表类(ChartGenerator.java)
基于XChart实现三种常用图表的绘制,解决XChart折线图X轴数据类型限制、中文显示等问题:
1. 年份电影数量柱状图:筛选1980年后的数据,取前15个年份,展示各年份电影产出数量;
2. 历年平均评分折线图:按年份分组计算平均评分,以数字类型为X轴,展示评分趋势变化;
3. 评分分布饼图:将电影按9.5分及以上、9.0-9.5分、9.0分以下分组,展示各评分段的电影占比。
所有图表均设置合理的宽高、标题、坐标轴标签,保存为PNG格式至项目根目录。
#### 6. 主程序类(Main.java)
作为项目入口,按**爬取→测试→分析→导出→可视化**的流程统一调用各模块方法,实现整个实验的自动化执行,核心执行逻辑如下:
1. 调用爬虫类爬取250部电影数据;
2. 打印第一部电影的评价人数,验证爬取结果有效性;
3. 调用分析类完成数据多维度统计并控制台输出;
4. 调用CSV导出类将数据保存为本地文件;
5. 调用可视化类绘制并保存柱状图、折线图、饼图。
### (四)项目运行与调试
1. 解决爬取阶段**评价人数提取失败**问题:因豆瓣页面结构,放弃固定索引定位,改为抓取电影卡片全部文字并通过正则强匹配`XXX人评价`,确保评价人数精准提取;
2. 解决CSV导出**字段顺序错乱**问题:修正字段写入顺序,保证与表头完全对应,解决评价人数字段显示为0的视觉问题;
3. 解决可视化阶段**Java版本兼容**问题:移除`var`关键字,改为显式类型声明,兼容Java 8及以上版本;
4. 解决折线图**数据类型报错**问题:将X轴字符串类型改为数字类型(Integer),符合XChart折线图数据类型要求,解决`Series data must be either Number or Date type`异常。
## 六、实验结果与分析
### (一)数据爬取结果
成功爬取豆瓣电影Top250全部250部电影的结构化数据,包括电影名称、导演、上映年份、豆瓣评分、评价人数,无数据缺失、无空指针异常,爬取结果验证有效(如《肖申克的救赎》评价人数3037887、评分9.7,《霸王别姬》评价人数2245306、评分9.6)。
### (二)数据统计分析结果
1. **数据总览**:共获取250部电影,平均评分为8.95分,整体评分水平较高,体现豆瓣Top250电影的优质性;
2. **评分Top10**:评分最高的电影为《肖申克的救赎》(9.7分),其次为《霸王别姬》《控方证人》(均9.6分),9.5分及以上电影共9部,均为经典高分作品;
3. **年份分布**:1994年、2004年、2010年为产出高峰,分别有12部、13部、14部电影上榜;1980年后电影占比超90%,反映经典电影的时间分布特征。
### (三)数据持久化结果
成功导出`douban_top250.csv`文件,文件包含250条数据记录,5个核心字段,字段顺序正确、格式规范,可通过Excel/WPS直接打开查看、编辑,实现了数据的本地持久化存储。
### (四)数据可视化结果
成功生成3张可视化图表并保存为PNG图片,图表样式规范、数据直观:
1. **年份电影数量柱状图**:清晰展示1980年后各年份的电影产出数量,可直观看到2004年、2010年等高峰年份;
2. **历年平均评分折线图**:展示各年份豆瓣Top250电影的平均评分趋势,整体评分保持在8.8-9.2分之间,波动较小,说明经典电影的评分稳定性;
3. **评分分布饼图**:9.0-9.5分电影占比最高(约70%),9.5分及以上电影占比约3.6%,9.0分以下电影占比约26.4%,体现豆瓣Top250的评分门槛较高。
## 七、实验问题与解决方法
本次实验过程中遇到多个技术问题,通过分析问题根源、调试代码实现了全部解决,具体问题与解决方法如下表所示:
|序号|问题描述|问题根源|解决方法|
|---|---|---|---|
|1|爬取评价人数时出现空指针异常|豆瓣页面结构导致固定索引定位元素失败|放弃固定索引,抓取电影卡片全部文字,通过正则表达式强匹配`XXX人评价`提取人数|
|2|CSV文件中评价人数全显示为0|CSV导出时字段顺序与表头不一致,赋值错误|修正字段写入顺序,保证与表头一一对应,添加字段赋值校验|
|3|可视化代码编译报错,提示无法解析`var`|部分开发环境对Java高版本语法支持不佳|移除`var`关键字,改为显式类型声明,兼容Java 8及以上版本|
|4|绘制折线图时抛出`IllegalArgumentException`|XChart折线图不支持字符串类型X轴,要求为数字/日期类型|将X轴`List`改为`List`(年份数字),符合数据类型要求|
|5|爬取数据时请求被限制,页面获取失败|请求频率过快,豆瓣反爬机制拦截|添加随机延时`Thread.sleep(1000-3000ms)`,设置`User-Agent`模拟浏览器|
## 八、实验总结与体会
本次实验基于Java语言完成了豆瓣电影Top250从**数据爬取→数据清洗→数据分析→数据持久化→数据可视化**的全流程实现,综合运用了Jsoup、Stream API、OpenCSV、XChart等技术,实现了多模块的分层开发与协同运行。
通过本次实验,我深入掌握了Java网络爬虫的开发流程,理解了静态网页数据提取的核心原理,学会了处理网页结构变化、反爬机制等实际问题;熟练运用Stream API实现了高效的数据统计分析,体会到流式编程在数据处理中的简洁性与高效性;掌握了OpenCSV的使用方法,实现了结构化数据的持久化;学会了XChart可视化工具的基本用法,理解了“数据可视化”将抽象数据转化为直观图形的核心价值,同时解决了开发过程中的版本兼容、数据类型、异常处理等多个实际问题。
在实验过程中,我深刻认识到**面向对象分层设计**的重要性,将项目按功能拆分为多个独立模块,不仅提高了代码的可读性、可维护性,也便于问题定位与调试;同时,**异常处理**和**边界条件校验**是保证程序稳定性的关键,如爬取时的空指针处理、数据清洗时的正则匹配、可视化时的数据类型校验,缺一不可。此外,网络爬虫开发需遵循**文明爬虫**原则,设置合理的请求延时、模拟浏览器请求,避免对目标网站造成服务器压力。
本次实验也让我认识到,实际开发中网页结构、第三方库语法、开发环境等均可能出现预期外问题,需要具备**问题分析能力**和**调试能力**,通过查看官方文档、调试代码、分析报错信息等方式解决问题。后续可在此实验基础上进行功能拓展,如爬取电影主演、简介、类型等更多数据,实现按导演、国家/地区的统计分析,绘制更多维度的可视化图表,进一步提升数据挖掘与分析能力。
## 九、实验拓展方向
1. 拓展爬取字段:增加电影主演、剧情简介、电影类型、制片国家/地区等数据,丰富数据维度;
2. 增强数据分析:实现按导演、国家/地区、电影类型的统计分析,挖掘经典电影的导演、地域分布特征;
3. 优化可视化效果:添加图表中文乱码解决方案、自定义图表颜色/样式,实现更美观的可视化效果;
4. 增加数据校验:实现爬取数据的重复校验、缺失值处理,提升数据质量;
5. 开发图形界面:基于JavaFX/Swing开发简单的图形界面,实现“一键爬取→分析→可视化”的可视化操作。
> (注:文档部分内容可能由 AI 生成)