☰
Python+MySQL舆情分析系统:DNN与BERT双模型实战与二次开发
2026/10/19 2:21:54 网站建设 项目流程

简介:这份资源是一篇完整的本科毕业论文文档,主题为基于Python与MySQL的网络舆情分析系统的设计与实现,面向计算机相关专业学生、毕业设计选题者以及需要搭建舆情监测功能的开发者。压缩包内共1个docx文件,约1.73MB,内容涵盖论文封面、独创性声明、中英文摘要、引言背景、系统需求分析、功能模块设计与实现等完整章节,可直接作为论文写作模板或项目参考。系统以Python为开发语言、MySQL为数据存储介质,围绕言论分析、言论管理、用户管理三大核心功能展开,重点解决网络管理部门以城市或地区为关键词快速检索、分析舆情与负面评论的需求,同时兼顾网民隐私与言论自由。论文结构规范、逻辑清晰,配有系统设计思路与实现说明,适合用于理解舆情分析系统的整体架构、数据库设计方法以及Python Web开发的落地流程。目前已有1262人学习下载,可作为毕业设计选题、课程设计或技术学习的实用参考资料。

1. 从一份毕设源码说起:Python 舆情分析系统到底能跑出什么结果

有个做后端的朋友接了个私活,对方丢过来一份压缩包,说“这是某高校的毕设,你帮我看看能不能改成能用的东西”。他解压一看,Python + MySQL,功能列表写得挺全:文本分析、文本管理、用户管理、对比分析。但代码跑起来之后,他发现真正有意思的不是界面,而是后台那套“输入一段话,系统告诉你这段话是正面还是负面”的逻辑。这套逻辑放在今天,就是很多公司做舆情监控、评论审核、品牌口碑分析的最小可用原型。

这份资源就是围绕这个场景展开的:一个基于 Python 和 MySQL 的网络舆情分析系统,带源码、数据库脚本和配套论文。它适合两类人——一类是正在找毕设选题、想拿一套能跑通的代码做二次开发的学生;另一类是刚接触文本分类、想找一个完整项目练手的开发者。系统本身不复杂,但麻雀虽小,从爬取、存储、分析到可视化展示的链路是完整的,拿来当“文本分析项目脚手架”很合适。

2. 技术选型与整体架构:为什么是 Python + MySQL + B/S

2.1 后端为什么选 Python 而不是 Java 或 PHP

这个项目在论文里明确写了后台语言用 Python,数据库用 MySQL,前端是 HTML5 + CSS + JavaScript,整体走 B/S 架构。很多人看到“舆情分析”四个字,第一反应是上 Elasticsearch 或者 Hadoop,但这个项目的定位是毕设级别,数据量不大,单机 MySQL 完全扛得住。Python 在这里的优势不是性能,而是开发效率——文本处理相关的库多,写起来快,调试也方便。

从代码结构看,后端大概率是 Flask 或 Django 这类轻量框架。论文里提到“Python 可以与 HTML 有效结合”,并且用了 Sublime Text 作为编辑器,没有提到复杂的工程化工具,说明项目走的是“单文件入口 + 模板渲染”的路线。这种结构对新手友好,不需要理解太多框架概念就能改代码。

提示:如果你打算把这个项目改成前后端分离,后端接口层不用大动,把模板渲染换成 JSON 返回即可,前端换成 Vue 或 React 成本也不高。

2.2 B/S 架构带来的部署便利性

论文里专门用了一节讲 B/S 和 C/S 的区别,结论是 B/S 不需要安装客户端,浏览器打开就能用。这个选择对舆情系统来说是对的——使用者是管理人员,可能在不同电脑上登录,如果每个终端都要装客户端,维护成本太高。B/S 架构下,你只需要把 Python 服务跑在一台机器上,其他人通过浏览器访问 IP 和端口就行。

实际部署时,常见做法是用 Nginx 做反向代理,Python 服务用 Gunicorn 或 uWSGI 托管。毕设项目可能直接python app.py就跑起来了,但如果你要放到服务器上给多人用,建议加上进程管理工具,不然终端一关服务就断了。

2.3 数据库表设计的核心思路

论文里列了四张核心表:用户信息表、文本分类及文本信息表、文本管理信息表、站内新闻表。这个设计不算复杂,但有几个点值得注意。

用户信息表以用户 ID 为主键,包含用户名、密码、注册时间。这里密码大概率是明文存储的,毕设项目常见做法。如果你要二次开发,第一件事就是把密码改成哈希存储,用werkzeug.security或者bcrypt都行,改动量不大。

文本分类及文本信息表拆成了两张表,一张管分类,一张管具体文本。这种设计的好处是分类可以复用,比如“负面”“正面”“中性”三个分类只存一次,文本表里用外键关联。文本管理信息表里有一个“管理状态”字段,用来标记“未处理”“已处理”,这个字段在实际业务里很有用,相当于工单状态。

站内新闻表是给管理员发公告用的,和核心业务关系不大,但能让系统看起来更完整。

-- 用户信息表(简化版) CREATE TABLE user_info ( user_id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, phone VARCHAR(20), register_time DATETIME DEFAULT CURRENT_TIMESTAMP, role VARCHAR(20) DEFAULT 'user' -- user 或 admin ); -- 文本信息表 CREATE TABLE text_info ( text_id INT PRIMARY KEY AUTO_INCREMENT, content TEXT NOT NULL, category_id INT, analyze_result VARCHAR(20), -- positive / negative / neutral manage_status VARCHAR(20) DEFAULT '未处理', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (category_id) REFERENCES text_category(category_id) );

上面这段 SQL 是根据论文描述还原的建表语句。role字段用来区分普通用户和管理员,analyze_result存分析结果,manage_status存处理状态。实际项目中,你可能会再加一个source字段,记录文本是从哪个平台来的,方便后续做来源分析。

2.4 算法层:DNN 和 BERT 的双模型对比

论文里提到系统用了 DNN 和 BERT 两种算法,并且有一个“对比分析”模块,用柱状图和饼图展示两种算法的分析结果。这个设计思路是合理的——单一模型容易有偏差,双模型对比能看出哪个更准。

DNN 部分大概率是用 Keras 或 PyTorch 搭了一个几层的全连接网络,输入是文本的向量化表示(比如 TF-IDF 或 Word2Vec),输出是分类概率。BERT 部分则是加载预训练模型,做 fine-tune 或者直接推理。毕设环境下,BERT 可能用的是bert-base-chinese或者更小的chinese_roberta_wwm_ext。

实际跑的时候,DNN 训练速度快但准确率一般,BERT 准确率高但推理慢。对比分析模块的价值就在于让用户直观看到这个差异。如果你要优化,可以考虑用蒸馏后的 BERT(比如 TinyBERT)来平衡速度和准确率。

3. 从零跑起来:环境准备、数据库导入和启动步骤

3.1 开发环境与依赖安装

论文里写的开发环境是 i5 十代 + 8GB 内存 + 500G 固态,这个配置跑 BERT 推理会有点吃力,但跑 DNN 和轻量级 BERT 没问题。操作系统没写,但 Python 项目在 Windows 和 Linux 上都能跑,macOS 也行。

依赖方面,除了 Python 本身,你大概率需要装这些包:

# 基础 Web 框架(Flask 或 Django 二选一) pip install flask # 数据库连接 pip install pymysql # 数据处理 pip install pandas numpy # 机器学习 pip install scikit-learn # 深度学习(如果跑 BERT) pip install torch transformers # 可视化(前端图表可能用 ECharts,后端可能用 matplotlib) pip install matplotlib

具体版本号论文里没写,我一般会先pip install最新版,跑不通再降级。Python 版本建议 3.8 以上,BERT 相关的库对版本有一定要求。

注意:如果你没有 GPU,BERT 推理会非常慢。建议先用 DNN 跑通流程,再决定要不要上 BERT。或者用transformers的 pipeline 做小批量推理,不要一次性加载太多数据。

3.2 数据库创建与数据导入

拿到源码后,第一件事是找.sql文件。毕设项目通常会带一个database.sql或者init.sql,里面是建表语句和初始数据。操作步骤:

  1. 打开 Navicat 或命令行,连接到本地 MySQL。
  2. 新建一个数据库,名字看配置文件里写的什么,通常是opinion_analysis或yq_analysis。
  3. 执行 SQL 文件导入表结构和初始数据。
  4. 修改项目配置文件里的数据库连接信息,包括 host、port、user、password、database name。
# 常见的数据库配置写法(Flask + PyMySQL) import pymysql def get_db_connection(): return pymysql.connect( host='localhost', port=3306, user='root', password='your_password', # 改成你自己的 database='opinion_analysis', charset='utf8mb4' # 支持中文和 emoji )

这段代码是数据库连接的基础封装。charset='utf8mb4'很重要,舆情数据里经常有 emoji 和特殊符号,用utf8会报错。如果你用的是 Django,配置写在settings.py的DATABASES里,格式类似。

3.3 启动项目与常见报错处理

数据库配好之后,启动命令通常是python app.py或python manage.py runserver。启动后浏览器访问http://127.0.0.1:5000(Flask 默认端口)或http://127.0.0.1:8000(Django 默认端口)。

第一次跑大概率会遇到几个问题:

  • 模块找不到:ModuleNotFoundError: No module named 'xxx',缺什么装什么,注意有些包名和导入名不一样,比如sklearn对应scikit-learn。
  • 数据库连接失败:检查 MySQL 服务是否启动,用户名密码是否正确,数据库名是否匹配。
  • 端口被占用:换个端口,Flask 里改app.run(port=5001)。
  • BERT 模型下载慢:transformers默认从 HuggingFace 下载,国内网络可能超时。可以手动下载模型文件放到本地,然后指定路径加载。
# 手动指定本地 BERT 模型路径,避免下载超时 from transformers import BertTokenizer, BertForSequenceClassification model_path = './local_models/bert-base-chinese' # 提前下载好放这里 tokenizer = BertTokenizer.from_pretrained(model_path) model = BertForSequenceClassification.from_pretrained(model_path, num_labels=3)

这段代码展示了如何从本地加载 BERT 模型。num_labels=3对应三分类(正面、负面、中性)。如果你只有两类,改成 2 即可。提前下载模型可以用git lfs或者从镜像站获取,具体方式这里不展开。

3.4 首页与核心功能入口验证

项目跑起来后,先别急着测分析功能,按顺序验证:

  1. 首页是否能正常显示,导航栏有没有“文本分析”“文本管理”“个人信息”“用户管理”这些入口。
  2. 注册一个普通用户,登录后看能否进入文本分析页面。
  3. 在文本框里输入一段测试文本,比如“这个城市的环境越来越差了”,看系统返回什么结果。
  4. 进入文本管理页面,看刚才的分析记录有没有存进去。
  5. 用管理员账号登录(如果有初始管理员账号的话),看用户管理功能是否正常。

这一步的目的是确认“输入 → 分析 → 存储 → 展示”这条链路是通的。如果某一步断了,根据报错信息定位问题,通常比盲目改代码高效。

4. 核心模块拆解:文本分析、文本管理和用户权限的代码实现

4.1 文本分析模块:从输入到分类结果的完整链路

文本分析是这个系统最核心的功能。用户在文本框输入一段话,点击分析,系统返回分类结果。这个过程的代码逻辑大致分四步:接收输入、预处理、模型推理、返回结果。

# 文本分析核心逻辑(简化版) from flask import request, jsonify from transformers import pipeline # 加载分类 pipeline(实际项目中应该全局加载一次,不要每次请求都加载) classifier = pipeline( "text-classification", model="./local_models/bert-base-chinese", tokenizer="./local_models/bert-base-chinese" ) @app.route('/api/analyze', methods=['POST']) def analyze_text(): data = request.get_json() text = data.get('content', '').strip() if not text: return jsonify({'code': 400, 'msg': '文本不能为空'}) # 调用模型推理 result = classifier(text)[0] label = result['label'] # 例如 'positive' / 'negative' / 'neutral' score = result['score'] # 置信度 # 存入数据库 conn = get_db_connection() cursor = conn.cursor() cursor.execute( "INSERT INTO text_info (content, analyze_result, create_time) VALUES (%s, %s, NOW())", (text, label) ) conn.commit() cursor.close() conn.close() return jsonify({ 'code': 200, 'data': { 'label': label, 'score': round(score, 4), 'text': text } })

这段代码的关键点有三个。第一,pipeline加载模型比较耗时,实际项目中应该放在应用启动时全局加载,而不是每次请求都重新加载。第二,text.strip()去掉首尾空格,避免空字符串进入模型。第三,分析结果直接写库,这样文本管理页面才能查到记录。

参数说明:content是前端传来的 JSON 字段,label是模型输出的分类标签,score是置信度,范围 0 到 1。如果你用的是 DNN 而不是 BERT,把pipeline换成自己的模型推理代码即可,整体流程不变。

4.2 文本管理模块:分页查询与状态流转

文本管理页面需要展示所有分析过的文本,支持分页和状态筛选。这个模块的代码重点是 SQL 查询和前端表格渲染。

# 文本列表查询接口(带分页和状态筛选) @app.route('/api/text/list', methods=['GET']) def text_list(): page = int(request.args.get('page', 1)) page_size = int(request.args.get('page_size', 10)) status = request.args.get('status', '') # 未处理 / 已处理 / 空 offset = (page - 1) * page_size conn = get_db_connection() cursor = conn.cursor(pymysql.cursors.DictCursor) if status: cursor.execute( "SELECT * FROM text_info WHERE manage_status = %s ORDER BY create_time DESC LIMIT %s OFFSET %s", (status, page_size, offset) ) else: cursor.execute( "SELECT * FROM text_info ORDER BY create_time DESC LIMIT %s OFFSET %s", (page_size, offset) ) rows = cursor.fetchall() # 查总数用于分页控件 cursor.execute("SELECT COUNT(*) AS total FROM text_info") total = cursor.fetchone()['total'] cursor.close() conn.close() return jsonify({ 'code': 200, 'data': rows, 'total': total, 'page': page, 'page_size': page_size })

这段代码用LIMIT和OFFSET实现分页,ORDER BY create_time DESC让最新的记录排前面。DictCursor让查询结果以字典形式返回,方便直接转 JSON。状态筛选通过manage_status字段实现,前端传“未处理”就只返回未处理的记录。

实际业务中,文本管理页面通常还会有一个“标记为已处理”的按钮,点击后更新manage_status字段。这个操作对应的 SQL 是UPDATE text_info SET manage_status = '已处理' WHERE text_id = %s,逻辑很简单,这里不展开。

4.3 用户权限模块:普通用户和管理员的边界

系统里有两种角色:普通用户和管理员。普通用户能看文本分析、文本管理、个人信息;管理员多一个用户管理功能。权限控制的实现方式通常有两种:装饰器拦截和路由判断。

# 权限检查装饰器 from functools import wraps from flask import session, jsonify def login_required(f): @wraps(f) def decorated_function(*args, **kwargs): if 'user_id' not in session: return jsonify({'code': 401, 'msg': '请先登录'}) return f(*args, **kwargs) return decorated_function def admin_required(f): @wraps(f) def decorated_function(*args, **kwargs): if session.get('role') != 'admin': return jsonify({'code': 403, 'msg': '无权限访问'}) return f(*args, **kwargs) return decorated_function # 使用示例 @app.route('/api/user/list') @login_required @admin_required def user_list(): # 只有管理员能访问 pass

login_required检查用户是否登录,admin_required检查角色是否为管理员。两个装饰器可以叠加使用,先检查登录,再检查权限。session里存的user_id和role在登录成功时写入,退出登录时清除。

这种实现方式简单直接,适合毕设项目。如果你要做得更规范,可以把权限做成配置表,不同角色对应不同权限点,但那样代码量会大很多,对这个小系统来说没必要。

4.4 对比分析模块:双模型结果的可视化展示

对比分析模块用柱状图和饼图展示 DNN 和 BERT 的分析结果。后端需要提供两个模型的分析数据,前端用 ECharts 渲染。

# 对比分析接口 @app.route('/api/compare', methods=['POST']) def compare_analyze(): text = request.get_json().get('content', '') # DNN 模型推理 dnn_result = dnn_model.predict(text) # 返回 {'label': 'negative', 'score': 0.87} # BERT 模型推理 bert_result = classifier(text)[0] # 返回 {'label': 'negative', 'score': 0.93} return jsonify({ 'code': 200, 'data': { 'text': text, 'dnn': dnn_result, 'bert': bert_result } })

前端拿到数据后,用 ECharts 画两个图:柱状图对比两个模型的置信度,饼图展示分类结果的分布。这个模块的价值在于让用户直观看到两个模型的差异,如果两个模型结果一致,说明分类比较可靠;如果不一致,就需要人工复核。

5. 避坑与排查:跑这套源码时最容易翻车的几个地方

5.1 中文编码问题导致数据乱码

现象:数据库里存的中文显示为???或者乱码,前端页面也显示不正常。

原因:MySQL 数据库、表、连接字符集没有统一设置为utf8mb4。Python 连接数据库时没有指定charset,或者数据库默认字符集是latin1。

解决:建库时指定CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,连接时加charset='utf8mb4'。已经建好的库可以用ALTER DATABASE opinion_analysis CHARACTER SET utf8mb4;修改。另外检查 Python 文件本身的编码,确保是 UTF-8。

5.2 BERT 模型加载失败或推理超时

现象:启动时卡在加载模型,或者分析请求长时间无响应。

原因:模型文件没有下载完整,或者网络问题导致from_pretrained超时。另外,如果每次请求都重新加载模型,内存和显存都会爆。

解决:提前下载模型到本地,用本地路径加载。模型加载放在应用启动时,不要放在请求处理函数里。如果内存不够,换用更小的模型,比如bert-tiny或albert-chinese-tiny。

5.3 数据库连接未关闭导致连接数耗尽

现象:系统运行一段时间后报Too many connections错误。

原因:每次数据库操作都新建连接,但没有关闭,连接数越积越多。

解决:用连接池管理数据库连接,或者确保每次操作后cursor.close()和conn.close()都执行。Flask 项目可以用flask-sqlalchemy或dbutils的连接池。毕设项目如果并发不高,至少要在finally块里关闭连接。

5.4 前端图表数据格式不匹配

现象:ECharts 图表不显示,或者显示为空白。

原因:后端返回的数据格式和前端 ECharts 配置里的series.data格式不一致。比如后端返回[{'label': 'negative', 'score': 0.9}],前端期望的是[0.9]。

解决:在接口层做数据转换,把后端数据转成前端需要的格式。或者在 ECharts 配置里用formatter函数处理。建议前后端约定好数据格式,写接口文档。

5.5 管理员账号初始密码未知

现象:源码跑起来后,不知道管理员账号密码,进不了用户管理页面。

原因:数据库初始数据里可能没有管理员账号,或者密码是加密的,看不到明文。

解决:直接查数据库user_info表,看role字段为admin的记录。如果密码是明文,直接看;如果是哈希,可以临时在代码里加一个注册管理员的逻辑,或者手动插入一条记录。毕设项目通常密码是明文或者简单 MD5,反查不难。

6. 二次开发与改造:把这套毕设变成能用的工具

6.1 从“手动输入”到“自动采集”的改造思路

这套系统目前是手动输入文本进行分析,但舆情系统的核心价值在于自动采集。改造方向是加一个爬虫模块,定时抓取指定平台的数据,自动送入分析流程。

常见做法是用requests+BeautifulSoup抓取网页,或者用平台提供的 API。抓到的数据先存到临时表,然后批量调用分析接口。注意控制抓取频率,不要给目标平台造成压力。如果要做定时任务,可以用APScheduler或者系统的crontab。

# 定时采集任务示例 from apscheduler.schedulers.background import BackgroundScheduler import requests def fetch_and_analyze(): # 抓取数据 resp = requests.get('https://example.com/api/comments', params={'city': '某市'}) comments = resp.json().get('data', []) for comment in comments: text = comment.get('content', '') if text: # 调用分析接口 analyze_text_internal(text) scheduler = BackgroundScheduler() scheduler.add_job(fetch_and_analyze, 'interval', minutes=30) scheduler.start()

这段代码用APScheduler每 30 分钟执行一次采集任务。fetch_and_analyze先抓数据,再逐条送入分析。实际部署时要注意异常处理,网络请求失败不能影响主流程。

6.2 模型替换与准确率验证

如果你觉得 BERT 太重,可以换成更轻量的模型,比如TextCNN或FastText。替换模型后需要验证准确率,方法是准备一批标注好的测试数据,跑一遍看准确率和召回率。

# 模型评估示例 from sklearn.metrics import classification_report true_labels = [...] # 人工标注的真实标签 pred_labels = [...] # 模型预测标签 print(classification_report(true_labels, pred_labels, target_names=['负面', '中性', '正面']))

classification_report会输出每个类别的精确率、召回率和 F1 值。如果某个类别 F1 明显偏低,说明模型在这个类别上表现不好,可能需要补充训练数据或者调整分类阈值。

6.3 前端交互优化:从“能用”到“好用”

毕设项目的前端通常比较粗糙,改造空间很大。几个低成本高收益的优化点:

  • 分析结果用颜色区分:负面红色、中性灰色、正面绿色,一眼就能看出结果。
  • 文本列表加搜索框,支持按关键词筛选。
  • 对比分析页面加一个“历史对比”功能,展示同一段文本在不同时间点的分析结果变化。
  • 移动端适配,用响应式布局让手机也能正常访问。

这些改动不需要动后端核心逻辑,主要是前端模板和 CSS 的调整。如果你不熟悉前端,可以用 Bootstrap 或 Tailwind CSS 快速搭一套好看的界面。

6.4 部署上线时的一个血泪教训

我见过太多人把毕设项目直接python app.py跑在服务器上,然后终端一关服务就没了。正确的做法是用nohup或者systemd托管进程,或者用supervisor管理。另外,Flask 自带的开发服务器性能很差,生产环境一定要用gunicorn或uwsgi。

# 用 gunicorn 启动 Flask 应用 gunicorn -w 4 -b 0.0.0.0:5000 app:app # 用 nohup 后台运行 nohup gunicorn -w 4 -b 0.0.0.0:5000 app:app > app.log 2>&1 &

-w 4表示 4 个 worker 进程,根据 CPU 核心数调整。app:app表示app.py文件里的app对象。日志重定向到app.log,方便排查问题。

从那以后我每次部署 Python 项目,都会先确认进程管理工具配好了,再去看业务逻辑。希望这套源码能帮你省掉一些重复造轮子的时间,把精力花在真正有价值的改造上。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询