ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

共享单车大数据分析毕设全攻略:Hadoop+Spark+Hive架构与实战

2026/9/10 2:30:30 拓冰建站 浏览量
共享单车大数据分析毕设全攻略:Hadoop+Spark+Hive架构与实战 共享单车大数据分析这套毕设我愿称之为大数据入门全家桶。它把Hadoop、Spark、Hive、爬虫、可视化这些最常被问到的技术点串在了同一个项目里做完这一套你对离线数仓的认知绝对会上一个台阶。网上类似的题目很多但大多数开源代码要么环境老得跑不起来要么图表做得很糊弄根本没法直接抄。这篇文章我会把整体架构怎么定、数据从哪来、每个环节怎么落地、以及你会踩到的坑一次性讲明白。如果你是零基础或者只学过Java/Python完全不用担心我会尽量把每一步的“为什么”也说清楚而不是只丢给你一堆命令。毕竟毕设答辩时老师最常问的就是“你为什么要这么设计”这个答不上来项目做得再花哨也白搭。1. 整体架构设计与技术选型思路先聊架构。共享单车分析这个题目本质上就是一个典型的离线数仓项目数据从业务系统来经过采集、清洗、分析最终以报表或大屏的形式呈现。所以最稳妥的套路就是分层处理每一层各司其职。我最终敲定的架构是这样的爬虫负责采集原始数据包括车辆信息、行程记录、站点信息数据落地到HDFSHive做数据清洗和ETL把杂乱无章的原始数据转换成结构化、可分析的表Spark负责跑核心的离线分析任务比如热度排名、潮汐规律、骑行OD分析最后用Spring Boot后端 ECharts前端把分析结果展示成可视化大屏。你可能会问为什么不能只用Hive或者只用Spark这个问题几乎必被答辩老师问到。答案是Hive适合做批处理和数据转换写起来简单底层是MapReduce跑大一点的join会慢到让你怀疑人生。Spark是基于内存的迭代计算速度比MapReduce快很多做复杂分析或者多次迭代时优势极其明显。用一句话概括就是Hive负责“把数据整理好”Spark负责“把数据算出来”。再来说为什么数据落地要用HDFS而不是普通文件系统。HDFS是分布式存储多个节点一起扛数据天然支持数据备份这对毕设来说也许感知不强但它是整个大数据生态的地基。面试时被问到“HDFS和传统文件系统的区别”本质考的就是这套分布式存储机制。技术版本方面我要特别提醒一句网上很多教程的版本组合已经过时了照抄必然翻车。我的选择是Hadoop 3.3.4 Spark 3.3.0 Hive 3.1.3 Scala 2.12 JDK 8这个组合经过大量实测兼容性最稳也是目前主流教程覆盖最多的版本组合。你可能还听说过一套新组合叫Flink流处理 Doris实时数仓那是实时数仓的方向跟这个题目的“离线分析”定位不同。毕设不需要追新关键是解决业务问题能用稳定的技术把结果算出来就是最好的方案。2. 核心业务模块与数据采集设计2.1 共享单车数据分析的核心业务问题既然做数据分析先得明确我们要算哪些东西。不是把数据查出来就完事了而是要回答几个有业务价值的问题共享单车一天当中哪个时段骑行量最高哪些区域是热点用户骑行距离和时长分布是怎样的早高峰和晚高峰的潮汐流动方向是什么我把核心分析主题拆成了四大类骑行时段与温度分析、热点区域与站点热度排名、骑行距离与时长分布、潮汐规律分析也就是OD分析。这四大类覆盖了绝大多数共享单车项目的可视化大屏需求也方便你在论文里写“业务背景与分析目标”。以OD分析为例O是出发地OriginD是目的地Destination。共享单车的核心痛点就是潮汐现象——早上大家都从住宅区骑到地铁站晚上再骑回来导致某些站点车满为患或无车可骑。通过OD分析我们能算出每个时段里O点和D点的主流流向这背后其实是一个城市公共交通规划的问题。2.2 共享单车爬虫的数据维度设计数据从哪来是个关键问题。毕设题目里写了“共享单车爬虫”所以你需要一个爬虫程序来获取数据。这里的数据源通常是某些城市开放数据平台或共享单车应用开放接口需要注意接口协议和数据质量。我设计的爬虫目标数据有三类。第一类是车辆基本信息包括车辆ID、车辆类型、经纬度坐标、状态。第二类是骑行订单记录包含订单ID、车辆ID、用户ID、出发时间、到达时间、出发站点、到达站点、骑行时长、骑行距离。第三类是站点信息包含站点ID、站点名称、经纬度、容量。爬虫不是写完就完事的你要考虑反爬策略。我碰到的典型情况是请求频率稍微快一点对方的服务端就直接返回验证码或者干脆拒绝连接。解决办法很朴素控制请求频率比如随机间隔1到3秒再发送下一次请求随机轮换User-Agent伪装成不同的浏览器设置请求重试机制失败后等待几秒重新请求不要硬灌。2.3 爬虫数据落地的规范爬虫爬下来的数据是JSON格式这个格式适合传输但不适合分析所以我先把原始JSON原样保存在HDFS的/raw_data目录下作为最原始的数据资产然后再用Hive来解析和清洗。有个很小的细节特别容易被忽略JSON文件里的中文可能出现乱码必须在爬虫里就统一指定UTF-8编码写入不能让编码错误污染到下游。对于HDFS的目录设计我的习惯是带上日期分区格式为/raw_data/dt2025-01-01这样后面做增量处理时特别方便直接用dt字段过滤就行不用全表扫描。因为爬虫每天都在跑累积的数据量会越来越大如果没有分区策略后期任务跑起来就会特别慢。3. 环境搭建与集群部署避坑实录3.1 集群规划合理评估资源集群怎么搭直接影响后续所有任务的稳定性。如果你是纯单机跑我的建议是至少给虚拟机分配4GB内存和2核CPU否则启动三个Hadoop进程就已经很吃力了再跑Spark任务大概率直接OOM。我用的是一台8核16GB的机器单机伪分布式部署。如果你手头资源够可以做成1个Master节点 2个Worker节点的集群这样在论文里能写“分布式集群环境”也方便展示HDFS的数据块备份机制。JAVA_HOME必须配置正确这是无数人踩坑的起点。用java -version确认版本是8推荐用OpenJDK 8或Oracle JDK 8然后export出来Hadoop的hadoop-env.sh里也要手动指定JAVA_HOME别偷懒否则启动DataNode时会报错。3.2 Hadoop伪分布式搭建要点Hadoop的配置集中在core-site.xml、hdfs-site.xml、yarn-site.xml这三个文件里。core-site.xml里设置fs.defaultFS为hdfs://localhost:9000hdfs-site.xml里设置replication为1伪分布式环境下一份数据就够了yarn-site.xml设置yarn.nodemanager.resource.memory-mb为4096以上否则跑Spark任务时容器内存会不够用。启动顺序千万别搞错先格式化NameNodehdfs namenode -format再启动HDFSstart-dfs.sh再启动YARNstart-yarn.sh。格式化这个操作只能做一次重复格式化会导致NameNode和DataNode的clusterID不一致启动时DataNode会莫名其妙地挂掉。这个问题出现的频率极高原因和解决办法我都写在后面的问题排查部分。启动HDFS后一定要通过Web界面确认节点状态浏览器访问50070端口看看NameNode和DataNode是否都是活跃状态。如果你开了防火墙记得把相关端口放行这个也容易卡住很久。3.3 Hive安装与MySQL元数据库配置Hive本身不存数据它只是把SQL翻译成MapReduce或Spark任务去HDFS上跑。但Hive的元数据表结构、字段、分区默认存储在自带的Derby数据库里Derby只支持单会话连接意味着你开两个Hive客户端就会报锁错误。所以第二步一定要把元数据库切换到MySQL。在hive-site.xml里配置javax.jdo.option.ConnectionURL指向本机的MySQLdriver、username、password都对应填好。MySQL里提前建好hive数据库再执行schematool -dbType mysql -initSchema初始化元数据表结构。测试连接时先启动HDFS再启动Metastore和HiveServer2。HiveServer2启动后用beeline去连接如果能够执行show databases说明Hive基本可以用了。接下来在Hive里建原始表、清洗表、分析结果表这是下一节要展开的内容。3.4 Spark安装与YARN模式配置Spark我选择以YARN模式运行这样可以让YARN统一管理CPU和内存资源。Spark解压后主要改spark-env.sh设置JAVA_HOME、HADOOP_CONF_DIR、SPARK_MASTER_HOST这几个变量。提交任务时用spark-submit --master yarn --deploy-mode client的方式指定executor数量和内存。这里有个很常见的坑Spark默认的executor内存只有1GB跑稍大一点的数据集就报内存溢出。我一般设置--executor-memory 2g、--driver-memory 2g。为什么推荐YARN模式而不直接用local模式因为YARN是分布式的资源调度框架能让你体会到大任务是如何被划分到不同执行器上的。在论文里你可以把YARN的资源分配机制作为重点来讲解这是加分项。3.5 Zookeeper与高可用拓展如果集群规模超过一台机器高可用模式是需要考虑的方向。Zookeeper解决了NameNode主备切换的问题——主节点挂了备用节点能自动顶上来。网上热词里也提到了“hadoop和zookeeper整合实战”如果你想在论文里加一点亮点可以考虑把NameNode高可用做进去。具体做法是准备两台NameNode节点一台Active一台Standby它们通过Zookeeper保持状态同步客户端连接时走Zookeeper选主主节点故障后自动切换。这一块内容在毕设答辩时是一个极好的加分点但前提是你自己得真的理解它的工作原理不然老师追问下很容易露出破绽。4. Hive表设计与数据ETL处理4.1 数仓分层ODS层 vs DWD层我在Hive里严格做了分层设计这也是目前企业中数仓建模的主流做法。第一层叫ODS层原始数据层直接存放从HDFS映射过来的原始表第二层叫DWD层明细数据层存清洗后的明细数据第三层叫ADS层应用数据层存面向最终分析结果的聚合表。为什么一定要分层因为第一层做数据落地第二层做数据净化第三层做数据输出每层职责清晰出了问题你知道该去哪一层排查。这也是答辩时老师很认可的设计思路。ODS层建表时我选择把JSON字段直接存成STRING类型等ETL时再解析这样建模最灵活原始数据想怎么重建都行。DWD层表则是把json拆解成一个个字段过滤掉脏数据并转成Parquet列式存储格式。Parquet格式值得多说一句它是列式存储压缩率高查询性能好Hive和Spark对它都有原生支持。同样是1GB的数据存成文本格式可能占1GB存成Parquet可能只占300MB跑分析时扫描的数据量也少得多。毕设里用上这个格式论述“数据存储优化”时就有东西可写了。4.2 建表语句与分区策略ODS层建表语句如下CREATE EXTERNAL TABLE ods.trip_ride( ride_id STRING, vehicle_id STRING, user_id STRING, start_time STRING, end_time STRING, start_station_id STRING, end_station_id STRING, duration_sec BIGINT, distance_m DOUBLE ) PARTITIONED BY (dt STRING) ROW FORMAT SERDE org.openx.data.jsonserde.JsonSerDe LOCATION /warehouse/ods/trip_ride;注意我使用了EXTERNAL关键字也就是外部表表结构删除后数据依然保留。使用JsonSerDe可以直接解析JSON格式文件省去自定义MapReduce的麻烦。分区字段dt来自爬虫目录加载数据时只要把分区目录指向对应日期即可。DWD层清洗后的表一个字段对应一个列格式如下CREATE EXTERNAL TABLE dwd.trip_ride_clean( ride_id STRING, vehicle_id STRING, user_id STRING, start_time TIMESTAMP, end_time TIMESTAMP, start_station_id STRING, end_station_id STRING, duration_min INT, distance_km DOUBLE, is_valid INT COMMENT 1有效 0无效 ) PARTITIONED BY (dt STRING) STORED AS PARQUET LOCATION /warehouse/dwd/trip_ride_clean;ETL清洗在这个环节就是INSERT OVERWRITE SELECT把ODS层的数据过滤后写入DWD层。清洗规则包括剔除start_time或end_time为空的数据剔除duration小于60秒或大于4小时的数据这类数据大概率是异常解锁产生的剔除distance为0的数据剔除经纬度越界的脏数据。最后加一个is_valid标记字段先保留数据原样然后打上合法标记这样后续分析既能只用合法数据又能追溯异常问题。4.3 Hive SQL优化Hive SQL优化是论文技术章节里可以深入展开的部分。我最常用的优化手段包括只想看某一天的数据就在where条件里加dt分区过滤避免全表扫描两张表关联时小表放前面让Hive先加载小表到内存里做Map端join避免走Reduce端join大表关联避免数据倾斜时使用skew join优化。Hive的排序也有讲究order by是全局排序数据量大时非常慢distribute by sort by是分区内排序可以让每个reduce都只处理自己那部分数据再排序速度快得多。网上热词里有“hive中partition by和distribute by的区别”说明这个是高频考点。partition by是窗口函数的分区distribute by是控制Map输出如何分发到Reducer上的两者作用完全不同别搞混了。5. Spark离线分析任务开发5.1 Spark分析的整体思路Hive把数据洗干净后真正的分析计算交给Spark来做。为什么不全用SQL分析因为有些复杂逻辑比如热力图数据点抽取、多维度交叉统计SQL写起来比较绕而Spark用DataFrame API或Spark SQL可以直接把数据加载成表写法和SQL类似但计算引擎更快。我的分析程序统一用Spark SQL来写原因有三代码可读性强答辩时方便解释Spark SQL底层会经过Catalyst优化器做谓词下推、列剪枝等优化比手写RDD算子更高效最终结果写回Hive ADS表时直接saveAsTable就行不用自己拼接路径。5.2 核心分析案例骑行时段与站点热度骑行时段分析的做法是从DWD层读取骑行记录用hour函数提取出发时间的小时值然后按小时分组统计订单数和平均骑行时长。这个数据放在折线图上你一眼就能看出一天中出现两个骑行高峰大概在早上7点到9点和傍晚17点到19点这是共享单车典型的通勤特征也是论文里分析城市潮汐规律的重要依据。站点热度分析稍微复杂一点。我把出发站点和到达站点拆开各统计一份出发量和到达量然后进行排名。出发量最高的一般是住宅区附近到达量最高的一般是写字楼、地铁站附近。如果一个站点出发量远大于到达量说明它是车辆流失点运营方需要往这里调车。这种分析结果可以直接做成地图热力图体现数据挖掘的商业价值。5.3 Spark任务提交与内存调优写好的Spark分析任务打包成JAR后我用以下命令提交spark-submit \ --master yarn \ --deploy-mode client \ --class com.bigdata.bike.StationHotAnalysis \ --executor-memory 2g \ --driver-memory 2g \ bike-analysis.jar内存调优是我个人花时间最多的地方。刚开始时我设置executor内存只有1g跑全量数据固定报Java heap空间不足错误。后来我确认了Spark内存模型中的三个关键概念执行内存负责shuffle、join等操作存储内存负责缓存DataFrame和RDD保留内存是系统预留的。提交任务时不要只看总内存还要看执行内存和存储内存的比例默认是0.6比0.4纯跑分析任务时可以把执行内存比例调高一些让shuffle更从容。还有个小知识点动态资源分配在YARN模式下是默认关闭的如果你的任务队列充足可以考虑开启spark.dynamicAllocation.enabledtrue让Spark根据任务负载自动调节executor数量。5.4 Spark on YARN常见坑Spark on YARN模式下最容易被卡住的是日志查看。用yarn logs -applicationId查看应用日志时很多人发现除了INFO什么也没有这是因为日志级别默认设置到了WARN。你可以临时把根日志级别调成WARN之上也可以直接在代码里用logger记录关键计算结果并打印到控制台这样在client模式下能直接看到结果输出便于快速验证。另外还有一个非常真实的坑本地写好的Spark代码放到集群上跑之前要联网检查依赖包的版本。我第一次提交时一直报NoClassDefFoundError原因就是本地依赖的某个Jackson版本和Hadoop自带的版本冲突。这类问题最好提前排查省得到答辩前临时爆炸。6. 可视化方案与大屏联动实现6.1 可视化技术选型Spring Boot ECharts可视化部分我选用Spring Boot ECharts这套组合。Spring Boot负责提供后端接口从MySQL或Hive的结果表里读取数据封装成JSON返回给前端ECharts负责把JSON数据渲染成图表。为什么不直接在Hive上跑前端查询呢因为Hive的查询延迟太高不适合实时交互。所以我的做法是把Spark分析结果输出到MySQL前端的所有查询都走MySQL这样大屏刷新时可以做到秒级响应。这也是业界常见的“离线计算 实时展示”组合套路。后端接口的设计按分析主题拆分/api/hour-trend返回每小时骑行量/api/top-stations返回站点热度排名/api/od-flow返回OD流向矩阵/api/distance-dist返回骑行距离分布。前端拿到JSON分别渲染折线图、柱状图、地图热力图和饼图。6.2 可视化大屏如何做出高级感可视化大屏的视觉体验决定答辩老师的印象分。配色方案我用深色背景配高亮色图表深色背景有科技感能掩盖数据不足时图表的单薄。标题区放项目名主体区排列4张核心图表底部放数据统计卡片整体结构参照监控大屏的经典布局。ECharts做GIS地图时要手动引入GeoJSON数据并在series里的map属性指定区域才能把站点热度叠加在地图上。动态刷新是加分项。我通过定时器每隔30秒重新请求接口模拟实时数据更新这对答辩展示效果帮助非常大直接让大屏“活起来”。另外ECharts的折线图加上平滑曲线柱状图用渐变颜色饼图用南丁格尔玫瑰图这些细节都会让评委觉得你花了心思。6.3 可视化结论如何反哺业务可视化不只是画图最好能在论文里写出数据背后的业务结论。比如“早高峰时段地铁站附近骑行需求激增而社区周边车辆大量闲置建议运营方增加地铁站的车辆调度频次”。这类结论放在论文的结果分析部分会显著提升项目的应用价值。我会在后端写一个统计汇总模块把核心指标自动生成中文结论比如骑行峰值时段、最大热点站点、平均骑行时长等前端直接展示这些结论文字配合图表形成“数据 结论”的完整闭环。7. 常见报错与调试方案速查这个部分是压箱底的干活我把毕设过程中最常遇到、最让人头皮发麻的几个问题整理出来并附上排查思路和解决方案。7.1 Hadoop启动格式化失败或DataNode无法启动这个问题出现频率最高。原因通常是重复执行了多次hdfs namenode -format导致NameNode的clusterID和DataNode的clusterID不一致。DataNode启动时会检查clusterID对不上就直接拒绝启动。解决办法很直接停止所有Hadoop进程删除每个节点上的tmp目录一般在/tmp/hadoop-*或你指定的hadoop.tmp.dir重新执行hdfs namenode -format然后依次Start。这个操作等于是把所有元数据都清空重新来过了属于重装级别的手段。另外要注意如果配置过HA高可用在执行格式化之前记得先把JournalNode启动起来否则格式化会提示失败。7.2 Hive中文乱码Hive表里中文注释或中文字段值显示乱码多半是MySQL元数据库的编码问题。在建hive数据库时执行以下语句CREATE DATABASE hive CHARACTER SET utf8mb4;然后修改hive-site.xml里的连接URL加上useUnicodetruecharacterEncodingUTF-8。改完要重启Metastore并刷新对应的表元数据缓存否则还是显示乱码。爬虫写入数据时也要确保源文件本身是UTF-8编码环环相扣。7.3 Spark任务OOM内存溢出这个问题的排查思路主要是两步先看任务执行计划定位是哪个stage失败再调整executor内存和并行度。如果是join或groupBy操作导致的OOM多半是因为某个key的数据特别大比如某个站点的订单量占据了总量的50%出现了数据倾斜。解决办法包括对热点key加随机前缀打散之后再聚合或者用spark.sql.shuffle.partitions把shuffle分区数调大。分区默认是200我实测在共享单车这个数据量下调整到400效果更好。7.4 Hive字符串和数值类型转换报错我用JsonSerDe解析数据时JSON里某个数值字段在个别记录中缺失或为空字符串导致Hive在转换类型时直接报错。解决办法是先把JSON里的字段类型全当STRING读进来然后在清洗SQL里用case when做判断对空值进行统一处理再显式转成数值类型。这种“先落原始类型后转换”的思路在数仓开发中非常常见值得养成习惯。7.5 Spark SQL书写报错cannot recognize input near你写的SQL中出现了Hive支持但Spark SQL不支持的关键字或语法比如某些正则函数或INSERT语法。解决办法是确认版本差异参考Spark官方SQL文档调整写法。遇到相关报错时对照官方文档去改很快能定位。7.6 MySQL连接数与并发问题可视化大屏开启了多个定时刷新请求后MySQL偶尔报连接数过多无法连接。因为项目里连接池配置太小默认10个连接扛不住并发请求。解决办法是把HikariCP的最大连接数调大一些比如设置为50同时适当缩短连接超时时间。7.7 端口被占用导致服务启动失败HDFS的50070端口或Spark Web UI的4040端口被其他进程占用时服务会启动失败。用lsof -i:50070或netstat -tlnp | grep 50070确认占用进程然后改配置文件里的端口或杀掉占用进程。开发机上这种问题很常见不用慌。8. 从毕设到答辩论文写法与面试考点8.1 论文技术章节的写作结构论文的技术章节我建议按五个层次来组织总体架构设计、数据采集模块、数据存储与ETL、离线计算分析、可视化展示与结论。每一章开头先写需求背景再写技术方案最后写实现细节和实验结果。架构图用一张分层图把“采集层、存储层、计算层、应用层”画清楚数据流向用箭头标明。存储层重点画HDFS目录结构计算层画Spark任务提交流程应用层画后端接口和前端图表对应关系。8.2 答辩必问问题与回答思路答辩时老师最爱问的几个问题你一定要提前准备。第一个问题是“你的数据从哪里来的”回答思路是说明爬虫数据源的合法性与公开性讲清楚爬虫的字段设计和清洗逻辑强调采集频率限制和数据量规模。第二个问题是“Hadoop、Spark、Hive各自的作用和区别”这是最基础但最常问的问题要把各组件在项目中的具体职责讲清楚如果能说清“HDFS管存、MapReduce淘汰、Spark管算、Hive管SQL接口”这个分工基本就稳了。第三个问题是“如果数据量扩大10倍你的方案怎么优化”这是一个典型的扩展性拷问。第三个问题的回答思路是存储上用HDFS横向扩容节点就能解决容量问题计算上Spark可以动态增加executor数量分析上可以做数据分区裁剪只扫描要用的日期调度上可以用分布式任务调度工具来管理多个分析任务。把横向扩展的思路和当前架构的对应关系讲清楚比背一堆理论更有说服力。8.3 毕设常见的三个心理误区做这套毕设我发现很多人容易陷入几个误区提前说破能帮你少走弯路。第一个误区是贪多求全总想加更多组件。有人想把Flink、Kafka、ClickHouse全塞进项目里还觉得“技术栈越新越好”。实际上毕业设计的评分核心是逻辑完整性和解决问题的能力盲目堆组件只会给自己埋雷任何一个环节不稳定都可能让你在答辩时无法演示。第二个误区是忽视数据质量。有些人爬下来的数据根本不清理就直接做分析得出“骑行时长1000小时”的荒唐结果。数据分析结果的可靠性完全取决于数据质量ETL清洗部分一定要花心思并把清洗前后数据的对比写进论文里这反而是一个亮点。第三个误区是重代码轻文档。代码跑通只是第一步怎么把设计的理由、实现的过程、踩坑的排查过程写清楚才是论文的真正难点。很多同学代码写得很好却拿不到高分问题就出在论文写得像流水账没有体现系统性思考和问题解决能力。9. 项目复盘与后续扩展方向最后再分享一些项目完成后的想法。我在做这套毕设时最大的瓶颈其实不是技术而是对业务问题的思考深度。一开始我只是想“把数据展示出来”后来才慢慢理解“分析结果要能解释一个现实问题”。如果你能在论文里把“潮汐规律如何影响车辆调度”“哪些站点在什么时段容易无车可骑”讲清楚项目的价值就会明显提升。如果你做完这套项目之后还有余力想继续扩展有几条路可以探索。一个是加入实时数据管道把Kafka和Flink引入项目中实现订单数据的流式分析在可视化大屏上展示实时骑行量这样就从“离线数仓”升级到了“实时数仓”技术层次会高出不少。另一个是引入机器学习做骑行需求预测基于历史时段的订单数据预测未来一小时的订单量这能进一步和“智慧城市”的概念挂钩项目的高度完全不一样。坦白说共享单车这个题目在毕业设计里已经算比较“卷”的了因为每年都有大量人选类似题目。真正让你分高的是差异化——要么在分析方法上有独特视角要么在工程实现上技高一筹要么在可视化体验上让人眼前一亮。照着文章的思路把每一个环节真正做扎实、想透彻答辩的时候你自然讲得出东西。我第一次跑通全流程的那天晚上看到大屏上的数据图表动起来的那一刻那种成就感确实很值。希望你也一样做完这套项目后不仅有了一个高分毕设更重要的是建立起对大数据体系全局性的理解。这套理解才是毕业之后最有用的东西。