尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Hadoop+Spark线上教育平台大数据分析系统:爬虫采集、离线计算与Django看板全链路

发布时间:2026/9/19 11:20:04

资讯中心
01
ARTICLE

Hadoop+Spark线上教育平台大数据分析系统:爬虫采集、离线计算与Django看板全链路

Hadoop+Spark线上教育平台大数据分析系统:爬虫采集、离线计算与Django看板全链路
简介这份毕业设计论文文档面向计算机相关专业的本科毕业生围绕《Hadoop爬虫Spark线上教育平台大数据分析系统》展开适合需要完成大数据方向毕设、参考完整论文结构与技术方案的学生。资源为单个docx文件压缩包约6.25MB内容涵盖绪论、开发技术、需求分析、概要设计、系统实现与系统测试等完整章节技术栈涉及Python、MySQL、Django及大数据处理框架。论文详细阐述了爬虫数据采集、Hadoop存储、Spark分析以及可视化看板展示的实现思路并配有功能模块设计、数据库设计与流程图说明。已有100人学习下载可作为选题参考、论文框架模板与技术实现思路的借鉴帮助读者快速理清线上教育平台大数据分析系统的开发脉络与写作要点。1. 从一份 docx 说起这套线上教育平台大数据分析系统到底交付了什么很多同学拿到《Hadoop爬虫Spark线上教育平台大数据分析系统.docx》这份毕业设计时第一反应是文档里怎么只有 Django 和 MySQL。翻完目录你会发现论文正文写的是 Python3.6.4 Django3.2.12 MySQL 的 Web 管理端而标题里却挂着 Hadoop、爬虫、Spark 三个大数据关键词。这不是矛盾而是本科毕设里非常典型的一种结构Web 端负责展示和后台管理大数据组件负责离线链路的数据采集、清洗与指标计算两者通过 MySQL 或 Hive 结果表对接。换句话说Django 那部分是看得见的看板HadoopSpark 那部分是看不见的算力。这套系统要解决的问题很具体把线上教育平台里散落的调剂信息、访问记录、阅读量、地区分布这些数据从爬取、落库、聚合到可视化一条链路跑通。适合正在做同类毕设的本科生也适合想快速搭一套爬虫离线分析Web 看板最小闭环的初中级工程师。下面按数据怎么来、怎么存、怎么算、怎么展示、怎么排错的顺序拆开讲。2. 爬虫采集与 Hadoop 落地的衔接设计2.1 为什么毕设里爬虫和 Hadoop 要分开写论文里调剂信息表有来源、学校名、标题、发布时间、阅读量、分类、内容七个业务字段这些字段的原始形态是网页。常见做法是用 requests BeautifulSoup 或 Scrapy 抓取先落到本地 CSV/JSON再用 HDFS 命令上传而不是让爬虫直接写 HDFS。原因有两个一是爬虫进程和 Hadoop 集群往往不在同一台机器直接调 HDFS API 会引入额外的 Kerberos 或网络配置成本二是本地文件便于断点续爬和去重出问题能直接看原始数据。2.2 采集脚本与字段对齐下面这段是毕设场景下最常用的采集骨架字段名刻意和论文表 4-2 的qh73g_tiaojixinxi对齐方便后续直接 load 进 Hive 外部表。# crawl_tiaoji.py import requests from bs4 import BeautifulSoup import csv, time, hashlib HEADERS {User-Agent: Mozilla/5.0 (compatible; EduSpider/1.0)} FIELDS [laiyuan, xuexiaoming, biaoti, fabushijian, yueduliang, fenlei, detail] def parse(url): r requests.get(url, headersHEADERS, timeout10) r.encoding r.apparent_encoding # 中文站点常见乱码先探测编码 soup BeautifulSoup(r.text, html.parser) return { laiyuan: 某教育信息网, xuexiaoming: soup.select_one(.school).get_text(stripTrue), biaoti: soup.select_one(h1).get_text(stripTrue), fabushijian: soup.select_one(.time).get_text(stripTrue), yueduliang: soup.select_one(.views).get_text(stripTrue), fenlei: soup.select_one(.cate).get_text(stripTrue), detail: soup.select_one(.content).get_text(stripTrue), } def save(rows, pathtiaoji.csv): with open(path, a, newline, encodingutf-8-sig) as f: w csv.DictWriter(f, fieldnamesFIELDS) if f.tell() 0: w.writeheader() w.writerows(rows) if __name__ __main__: buf [] for page in range(1, 51): # 分页抓取50 页足够毕设数据量 url fhttps://example-edu.com/list?p{page} try: buf.append(parse(url)) except Exception as e: print(skip, url, e) # 单页失败不中断整体任务 if len(buf) 20: save(buf); buf.clear() time.sleep(1.5) # 控制频率避免被限流 save(buf)逻辑上分三层parse只负责把一页 HTML 映射成字典字段名和数据库列名一致save用追加模式写 CSVutf-8-sig是为了 Excel 打开不乱码主循环里每 20 条落一次盘配合time.sleep降低请求频率。参数上timeout10防止单请求挂死range(1,51)是抓取页数实际按目标站点分页结构调整。yueduliang抓下来是字符串后面进 Hive 时要cast成 int这点在论文表 4-2 里也写成了 varchar属于典型的历史遗留清洗阶段必须处理。2.3 上传 HDFS 与建外部表CSV 攒够之后用命令行推到 HDFS再建 Hive 外部表指向该目录这样删表不删数据重跑方便。# 本地文件推到 HDFS目录按日期分区 hdfs dfs -mkdir -p /edu/ods/tiaoji/dt20240501 hdfs dfs -put tiaoji.csv /edu/ods/tiaoji/dt20240501/ # 进入 hive 建外部表 hive -e CREATE EXTERNAL TABLE IF NOT EXISTS ods_tiaoji ( laiyuan STRING, xuexiaoming STRING, biaoti STRING, fabushijian STRING, yueduliang STRING, fenlei STRING, detail STRING ) ROW FORMAT DELIMITED FIELDS TERMINATED BY , STORED AS TEXTFILE LOCATION /edu/ods/tiaoji/dt20240501; EXTERNAL关键字保证 drop 表时数据仍在 HDFSFIELDS TERMINATED BY ,要和 CSV 分隔符一致LOCATION指向具体分区目录。常见坑是 CSV 里detail字段含逗号或换行导致列错位稳妥做法是采集时把内容里的逗号替换成中文逗号或改用\t分隔。提示HDFS 上传前先hdfs dfs -ls确认目录不存在同名文件重复 put 会产生tiaoji.csv.1这类副本Hive 查询时会被当成额外数据行。3. Spark SQL 做阅读量与地区访问的指标计算3.1 从 ODS 到 DWD 的清洗动作原始表里yueduliang是字符串fabushijian格式不统一直接聚合会出错。用 Spark SQL 建一张清洗后的 DWD 表把阅读量转 int、时间规整成标准格式同时过滤掉标题为空的行。# etl_tiaoji.py from pyspark.sql import SparkSession from pyspark.sql.functions import col, to_date, regexp_replace spark SparkSession.builder \ .appName(edu_tiaoji_etl) \ .enableHiveSupport() \ .getOrCreate() df spark.sql(SELECT * FROM ods_tiaoji) dwd df.select( col(laiyuan), col(xuexiaoming), col(biaoti), to_date(regexp_replace(col(fabushijian), 年|月, -).substr(1, 10)).alias(fabu_date), col(yueduliang).cast(int).alias(yueduliang), col(fenlei), col(detail) ).filter(col(biaoti).isNotNull() (col(yueduliang) 0)) dwd.write.mode(overwrite).saveAsTable(dwd_tiaoji)regexp_replace把2024年5月1日这类中文日期替换成2024-5-1再substr截前 10 位交给to_datecast(int)处理阅读量filter同时过滤空标题和异常阅读量。mode(overwrite)让脚本可重复执行每次全量重算毕设数据量下完全够用。3.2 阅读量 TOP10 与地区访问统计论文里看板要展示调剂信息阅读量 TOP10和地区访问量统计对应两条聚合 SQL。-- 阅读量 TOP10 SELECT biaoti, xuexiaoming, yueduliang FROM dwd_tiaoji ORDER BY yueduliang DESC LIMIT 10; -- 地区访问量统计访问信息表 SELECT fangwendiqu, SUM(fangwenliang) AS total_views, COUNT(DISTINCT fangwenbianhao) AS uv FROM ods_fangwen GROUP BY fangwendiqu ORDER BY total_views DESC;第一条按阅读量倒序取前 10直接喂给前端 ECharts 柱状图第二条按地区分组SUM算总访问量、COUNT(DISTINCT)算独立访问编号数对应论文表 4-3 的fangwenliang和fangwenbianhao两个字段。结果表建议写成ads_tiaoji_top10和ads_fangwen_diquDjango 端只读这两张结果表不碰明细查询压力小。3.3 关键参数与常见误用参数/写法作用误用后果enableHiveSupport()让 Spark 读写 Hive 表不加则saveAsTable写到默认 warehouseDjango 读不到mode(overwrite)全量覆盖结果表用append会累积重复数据看板数字翻倍cast(int)阅读量转数值不转则ORDER BY按字符串排9会排在10前面COUNT(DISTINCT)去重计数用COUNT会把同一访问编号多次计入 UV注意Spark 本地模式跑enableHiveSupport需要把hive-site.xml放到SPARK_HOME/conf否则会报找不到 metastore。毕设环境用伪分布式时这一步最容易卡住。4. Django 看板对接 Spark 结果表与排错4.1 用 ORM 读结果表而不是直连 HiveDjango 的 ORM 只认 MySQL所以 Spark 算完的结果要落到 MySQL 结果表Django 再通过 model 读取。论文表 4-6 的用户表、表 4-7 的调剂信息表都是这个思路。下面是一个只读结果表的 model 和视图。# models.py from django.db import models class AdsTiaojiTop10(models.Model): biaoti models.CharField(max_length200) xuexiaoming models.CharField(max_length200) yueduliang models.IntegerField() class Meta: db_table ads_tiaoji_top10 managed False # 表由 Spark 写入Django 不建表不迁移 # views.py from django.http import JsonResponse from .models import AdsTiaojiTop10 def top10_api(request): rows AdsTiaojiTop10.objects.order_by(-yueduliang)[:10] return JsonResponse( {data: [{title: r.biaoti, school: r.xuexiaoming, views: r.yueduliang} for r in rows]} )managed False是关键告诉 Django 这张表不归迁移系统管避免migrate时把 Spark 写的表结构改掉。视图返回 JSON前端 ECharts 直接消费。Spark 写 MySQL 用 JDBCdwd.write.format(jdbc) \ .option(url, jdbc:mysql://localhost:3306/edu_analysis?useSSLfalse) \ .option(dbtable, ads_tiaoji_top10) \ .option(user, root).option(password, ***) \ .option(truncate, true) \ .mode(overwrite).save()truncatetrue配合overwrite会先清空再写比 drop 重建表更安全不会丢索引。4.2 链路排错的三个检查点数据从爬虫到看板任何一环断了看板就是空的。按顺序查第一HDFS 上hdfs dfs -cat /edu/ods/tiaoji/dt20240501/tiaoji.csv | head看原始数据有没有第二SELECT COUNT(*) FROM dwd_tiaoji看清洗后行数是否骤减骤减通常是日期正则没匹配上导致to_date返回 null 被过滤第三MySQL 里SELECT COUNT(*) FROM ads_tiaoji_top10看结果表有没有数据没有就是 Spark JDBC 写入失败检查驱动 jar 是否在--jars里。提示Django 的managedFalse表在makemigrations时不会生成迁移文件如果发现表不存在先确认 Spark 任务是否成功执行过而不是去跑 migrate。5. 进阶技巧用分区裁剪和缓存把重复查询压下去毕设数据量不大但看板每次刷新都全表扫dwd_tiaoji仍然浪费。两个立竿见影的优化一是给 ODS 表按dt分区查询时带WHERE dt20240501触发分区裁剪Spark 只读对应目录二是对反复用的dwd_tiaoji做cache()多个聚合 SQL 共享同一份内存数据。dwd spark.sql(SELECT * FROM dwd_tiaoji WHERE dt20240501) dwd.cache() # 后续多次聚合复用 dwd.createOrReplaceTempView(tmp_dwd) top10 spark.sql(SELECT biaoti, yueduliang FROM tmp_dwd ORDER BY yueduliang DESC LIMIT 10) diqu spark.sql(SELECT fenlei, SUM(yueduliang) v FROM tmp_dwd GROUP BY fenlei)cache()把 DataFrame 物化到内存createOrReplaceTempView让后续 SQL 直接引用避免重复读 HDFS。数据量超过内存时改用persist(StorageLevel.DISK_ONLY)。另一个技巧是 Spark SQL 的日期加减做近 7 天阅读量趋势时用date_sub(current_date(), 7)生成起始日期比在 Python 里算好再传参更省事SELECT fabu_date, SUM(yueduliang) AS views FROM dwd_tiaoji WHERE fabu_date date_sub(current_date(), 7) GROUP BY fabu_date ORDER BY fabu_date;date_sub返回日期类型和fabu_date直接比较即可不用手动格式化。验证优化是否生效看 Spark UI 的 Stage 详情里 Input Size 是否下降以及 Django 接口的响应时间是否从秒级降到百毫秒级。如果cache()后内存报 OOM把spark.executor.memory调大或改磁盘存储别硬扛。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。