ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Django的B站青少年模式数据分析系统实战解析

基于Django的B站青少年模式数据分析系统实战解析 毕业设计年年有人选数据分析类题目但真正能落地、能答辩、能让评委眼前一亮的其实不多。大部分同学做着做着就变成了套一个框架放两张图表自己都不知道数据怎么来的、分析逻辑是什么。今天我想拆解一个我实际带过、也亲自复现过的案例基于Django的Bilibili青少年模式使用情况的数据分析系统。这个题目既有社会关注度又有真实的数据获取渠道还覆盖了爬虫、数据清洗、数据建模、可视化展示这一整条技术链路做出来之后无论放到简历里还是拿去答辩都拿得出手。如果你是正在选题的计算机专业学生或者在纠结Django项目到底能做到什么深度这篇文章会给你一套完全可以照着做的完整方案。我尽量把每一步的设计理由和技术细节都讲清楚包括哪些地方容易踩坑、哪些数据可以现场演示撑场面全部是实操过的经验。1. 项目到底做什么需求拆解与选题逻辑1.1 为什么是B站青少年模式先把需求本质讲清楚。这个系统表面上是数据分析系统实际上需要用数据回答几个具体问题B站青少年模式下用户在看什么、什么时间段使用最多、哪些内容类型最受欢迎、不同分区的内容分布是否合理。之所以选Bilibili有几个非常现实的原因。第一B站的内容品类足够丰富分区维度多动画、游戏、知识、影视、音乐、生活等分析出来有层次感。第二B站提供了一套相对稳定的网页接口数据采集不需要逆向APP客户端对毕设来说务实可行。第三青少年模式本身就是热点话题评委一看题目就懂你做的是什么东西不需要额外解释背景。这个题目还有一个隐性加分项它天然和数据合规、用户保护挂钩。你可以很自然地在论文里引出未成年人网络内容治理这个背景让课题具备一定的社会意义这在毕业设计的评分标准里属于加分方向。1.2 为什么用Django而不是Flask或SpringBoot很多人在选题时会纠结框架我直接说结论这个题目用Django是性价比最高的选择。自带ORM和数据迁移机制数据分析系统的核心是数据建模Django的ORM允许你用Python类定义表结构执行迁移自动改数据库比手写SQL省力得多。自带Admin后台毕业设计需要展示系统管理功能Django Admin不用写任何前端代码注册一下模型就能实现对数据的增删改查这在演示阶段非常救命。自带认证和会话管理如果你的系统需要区分普通用户和管理员Django的auth模块可以直接用不用自己造轮子。模板系统方便快速出页面数据分析结果需要以页面形式展示Django模板配合Bootstrap、ECharts可以在很短时间内做出完整的Web界面。Flask虽然轻量但所有组件都要自己拼对毕设来说工作量反而更大。SpringBoot当然也能做但Java生态对数据分析的支持不如Python顺滑而且你最后做可视化分析必然要用pandas一类的库Django直接复用Python生态代码量最少。1.3 系统整体架构与数据流整个系统的架构并不复杂我拆成四层来看数据采集层通过requests请求B站公开接口获取视频信息、评论区文本、用户行为数据定时任务触发抓取。数据存储层Django ORM管理MySQL数据库核心表包括分区表、视频表、评论表、使用时长记录表、内容特征表。分析运算层读取数据库数据使用pandas做聚合计算、基于词典的情感倾向分析、时段热度统计等结果存入统计结果表。可视化展示层Django视图从数据库取统计结果渲染到ECharts图表和页面模板中实现关键词云、趋势折线、分区占比饼图等。注意这个项目里最容易被忽略的是数据流闭环这四个字。很多毕设只是把爬到的数据原样展示没有分析加工环节导师一眼就能看出来。真正的分析系统必须是原始数据→清洗→聚合→特征提取→可视化的完整链路。2. 核心技术点拆解从爬虫到可视化2.1 数据从哪来B站数据通道与采集策略这里有一个很多同学一开始就会搞错的地方Bilibili青少年模式下的内容数据本身并没有一个公开的独立入口。实际操作中我们拿的是B站普通内容的公开接口然后按青少年模式的内容过滤策略进行模拟筛选。这里的核心思路是用普通内容数据标注合规属性再结合用户使用行为数据来做综合分析。实际可行的数据来源主要有这几个分区视频流接口api.bilibili.com/x/web-interface/wbi/ranking/v2这类排行接口可以按分区获取视频基本信息播放量、点赞、投币、分享、标题、UP主。视频详情接口获取单个视频的标签、发布时间、时长、简介。评论接口api.bilibili.com/x/v2/reply用于采集视频下评论内容后续做文本分析。用户行为数据这个B站没有公开接口需要靠系统自己设计。比如在系统中注册青少年模式模拟用户记录其浏览、搜索、停留时长这部分数据就是你自己系统的独有数据。这里有个关键的设计思路系统的创新点不在于爬了多少条B站数据而在于把外部内容数据与系统内部行为数据做关联分析。比如你可以分析某类标签视频在青少年模式下的播放占比、哪些关键词在青少年内容的评论区出现频率最高。这种内外结合的方式既解决了数据来源问题又让系统有独立价值。采集策略上我强烈建议不要用Scrapy直接用requests配合time.sleep()做轻量采集就够了。原因很简单毕设要展示的是你能写爬虫而不是你能写多大规模的分布式采集系统Scrapy会显著增加代码量和调试成本。控制请求频率在每秒1次左右每采集完一个分区休息2到3秒基本不会触发风控。2.2 数据模型怎么设计五张核心表Django的数据模型设计是这个项目的灵魂环节。我实际采用过一套五张核心表的结构基本能满足所有分析需求表名主要字段作用Categoryid、name、code视频分区字典表Videoid、bid、title、play_count、like_count、coin_count、share_count、duration、publish_time、category_id、is_suitable视频内容数据Commentid、video_id、user_name、content、like_count、create_time评论文本数据UserBehaviorid、behavior_type、target_video_id、duration_seconds、create_time模拟青少年用户行为AnalysisResultid、result_type、dimension、content_json、create_time分析结果存储Video表里特别注意is_suitable这个字段标记该视频是否符合青少年模式的内容投放条件。判断依据可以设定为无风险标签 非敏感分区 内容评分达标具体逻辑写在爬虫过滤函数里。这个字段是后面所有筛选分析的前提。AnalysisResult表的作用很多人会忽略但它特别重要。它把分析计算的结果缓存成JSON格式存起来这样页面每次打开就不需要重新跑pandas计算了。毕设答辩现场演示时如果图表加载要几秒甚至报错体验会非常差。预计算缓存存储是保证演示流畅的关键。2.3 分析维度用数据回答什么系统不能只有图表每个图表背后必须对应一个业务问题。我设计的分析维度有几个层次内容分布维度各分区在青少年模式下的视频数量占比、播放量占比回答青少年模式下的内容生态到底偏向什么。时段活跃维度按小时聚合用户行为数据画出一天内的使用热度曲线回答青少年通常在什么时间段刷B站。内容互动维度对比分析适龄视频与全站视频的完播率、点赞率回答适龄内容是否仅是被动展示而不是真正受欢迎。文本语义维度对评论内容做分词、词频统计、情感倾向分析回答用户对青少年内容的反馈是正面的还是负面的。这些维度每一个都可以在系统里对应一个独立页面展示一张或一组图表。到论文里每个维度就是一个小节分析结论就是你的研究成果。这样一来课题的数据分析属性就非常扎实了。3. 实操复现从零搭建这套系统3.1 环境准备与Django项目初始化我建议直接用Python 3.10以上版本Django用4.2 LTS版本。创建项目时目录结构按模块拆分会清晰很多# 创建项目 django-admin startproject bili_da # 进入项目目录创建两个核心应用 cd bili_da python manage.py startapp collector python manage.py startapp analyzer python manage.py startapp dashboard三个app各有分工collector负责采集数据和定义数据模型analyzer负责pandas分析和定时任务dashboard负责视图和页面渲染。在settings.py里需要做几个关键配置# 时区必须用 Asia/Shanghai不然采集到的时间数据在入库后会出现8小时偏差 TIME_ZONE Asia/Shanghai USE_TZ True # 数据库按需选择本地开发建议先用MySQL答辩部署可以用SQLite省事 DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: bili_analysis, USER: root, PASSWORD: your_password, HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, } } } # 注册三个app INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, collector, analyzer, dashboard, ]注意MySQL的charset必须指定为utf8mb4否则后续评论数据一遇到emoji就会整条写入失败。这个问题我踩过一次大坑当时评论区一个狗头表情导致爬虫任务中断排查了一下午。配置好之后在collector/models.py里定义上面那张五表结构然后执行makemigrations和migrate初始化数据库。这一步完成后先真实跑一次采集确认每条表的入库数据正确再去做页面。3.2 爬虫模块定时采集与反爬处理采集模块我用的是requests配合Django的命令行扩展来做的。在collector里创建management/commands目录写一个crawl_bili.py自定义命令from django.core.management.base import BaseCommand from collector.services import BiliCrawler class Command(BaseCommand): help 抓取B站视频和评论数据 def add_arguments(self, parser): parser.add_argument(--pages, typeint, default5, help采集页数) def handle(self, *args, **options): crawler BiliCrawler() crawler.crawl_ranking(pagesoptions[pages]) self.stdout.write(self.style.SUCCESS(采集完成))核心爬虫逻辑中请求头、随机延时、Cookie处理是三个必须要做对的地方import time import random import requests class BiliCrawler: def __init__(self): self.session requests.Session() # 请求头带上浏览器标识不要赤裸裸暴露爬虫身份 self.session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36, Referer: https://www.bilibili.com/, Accept: application/json, text/plain, */*, }) def fetch_json(self, url, paramsNone): # 随机延时对B站接口友好一些 time.sleep(random.uniform(1, 3)) resp self.session.get(url, paramsparams, timeout10) resp.raise_for_status() data resp.json() if data.get(code) ! 0: self.log_error(url, data) return None return data[data]这里有一个很多人不知道的小细节B站的接口参数中有些需要签名wbi机制很多同学的写法直接硬编码参数会导致请求返回-403。最简单的处理方式是先用浏览器开发者工具复制请求头的完整参数列表把X-Bili-Device-ID这类需要的前置条件一起放进请求头。如果只是为了毕设采用/x/web-interface/ranking/v2这个老接口参数相对简单不需要签名也能正常工作。采集完成后数据不能直接入库。要做一轮清洗去重按bid判断视频是否已存在、过滤去掉明显不适合青少年模式的分区、补全时长小于1分钟的视频直接标记为低质量内容。清洗逻辑我放在collector/services/cleaner.py里每一层过滤器单独一个函数方便论文里展开写。3.3 分析计算Django命令行脚本与pandas分析模块不建议放在页面请求里去跑因为pandas的聚合计算虽然对这个数据量不慢但每次刷新都重算一遍属于浪费资源。我采用的方式是写一个分析脚本用Django命令触发跑完后结果写入AnalysisResult表。举个时段活跃分析的例子import json import pandas as pd from django.core.management.base import BaseCommand from collector.models import UserBehavior from analyzer.models import AnalysisResult class Command(BaseCommand): def handle(self, *args, **options): # 从数据库读取行为数据 behaviors UserBehavior.objects.all().values( create_time, behavior_type ) df pd.DataFrame(list(behaviors)) if df.empty: self.stdout.write(暂无数据) return # 提取小时维度 df[hour] pd.to_datetime(df[create_time]).dt.hour hour_stats df.groupby(hour).size().reset_index(namecount) # 转成前端ECharts需要的格式 result_data { hours: hour_stats[hour].astype(str).tolist(), counts: hour_stats[count].tolist(), } # 缓存到AnalysisResult表 AnalysisResult.objects.update_or_create( result_typehour_activity, defaults{content_json: json.dumps(result_data, ensure_asciiFalse)} ) self.stdout.write(self.style.SUCCESS(时段分析完成))这个模式你可以复制到所有分析维度上读取数据 → DataFrame处理 → 结果JSON化 → 缓存入库。代码非常套路化但稳定性高答辩现场演示时页面打开永远是秒出图表不会因为现场网络问题导致统计中断。文本情感分析这个维度稍微复杂一些但也不用上机器学习。一个实用做法是维护一个情感词典把积极词和消极词作为两个Python列表对每条评论做分词计数最后统计积极占比。如果要更专业一点可以用jieba做分词再匹配词典import jieba positive_words [好看, 喜欢, 棒, 有意思, 支持, 优秀] negative_words [无聊, 差, 失望, 不好看, 低俗, 反感] def analyze_sentiment(text): words jieba.lcut(text) positive_hit sum(1 for w in words if w in positive_words) negative_hit sum(1 for w in words if w in negative_words) if positive_hit negative_hit: return positive elif negative_hit positive_hit: return negative return neutral这个方法解释起来简单PPT上画个流程图就能讲明白原理答辩时不需要把评委绕进机器学习黑箱里。3.4 可视化展示ECharts与页面渲染页面展示部分我用的是Django模板 Bootstrap 5 ECharts 5的方案。每个分析维度对应一个页面视图函数从AnalysisResult里读JSON再传给模板。视图层代码保持简洁from django.shortcuts import render from analyzer.models import AnalysisResult def hour_activity(request): result AnalysisResult.objects.filter( result_typehour_activity ).order_by(-create_time).first() context { chart_data: result.content_json if result else {}, } return render(request, dashboard/hour_activity.html, context)模板里通过json_script过滤器把数据安全传到JavaScriptdiv idhour-chart styleheight: 400px;/div {{ chart_data|json_script:chart-data }} script const raw document.getElementById(chart-data).textContent; const data JSON.parse(raw); const chart echarts.init(document.getElementById(hour-chart)); chart.setOption({ title: { text: 青少年模式使用时段分布 }, tooltip: { trigger: axis }, xAxis: { type: category, data: data.hours }, yAxis: { type: value }, series: [{ name: 使用次数, type: line, smooth: true, data: data.counts, areaStyle: { opacity: 0.2 } }] }); /script类似地分区占比用饼图、关键词热度用词云或柱状图、互动率对比用横向柱状图。整个dashboard app里可以放六到八个页面系统首页、内容分布、时段分析、互动分析、评论文本分析、数据明细、后台管理。首页很重要它承担数据驾驶舱的定位。放四到六个统计卡片总视频数、总评论数、适龄内容占比、平均播放量再放两张核心大图分区分布、时段趋势。演示的时候打开首页展示全景然后逐页深入节奏非常舒服。4. 实战中的高频问题与排查实录4.1 B站接口返回空数据或代码为-403这个问题出现的频率极高。如果你直接在某云服务器上跑爬虫大概率会遇到接口返回验证码或-412状态码。处理方式分几步排查确认请求头完整User-Agent、Referer不能省确认Cookie有效性直接用浏览器登录B站后复制自己的Cookie放到请求头里请求频率是否过高调整到每2秒一次避免短时间高频请求如果同时采集多个分区串行执行不要并发实测建议本地开发如果不涉及反爬问题尽量保存一个已登录Cookie到本地文件。这是整个毕设项目时间最容易被拖垮的环节不要在最开始就陷入调反爬的泥潭先保证数据能跑通流程。4.2 采集到几千条数据后图表依然显得单薄很多同学跑完数据一看图表有是有但看起来像半成品不够数据分析系统的感觉。这里我给你一个完全合规的思路在论文和演示中区分真实采集数据和模拟行为数据。B站真实内容数据视频、评论是实打实采集的这没问题。而用户行为数据浏览记录、停留时长、操作路径B站不开放所以系统内部随机生成一批符合正态分布的模拟用户行为记录并把这个模拟过程在论文里明确说明。演示时页面展示的时段分析、情境分析基于这批数据同时备注系统内置模拟器生成示例行为数据。研究生和本科毕设都接受这种方式关键是表结构、分析逻辑、可视化链路是真实完整的。4.3 MySQL存储emoji报错错信息一般是Incorrect string value: \xF0\x9F\x98...。原因很简单MySQL的utf8字符集实际上最多只支持3字节字符而emoji是4字节。解决办法就是建库时指定utf8mb4CREATE DATABASE bili_analysis DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;同时Django这边数据库连接的OPTIONS里也加上charset: utf8mb4两边保持一致。如果已经建了库可以用ALTER DATABASE和ALTER TABLE调整但最省事的方法是一开始就建正确。4.4 Django时区导致的时间偏差这个坑特别隐蔽。Django默认USE_TZTrue时存进数据库的datetime是按UTC时间存的读取时会自动转换但你的爬虫在本地用的是datetime.now()写入后与页面上显示的时间可能差8个小时。解决方案是统一时间基准采集数据时使用django.utils.timezone.now()获取当前时间而不是Python原生的datetime.now()。另外TIME_ZONE设置为Asia/Shanghai。这样数据库里存的是UTC读出来时会自动转成北京时间前后台显示一致。4.5 演示环境无法联网图表加载不出来现场答辩经常遇到Wi-Fi不稳定的情况ECharts如果是通过CDN引用的图表就会白屏。提前把ECharts的JS文件下载到本地static目录里全部依赖本地化。除ECharts外Bootstrap、jQuery这些也都下载到本地。演示时断网也不受影响这个细节很多同学都没准备等真遇到问题就晚了。5. 毕业设计答辩与文档的加分点5.1 论文结构怎么安排论文一般八到十章核心框架我给一个实用模板第一章绪论写背景和意义重点讲未成年人网络保护政策与青少年模式发展趋势。第二章相关技术介绍写Django框架、B站开放接口、pandas分析、ECharts可视化。第三章需求分析把系统分为四个角色用例普通用户、系统管理员、数据采集模块、分析模块。第四章系统设计画整体架构图、功能模块图、数据库ER图这章是导师最爱看的部分。第五章系统实现按功能模块分节每节放关键代码运行截图。第六章系统测试写功能测试用例表测试结果。第七章总结与展望。5.2 演示Demo的节奏设计答辩演示控制在8分钟以内顺序很关键首页数据驾驶舱展示30秒让评委看清楚系统在做什么数据采集过程演示1分钟打开命令行运行爬虫命令显示采集日志内容分布与时序分析页1分30秒点开图表展示交互效果评论文本分析页1分钟展示情感分析结果和关键词图表后台管理页面1分钟通过Django Admin修改一条数据在前端看到联动总结分析结论1分钟直接朗读每个图表对应的研究结论这套流程的核心逻辑是从数据到结论。很多同学演示时只会说这是柱状图、这是饼图评委就会追问然后呢结论是什么所以在每个页面上都提前写好分析结论文字比如12时至21时为使用高峰时段占全天活跃度的68.4%课余时间特征明显一句话就让图表有了研究意义。6. 复盘一套可复用的毕设开发流程做完整套系统后我最大的感受是毕业设计最忌讳收藏即完成。这个基于Django的Bilibili青少年模式数据分析系统之所以能成为不错的毕设案例不是因为技术有多深而是整个链路是完整且自洽的——数据来源真实、分析逻辑成立、可视化表达清晰、文档有料可写。拿到类似题目时可以套用我上面的流程先分析选题的背景价值和数据可行性再设计数据模型打通采集清洗存储然后做分析计算最后呈现可视化。每一步完成一个可演示的里程碑而不是到了最后一周才堆代码。如果你现在正在动手写这个系统建议第一周用所有精力先跑通最核心的一页数据分析页面后面再慢慢丰富页面。先治好能跑通这个焦虑做起来思路自然会越来越清楚。
返回列表