如果你正在选毕业设计题目,又想做一个技术栈完整、演示效果好、能讲出“业务闭环”的项目,这篇可以直接收藏。这次要拆解的是典型的“Python 计算机毕业设计”:基于 Hadoop 的招聘数据分析及可视化系统,整体技术栈包括 Python、Hadoop、Vue、爬虫、算法,并且配套源码、文档报告和代码讲解。项目核心不是“做一个网页”,而是围绕招聘数据构建一条完整的链路:用爬虫采集数据,用 Hadoop 做存储和计算,用算法做分析,最后用 Vue 做可视化展示。
这类项目的价值在于覆盖点非常广。从毕业设计的角度来评价,它能同时体现三件事:第一,你会写爬虫,能把互联网公开数据抓下来;第二,你了解大数据组件,能在 Hadoop 上完成数据落地和处理;第三,你会做 Web 系统,能把分析结果变成前端图表。这三个能力组合起来,基本就是一份“数据采集 + 大数据处理 + 可视化开发”的完整简历素材。从技术门槛看,它比普通管理系统类毕设要高,但比纯算法研究类要稳,属于“工作量可见、讲解空间大、答辩好讲”的类型。
接下来这篇文章会从系统整体设计、爬虫模块、Hadoop 数据处理、后端服务、Vue 可视化、部署流程、常见问题和答辩要点几个方向展开。每一步都尽量落到可操作层面,方便拿到源码后快速跑通,也方便自己二次修改。
1. 核心能力速览
先给一张速览表,方便你快速判断这个项目适不适合自己。
| 能力项 | 说明 |
|---|---|
| 项目类型 | 大数据分析与可视化 Web 系统,毕业设计类项目 |
| 技术栈 | Python、Hadoop、HDFS、MapReduce、Flask、Vue、ECharts |
| 数据来源 | 招聘网站公开数据,通过 Python 爬虫采集 |
| 核心功能 | 岗位数据采集、数据清洗、Hadoop 存储、统计分析、可视化看板 |
| 可视化能力 | 岗位分布、城市薪资、学历要求、经验要求、技能关键词等图表 |
| 算法应用 | 文本匹配、关键词提取、聚类分析等,用于技能标签和岗位分析 |
| 后端服务 | Flask 提供 JSON 数据接口,供 Vue 前端调用 |
| 前端框架 | Vue + Vue Router + Axios + ECharts |
| 运行环境 | Windows / Linux 均可,Hadoop 推荐用伪分布式模式部署 |
| 启动方式 | 分模块启动:爬虫 → Hadoop → 后端 → 前端 |
| 是否支持批量任务 | 是,爬虫可配置多页批量抓取,分析任务可批处理 |
| 适合读者 | 计算机相关专业本科毕业设计、大数据综合实践课程、想快速搭建数据分析展示系统的同学 |
从材料看,这个系统最大的优势不是某个单一技术多深入,而是完整度。数据能跑,分析能出结果,前端能展示,文档报告齐全,代码有讲解。对毕业设计场景来说,这种“完整闭环”比“单点炫技”更实用。
2. 适用场景与使用边界
这类系统适合的人很明确:需要毕业设计项目的本科生,尤其是计算机科学与技术、软件工程、大数据、信息管理这类专业;或者正在做大数据课程设计,想用真实数据做一套可视化演示系统的同学。它的业务链路足够长,答辩时可以从数据采集讲到前端渲染,每个环节都能展示工作量。
从技术价值来看,它能帮你补齐几个常见短板:
- Python 爬虫的实战能力,包括请求库、解析库、数据清洗。
- Hadoop 的基本使用方式,包括 HDFS 文件操作、MapReduce 统计逻辑、伪分布式环境搭建。
- 前后端分离开发方式,Vue 怎么调后端 API,ECharts 怎么渲染数据。
- 算法在实际系统里的落地方式,不是单纯跑模型,而是和业务数据结合起来。
使用边界也要说清楚。它不是一个实时招聘数据平台,不支持实时更新和高并发访问;它更多是“离线采集 + 离线分析 + 可视化展示”的架构。如果你要做实时监控,需要引入消息队列和流计算框架,这超出原项目范围。另外,招聘数据属于第三方平台公开数据,爬虫采集时要遵守网站 robots 协议、访问频率和公开数据使用规范,不要采集个人隐私信息,不要突破平台反爬技术,数据只能用于学习研究,不能商用或未经授权对外发布。
3. 系统整体架构与核心组成
这个项目从结构上看是典型的分层架构,数据从源头到展示一共经过四个环节。
3.1 四层架构
- 数据采集层:Python 编写爬虫,采集招聘网站的岗位名称、公司名称、城市、薪资、学历要求、经验要求、技能标签、发布时间等字段,存储为结构化数据文件。
- 存储计算层:Hadoop 分布式文件系统承载数据落地,MapReduce 完成离线统计计算,可按城市、学历、经验、薪资等维度聚合分析。
- 后端服务层:Python Web 框架封装分析结果,对外提供 JSON 接口,处理前端请求。
- 前端展示层:Vue 管理页面路由和状态,ECharts 渲染可视化图表。
3.2 开发环境建议
开发这个项目不需要太高的服务器配置。Hadoop 采用伪分布式模式,也就是在一台机器上同时运行 NameNode、DataNode、ResourceManager、NodeManager。推荐使用 Linux 环境或者虚拟机,Windows 也能跑,但要注意 ssh 免密配置和 Hadoop 本地库的兼容问题。后端和前端只需要普通开发机即可,内存建议 8GB 以上,磁盘预留 20GB 以上,因为 Hadoop 运行会产生日志和多份副本数据。
3.3 模块之间的关系
爬虫产出的数据是源头,Hadoop 分析的结果是中间产物,后端接口是连接桥梁,前端页面是最终展示。任何一个环节断了,系统都不算跑通。所以部署顺序也应该按照数据流向走:先装 Hadoop,再跑爬虫,然后写后端接口,最后启动前端页面。
4. 数据采集模块设计与实现
爬虫是整个系统的数据来源。没有数据,后面的 Hadoop 分析和 Vue 展示就没有意义。所以第一个要设计好的模块就是数据采集。
4.1 爬虫整体设计思路
爬虫负责从招聘网站获取岗位列表和岗位详情。常见实现方式有两种:一种是轻量级方式,使用 requests 请求页面,BeautifulSoup 或 lxml 解析 HTML;另一种是框架级方式,使用 Scrapy 构建爬虫工程,支持管道处理和去重。毕业设计场景下两种都可以,如果追求快速高效,用 requests + BeautifulSoup 就够了;如果想让项目结构更工程化,可以选用 Scrapy。
主要采集字段包括:
{ "job_name": "Python开发工程师", "company_name": "某科技有限公司", "city": "北京", "salary_min": 15000, "salary_max": 25000, "education": "本科", "experience": "3-5年", "skills": ["Python", "Hadoop", "Vue"], "publish_date": "2025-01-10", "job_url": "https://example.com/job/12345" }注意,salary_min 和 salary_max 是从类似“15-25K”这样的文本中解析出来的,这一步在清洗阶段完成。
4.2 requests 爬虫基础示例
下面给出一个通用的请求示例,实际使用时要替换为目标网站 URL,并遵守网站访问规则。
import time import random import requests from bs4 import BeautifulSoup headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8" } def fetch_page(url): """请求页面,失败时重试一次""" try: response = requests.get(url, headers=headers, timeout=10) response.raise_for_status() response.encoding = response.apparent_encoding return response.text except requests.RequestException as e: print(f"请求失败: {e}") return None def parse_job_list(html): """解析岗位列表,返回岗位名称、公司、城市等字段""" soup = BeautifulSoup(html, "html.parser") jobs = [] items = soup.select(".job-list-item") for item in items: job_name = item.select_one(".job-name") company = item.select_one(".company-name") city = item.select_one(".job-area") if job_name: jobs.append({ "job_name": job_name.get_text(strip=True), "company_name": company.get_text(strip=True) if company else "", "city": city.get_text(strip=True) if city else "" }) return jobs def crawl(start_page=1, max_page=10): all_jobs = [] for page in range(start_page, max_page + 1): url = f"https://example.com/jobs?page={page}" html = fetch_page(url) if html: jobs = parse_job_list(html) all_jobs.extend(jobs) time.sleep(random.uniform(2, 5)) return all_jobs if __name__ == "__main__": result = crawl() print(f"采集到 {len(result)} 条岗位数据")这个示例展示了基本的流程:构造请求头、请求页面、解析 HTML、循环翻页、控制频率。实际项目中,网站页面结构不同,选择器需要相应调整。关键是在采集过程中保持低频访问,不要对目标站点造成压力。
4.3 数据清洗与落地
采集后的原始数据通常包含缺失值、重复项、薪资文本、技能标签混杂等问题,需要先清洗再入 HDFS。清洗工作包括:
- 去重:以岗位链接或岗位标题 + 公司名称为去重依据。
- 统一格式:城市名统一为“北京”、“上海”等标准叫法;学历字段统一为“大专”、“本科”、“硕士”等枚举值。
- 薪资解析:把
"15-25K"解析成数值,方便后续统计。 - 技能字段:把“熟悉Python,掌握Hadoop”这类文本拆成技能标签。
清洗完成后,数据一般存为 CSV 或 JSON 文件,再上传到 HDFS。
import pandas as pd df = pd.read_csv("raw_jobs.csv") # 去重 df = df.drop_duplicates(subset=["job_url"]) # 薪资解析 def parse_salary(text): if not isinstance(text, str): return None, None text = text.replace("K", "").replace("k", "") parts = text.split("-") if len(parts) == 2: try: return int(float(parts[0]) * 1000), int(float(parts[1]) * 1000) except ValueError: return None, None return None, None df["salary_min"], df["salary_max"] = zip(*df["salary"].apply(parse_salary)) # 删除无薪资数据 df = df.dropna(subset=["salary_min", "salary_max"]) df.to_csv("cleaned_jobs.csv", index=False, encoding="utf-8")清洗后的文件就是 Hadoop 分析的输入。
5. Hadoop 存储与 MapReduce 分析
Hadoop 是这套系统的计算核心。从毕业设计角度来说,不需要搭建完整分布式集群,伪分布式模式足够说明问题。
5.1 Hadoop 环境准备
Hadoop 伪分布式模式需要准备以下基础环境:
- JDK,Hadoop 依赖 Java 环境运行。
- ssh,需要配置本机免密登录。
- Hadoop 安装包,按版本要求解压并配置环境变量。
- 修改 core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml 等配置文件。
启动流程通常是:
# 格式化文件系统(首次启动时执行) hdfs namenode -format # 启动 HDFS start-dfs.sh # 启动 YARN start-yarn.sh # 检查进程是否正常 jps如果 jps 能看到 NameNode、DataNode、ResourceManager、NodeManager 四个进程,说明 Hadoop 启动成功。这是整个系统里最容易出问题的一步,网上关于“Hadoop 伪分布式搭建”的教程很多,但核心顺序就这几个:改配置、免密、格式化、启动、看进程。
5.2 数据入 HDFS
清洗后的 CSV 文件需要上传到 HDFS,作为 MapReduce 的输入目录。
# 创建输入目录 hdfs dfs -mkdir -p /user/hadoop/job_data/input # 上传数据 hdfs dfs -put cleaned_jobs.csv /user/hadoop/job_data/input/ # 查看文件 hdfs dfs -ls /user/hadoop/job_data/input/5.3 MapReduce 分析维度
上传完成后,就可以编写 MapReduce 任务。在毕业设计场景中,常用分析维度包括:
- 不同城市的岗位数量分布。
- 不同学历要求的岗位数量。
- 不同经验年限的岗位数量。
- 薪资区间与学历的关系。
- 技能关键词出现频率。
这些统计逻辑很简单,MapReduce 的 Mapper 负责提取字段并输出 key-value,Reducer 负责聚合。以“按城市统计岗位数量”为例:
#!/usr/bin/env python3 import sys # Mapper def mapper(): for line in sys.stdin: fields = line.strip().split(",") if len(fields) > 2: city = fields[2].strip() if city: print(f"{city}\t1") # Reducer def reducer(): current_city = None count = 0 for line in sys.stdin: city, value = line.strip().split("\t") value = int(value) if current_city == city: count += value else: if current_city: print(f"{current_city}\t{count}") current_city = city count = value if current_city: print(f"{current_city}\t{count}") if __name__ == "__main__": if sys.argv[1] == "mapper": mapper() else: reducer()使用 Hadoop Streaming 提交任务:
hadoop jar $HADOOP_HOME/share/hadoop/tools/lib/hadoop-streaming-*.jar \ -input /user/hadoop/job_data/input \ -output /user/hadoop/job_data/output/city_count \ -mapper "python city_count.py mapper" \ -reducer "python city_count.py reducer" \ -file city_count.py任务跑完后,用hdfs dfs -cat /user/hadoop/job_data/output/city_count/part-00000查看统计结果。这个阶段你会看到 Hadoop 的核心用法:把任务拆成 Map 和 Reduce 两个阶段,适合离线批处理计算。
这里的实现可以有两种路径。第一种是直接写 MapReduce,学习价值高,但代码重复较多;第二种是引入 Hive,把数据加载成外部表,直接用 SQL 分析,开发效率更高。毕业设计如果时间紧张,建议用 MapReduce 实现两到三个核心统计任务,其他维度用 Hive 补充,答辩时能讲出技术选型的理由。
6. 后端服务与算法模块
Hadoop 分析后的结果存储在 HDFS 或导出为本地文件,后端服务需要把这些结果包装成接口,提供给前端调用。
6.1 后端框架选择
Python 后端常用 Flask 或 Django。Flask 轻量灵活,适合接口数量不多、以数据展示为主的毕业设计项目。Django 自带 Admin 和 ORM,适合包含后台管理功能的系统。从快速开发和代码量控制角度,推荐 Flask。
6.2 Flask 接口设计
接口设计一般围绕可视化页面来定,比如前端需要城市岗位分布图,后端就提供一个/api/city_distribution接口。
from flask import Flask, jsonify import pandas as pd app = Flask(__name__) @app.route("/api/city_distribution", methods=["GET"]) def city_distribution(): df = pd.read_csv("analysis/city_count.csv") data = { "cities": df["city"].tolist(), "counts": df["count"].tolist() } return jsonify({"code": 0, "data": data}) @app.route("/api/salary_by_education", methods=["GET"]) def salary_by_education(): df = pd.read_csv("analysis/salary_education.csv") data = { "education": df["education"].tolist(), "avg_salary": df["avg_salary"].tolist() } return jsonify({"code": 0, "data": data}) if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=False)接口返回结构统一为{"code": 0, "data": ...},前端根据 code 判断请求是否成功。这个约定在前后端联调时非常有用,能减少沟通成本。
6.3 算法模块设计
标题里提到的“算法”不是一个独立的大模块,而是结合业务场景设计的一些算法应用。常见的落地点包括:
- 岗位技能关键词提取:对 JD 文本做分词,使用 TF-IDF 提取代表岗位的技能词。
- 岗位聚类分析:基于薪资、学历、经验等特征对岗位进行聚类,发现岗位群组规律。
- 技能匹配度计算:根据用户掌握的技能和岗位要求技能做匹配,计算匹配度。
- 字符串匹配算法:在技能关键词搜索或岗位名称匹配中,可以使用 KMP 等高效文本匹配算法。
以 KMP 为例,它解决的是“在主串中查找模式串”的问题,和岗位名称搜索、技能关键词匹配场景很贴合。比如用户输入“python”,系统要去岗位名称列表里快速找出包含该关键词的所有岗位。
def kmp_search(text, pattern): """KMP 字符串匹配,返回模式串在主串中的起始索引,未找到返回 -1""" n, m = len(text), len(pattern) if m == 0: return 0 # 构造 next 数组 next_arr = [0] * m j = 0 for i in range(1, m): while j > 0 and pattern[i] != pattern[j]: j = next_arr[j - 1] if pattern[i] == pattern[j]: j += 1 next_arr[i] = j # 匹配过程 j = 0 for i in range(n): while j > 0 and text[i] != pattern[j]: j = next_arr[j - 1] if text[i] == pattern[j]: j += 1 if j == m: return i - m + 1 return -1 if __name__ == "__main__": text = "高级Python开发工程师" pattern = "Python" index = kmp_search(text, pattern) print(f"匹配位置: {index}")答辩的时候,算法部分不要求讲得多深,但要讲明白“为什么用这个算法、应用在哪个场景、解决了什么问题”。比如 KMP 用于关键词匹配,比暴力匹配效率更高,适合在大量岗位数据中快速搜索。
6.4 后端与 Hadoop 的关系
后端接口不直接读 HDFS 里的文件,而是读取 MapReduce 分析后导出的结果文件。原因是 Hadoop 执行批处理任务较慢,不适合放在每个用户的请求链路里。更好的做法是:先定时跑 Hadoop 分析,把结果导出到本地或 MySQL,后端接口再做轻量查询。这种“离线计算 + 在线查询”的架构在实际项目中也很常见。
7. Vue 可视化系统实现
前端是整个项目的门面,也是答辩时最直观的展示部分。技术栈是 Vue + Vue Router + Axios + ECharts。
7.1 前端页面结构
整体页面通常分为若干模块:
- 数据总览:显示岗位总数、公司数量、城市数量、平均薪资等核心指标。
- 岗位地域分布:地图或柱状图展示各城市岗位数量。
- 薪资分析:折线图展示不同岗位或城市的薪资分布。
- 学历与经验分析:饼图或环形图展示学历要求、经验要求占比。
- 技能标签云:词云展示热门技能关键词。
- 公司招聘排行:列表展示招聘岗位最多的公司。
7.2 Vue 组件与 ECharts 示例
下面是 ECharts 柱状图组件的简化示例。
<template> <div id="cityChart" style="width: 100%; height: 400px;"></div> </template> <script> import * as echarts from "echarts"; import axios from "axios"; export default { name: "CityChart", data() { return { chart: null }; }, mounted() { this.initChart(); this.loadData(); }, methods: { initChart() { this.chart = echarts.init(document.getElementById("cityChart")); }, async loadData() { const res = await axios.get("/api/city_distribution"); if (res.data.code === 0) { const data = res.data.data; this.chart.setOption({ title: { text: "岗位城市分布" }, tooltip: {}, xAxis: { data: data.cities }, yAxis: {}, series: [{ name: "岗位数量", type: "bar", data: data.counts }] }); } } }, beforeDestroy() { if (this.chart) { this.chart.dispose(); } } }; </script>这个组件做的事情很清晰:初始化 ECharts 实例,然后调用后端接口获取城市岗位数据,最后把数据设置到图表中。需要注意的地方是:容器 div 必须有明确宽度和高度,否则图表渲染不出来;异步渲染时要在接口返回后再 setOption。
7.3 前端路由与访问地址
使用 Vue Router 配置页面路由,本地开发时通过代理解决跨域问题。
import Vue from "vue"; import VueRouter from "vue-router"; import Dashboard from "../views/Dashboard.vue"; import SalaryAnalysis from "../views/SalaryAnalysis.vue"; Vue.use(VueRouter); const routes = [ { path: "/", redirect: "/dashboard" }, { path: "/dashboard", component: Dashboard }, { path: "/salary", component: SalaryAnalysis } ]; const router = new VueRouter({ mode: "history", routes }); export default router;开发环境启动命令通常是:
npm install npm run serve访问http://localhost:8080就能看到系统首页。生产环境可以执行npm run build构建静态文件,然后交给 Flask 托管或部署到 Nginx。
8. 部署流程与开发顺序建议
拿到项目源码后,不建议直接一头扎进前端页面。正确做法是按数据依赖关系,从底层往上层逐层跑通。
8.1 推荐启动顺序
- 启动 Hadoop,验证 HDFS 可用。
- 运行爬虫,采集数据并清洗,保存为 CSV。
- 将清洗后的数据上传到 HDFS。
- 运行 MapReduce 分析任务,导出统计结果。
- 启动 Flask 后端,用 Postman 或浏览器测试接口。
- 启动 Vue 前端,访问页面,确认图表数据正常。
8.2 最小验证用例
为了让系统尽快跑通,可以先用 100 条测试数据验证全流程:
- 准备好 100 条招聘数据样例。
- 直接上传到 HDFS,跳过爬虫采集步骤。
- 运行一个 MapReduce 任务,比如按城市统计岗位数量。
- 查看输出结果文件。
- 编写一个 Flask 接口读取结果文件。
- 前端调用接口展示柱状图。
这条链路跑通,说明 Hadoop、后端、前端三个环节都正常,之后再回来优化爬虫和数据清洗的细节。先保证“能用”,再追求“完善”。
9. 常见问题与排查方法
根据常见的毕业设计开发情况,这里整理了一份排查清单。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Hadoop 启动后进程缺失 | ssh 免密未配置、配置文件参数错误 | 执行jps查看进程;查看/usr/local/hadoop/logs/日志 | 配置 ssh 无密码登录;检查 core-site.xml、hdfs-site.xml 配置;重新格式化需要先删除临时目录 |
| HDFS 上传文件失败 | NameNode 未启动、目录权限不足 | 执行hdfs dfs -ls /验证文件系统可用 | 确认 NameNode 进程存在;使用hdfs dfs -mkdir -p创建目录;检查用户权限 |
| 爬虫采集不到数据 | 页面结构变化、请求被拦截、编码问题 | 打印 response.text 前 500 字符;检查页面选择器;检查返回状态码 | 更新 CSS 选择器;设置合理请求头;控制访问频率;必要时增加 Cookie |
| 中文乱码 | 文件编码不统一 | 用file命令或编辑器查看编码 | 统一使用 UTF-8 编码;pandas.read_csv指定encoding="utf-8" |
| MapReduce 任务失败 | 输入输出路径错误、代码有误、没有使用 streaming jar | 查看 YARN 日志 | 检查输入目录是否存在;确认输出目录未存在;调整 mapper/reducer 脚本参数 |
| Flask 接口返回 404 | 路由路径错误、未启动 Flask | 控制台查看请求路径 | 检查 app.route 路径;确认 Flask 监听端口 |
| Vue 页面图表不显示 | 容器没有高度、ECharts 初始化过早、接口未返回 | 打开浏览器控制台看报错;检查接口返回 | 给容器设置固定高度;在 mounted 中初始化;添加 loading 状态 |
| 前端接口跨域 | 前后端端口不同导致跨域 | 浏览器控制台显示 CORS 报错 | 开发环境使用 Vue 代理;后端开启 CORS 支持 |
这里要特别注意 Hadoop 的重置问题。很多同学格式化 NameNode 之后直接启动,结果 DataNode 和 NameNode 的 clusterID 不一致,导致 DataNode 反复退出。解决方法是将 Hadoop 临时目录和日志目录清空,再重新格式化 NameNode,之后一次性启动所有进程。
10. 毕业设计答辩与项目改进方向
答辩是毕业设计的重要一环。项目做出来了,还要能讲清楚。这套系统在答辩时可以按一条主线来展示:从招聘数据采集开始,到 Hadoop 存储和离线分析,再到 Flask 后端接口,最后是 Vue 可视化页面。核心要讲明白三件事:数据是怎么来的,数据是怎么算的,结果是怎么展示的。
建议在答辩前准备一张系统架构图,把四个模块之间的调用关系画清楚。讲爬虫时重点讲数据规模和字段设计,讲 Hadoop 时重点讲分析维度和 MapReduce 逻辑,讲算法时重点讲匹配和聚类在实际业务中的应用,讲前端时重点讲图表和数据的对应关系。如果老师追问“为什么用 Hadoop”,可以回答:这是离线批处理场景,招聘数据量大且不需要实时计算,Hadoop 适合存储大规模结构化文件并通过 MapReduce 做分布式统计,比单机处理更有扩展性。
关于改进方向,可以提几个让项目更有亮点的地方:
- 引入 Spark 替代部分 MapReduce 任务,提高计算效率。
- 引入 Hive 管理分析任务,用 SQL 快速实现更多统计维度。
- 使用 MySQL 存储最终分析结果,让后端查询更快。
- 增加用户登录和报告导出功能,完善系统业务闭环。
- 使用定时调度框架定时触发爬虫和分析任务,实现数据自动更新。
- 增加岗位画像和用户推荐功能,把算法权重从关键词匹配提升到推荐场景。
不用全部实现,选一两个能讲清楚的方向说就行。毕业设计评审更看重的往往不是功能多少,而是你对自己的项目是否有清晰的理解。
最后总结一下这个项目最值得做的事情:先用最少数据跑通一条主链路,确认 Hadoop、Flask、Vue 三个模块连接正常;再逐步补充爬虫数据规模和可视化图表数量;最后整理好文档报告,把 MapReduce 任务、算法模块、接口设计这几个核心点写清楚。如果开发过程中遇到环境配置问题,优先检查日志,Hadoop 的日志、Vue 的浏览器控制台、Flask 的终端输出都能给出明确线索。这套项目做完,你对 Python 爬虫、Hadoop 数据分析、Vue 可视化开发的整体理解会上一个台阶,拿去做答辩演示也有足够的技术支撑。