新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于Python+Flask+MongoDB+ECharts的舆情监测系统实战

发布时间:2026/10/2 4:17:28来源:尧图网络
基于Python+Flask+MongoDB+ECharts的舆情监测系统实战
简介这份资源是《基于Python的舆情监测系统设计》完整文档面向计算机相关专业学生、毕业设计开发者以及希望掌握舆情监测技术的学习者帮助解决从数据采集到可视化展示的全流程设计问题。压缩包内共1个docx文件约762KB内容涵盖绪论、相关技术介绍、数据采集、数据分析、数据可视化与系统架构等章节结构完整、层次清晰。文档围绕网络爬虫原理、请求头改写、正则表达式与DOM树定位、XML与JSON解析、MongoDB非结构化存储、中文分词与情感分析、时间序列趋势分析、Flask后端搭建以及Echarts动态图表展示等关键技术展开并给出微服务架构下的模块划分与API通信思路。目前已有361人学习下载适合作为课程设计、毕业设计或技术选型的参考材料读者可据此快速理解舆情监测系统的整体实现路径与关键技术选型依据。1. 舆情监测系统到底在监测什么从一条负面帖子的 6 小时说起一条本地论坛的吐槽帖从发出到被品牌方发现中间隔了 6 个小时。这 6 小时里它被转到了两个微信群、一个本地生活号等公关团队反应过来评论区已经吵翻了。很多做舆情监测系统的人最初都是被这种「发现太晚」逼出来的。所谓舆情监测系统本质就是一套自动化的信息采集、清洗、存储、分析和可视化流水线用 Python 爬虫把分散在论坛、新闻站、社交平台的信息抓回来做去重和情感倾向判断存进 MongoDB再用 Flask 把数据接口暴露出来前端用 ECharts 把趋势、来源分布、热词云画出来。它适合谁适合中小团队里那个既懂点 Python、又要对品牌口碑负责的人也适合想拿一个完整项目练手的开发者。这套东西不神秘难的是把采集频率、去重逻辑和存储结构设计对否则跑两天数据库就爆了。2. 技术选型为什么是 Python Flask MongoDB ECharts2.1 采集与分析层为什么锁定 Python舆情监测的第一道工序是采集第二道是文本处理这两件事 Python 的生态最顺手。采集端常见做法是 requests 配合 BeautifulSoup 或 lxml 解析静态页遇到动态渲染的页面再上 Playwright 或 Selenium。文本处理端中文分词用 jieba情感判断可以先用 SnowNLP 跑一个基线后面再换成自己标注训练的模型。选 Python 不是因为它快而是因为从爬虫到分词到入库整条链路都有成熟库一个人一周内能把最小闭环跑通。这里要提醒一个边界采集频率不是越高越好。我一般把新闻类站点设成 30 分钟一轮论坛类设成 15 分钟一轮社交平台类如果接口受限就拉长到 1 小时。频率过高不仅给对方服务器压力自己这边也容易被限流反而漏数据。2.2 Flask 做接口层轻量但够用Flask 在这个系统里的角色是「数据出口」。爬虫和分析脚本把结果写进 MongoDBFlask 负责按时间范围、来源、情感标签把数据查出来以 JSON 返回给前端。它比 Django 轻路由和扩展按需引入适合这种以数据接口为主、页面不复杂的场景。一个最小可用的接口长这样from flask import Flask, jsonify, request from pymongo import MongoClient from datetime import datetime, timedelta app Flask(__name__) client MongoClient(mongodb://localhost:27017/) db client[opinion_monitor] col db[posts] app.route(/api/trend) def trend(): # 默认查最近 7 天前端可通过 days 参数覆盖 days int(request.args.get(days, 7)) since datetime.now() - timedelta(daysdays) pipeline [ {$match: {publish_time: {$gte: since}}}, {$group: { _id: {$dateToString: {format: %Y-%m-%d, date: $publish_time}}, count: {$sum: 1} }}, {$sort: {_id: 1}} ] result list(col.aggregate(pipeline)) return jsonify([{date: r[_id], count: r[count]} for r in result]) if __name__ __main__: app.run(host0.0.0.0, port5000, debugTrue)这段代码的关键在聚合管道$match先按时间过滤减少后续处理量$group用$dateToString把时间戳按天归组$sort保证前端拿到的顺序是对的。days参数做成可调是因为前端切换「近 7 天 / 近 30 天」时不用改后端。debugTrue只在开发时开上线要关掉否则有安全风险。2.3 MongoDB 存舆情数据文档模型天然贴合舆情数据的特点是字段不固定。一条微博有转发数、点赞数一条新闻有作者、来源媒体一条论坛帖有回复楼层。用关系型数据库要建一堆表和关联用 MongoDB 直接一个文档塞进去字段不同也不影响。集合设计上我一般分三个posts存原始帖子analysis存分词和情感结果keywords存热词统计。posts里必须建两个索引publish_time用于时间范围查询url建唯一索引用于去重。没有唯一索引同一篇文章被爬两次就会重复入库趋势图直接失真。// 在 mongo shell 里执行 db.posts.createIndex({ publish_time: -1 }) db.posts.createIndex({ url: 1 }, { unique: true }) db.posts.createIndex({ source: 1, publish_time: -1 })第三个复合索引是给「按来源筛选 按时间排序」这种组合查询用的。索引不是越多越好每个索引都会拖慢写入速度舆情系统写入频繁三个索引基本是平衡点。2.4 ECharts 做可视化前端只负责画ECharts 在这个系统里承担趋势折线图、来源饼图、热词柱状图。它的好处是配置项驱动后端返回 JSON前端改series.data就能刷新。折线图的 x 轴刻度如果数据点太密用axisLabel.interval控制间隔不然标签会叠在一起。饼图做来源分布时radius设成[40%, 70%]做成环形中间留白放总数比实心饼图清爽。3. 从零搭一套最小可跑系统环境、采集、入库、出图3.1 环境准备Python、MongoDB、依赖一次装齐先把 Python 环境弄干净。我习惯用 venv 隔离避免和系统包打架python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install flask pymongo requests beautifulsoup4 jieba snownlpMongoDB 的安装按官方文档走Linux 下用包管理器装完记得启动服务并设开机自启。装完用mongosh连一下能进就说明服务正常。常见翻车点是数据目录权限不对服务起不来日志里会写 permission denied改一下/var/lib/mongodb的属主即可。依赖里snownlp是情感分析的基线库jieba负责分词。这两个库第一次加载模型会慢几秒属正常现象。3.2 采集脚本抓取、清洗、去重三步走采集脚本的核心不是「抓到」而是「抓干净」。下面是一个针对新闻列表页的最小示例import requests from bs4 import BeautifulSoup from pymongo import MongoClient from datetime import datetime import hashlib client MongoClient(mongodb://localhost:27017/) col client[opinion_monitor][posts] def fetch_list(url): headers {User-Agent: Mozilla/5.0 (compatible; OpinionBot/1.0)} resp requests.get(url, headersheaders, timeout10) resp.encoding resp.apparent_encoding soup BeautifulSoup(resp.text, lxml) items [] for node in soup.select(.news-list li): title node.select_one(a).get_text(stripTrue) link node.select_one(a)[href] items.append({title: title, url: link}) return items def save(items, source): for it in items: doc { title: it[title], url: it[url], source: source, publish_time: datetime.now(), raw_hash: hashlib.md5(it[title].encode()).hexdigest() } try: col.insert_one(doc) except Exception as e: # 唯一索引冲突说明已存在跳过即可 print(duplicate skip:, it[url])逻辑说明apparent_encoding能自动识别中文编码避免乱码raw_hash是对标题做的指纹配合url唯一索引双重去重insert_one触发唯一索引冲突时抛异常捕获后跳过这是去重最省事的写法。参数上timeout10别省否则某个站点卡住会拖死整个采集循环。3.3 情感分析与热词统计把原始数据变成指标入库之后要跑分析。情感分析用 SnowNLP 给每条帖子打一个 0 到 1 的分数大于 0.6 判正面小于 0.4 判负面中间算中性。热词统计用 jieba 分词后过滤停用词再按词频排序。import jieba from snownlp import SnowNLP from pymongo import MongoClient client MongoClient(mongodb://localhost:27017/) db client[opinion_monitor] STOPWORDS set([的, 了, 是, 在, 和, 就, 都, 而, 及]) def analyze(): for post in db.posts.find({analyzed: {$ne: True}}): text post[title] score SnowNLP(text).sentiments label positive if score 0.6 else (negative if score 0.4 else neutral) words [w for w in jieba.cut(text) if w not in STOPWORDS and len(w) 1] db.analysis.insert_one({ post_id: post[_id], score: score, label: label, words: words }) db.posts.update_one({_id: post[_id]}, {$set: {analyzed: True}})analyzed字段是幂等标记保证脚本重复跑不会重复分析。len(w) 1过滤掉单字单字在中文里噪声太大。停用词表要按自己的数据补比如「转发」「评论」这类平台词也该加进去。3.4 Flask 接口 ECharts 出图前后端怎么对接后端接口按第 2 章的写法暴露/api/trend、/api/source、/api/keywords三个路由。前端页面用 ECharts 初始化图表定时 fetch 数据刷新。const chart echarts.init(document.getElementById(trend)); async function loadTrend() { const res await fetch(/api/trend?days7); const data await res.json(); chart.setOption({ xAxis: { type: category, data: data.map(d d.date) }, yAxis: { type: value }, series: [{ type: line, data: data.map(d d.count), smooth: true, areaStyle: { color: rgba(64,158,255,0.2) } }] }); } loadTrend(); setInterval(loadTrend, 60000);areaStyle给折线加了渐变填充视觉上更像「趋势」。setInterval每分钟刷新一次和采集频率对齐即可刷太快没意义。x 轴数据点超过 30 个时加axisLabel: { interval: auto }让 ECharts 自己抽稀。4. 避坑与排查那些让系统跑不过三天的坑4.1 去重失效导致趋势图虚高现象趋势图上的数量比实际帖子多出一大截同一篇文章反复出现。原因url字段没建唯一索引或者采集时 url 带了随机的 session 参数导致同一页面每次抓到的 url 都不同。解决先确认唯一索引已建再在入库前对 url 做规范化去掉?后面的追踪参数只保留路径部分。4.2 情感分析在反讽文本上集体翻车现象明显是吐槽的帖子被判成正面。原因SnowNLP 基于电商评论语料训练对反讽、网络梗的识别能力弱。解决把情感分析当基线不要当结论。对判分在 0.4 到 0.6 之间的「模糊区」单独抽出来人工复核或者引入领域词典做二次修正。别指望一个库解决所有问题。4.3 MongoDB 写入越来越慢现象系统跑一周后采集入库明显变慢。原因索引过多或者posts集合里堆积了大量analyzed: false的文档分析脚本跟不上采集速度。解决用db.posts.stats()看索引大小砍掉不用的索引分析脚本改成批量处理一次取 500 条别一条条查。4.4 Flask 接口返回慢拖垮前端现象前端图表加载转圈很久。原因聚合查询没走索引或者一次返回了全量数据。解决确认publish_time索引生效用explain()看查询计划接口强制加时间范围和分页默认只返回最近 7 天别让前端拉全表。4.5 采集被目标站点限流现象采集脚本跑着跑着开始返回 403 或空内容。原因请求频率过高或 User-Agent 太单一。解决加随机延时请求间隔设成 2 到 5 秒随机User-Agent 准备几个轮换对返回 403 的站点拉长采集周期别硬刚。5. 让系统从「能跑」到「好用」三个进阶技巧第一个技巧是给采集加断点续采。在 MongoDB 里单独建一个crawl_state集合记录每个来源最后成功采集的时间戳脚本启动时先读这个时间戳只抓这之后的新内容。这样即使脚本中途挂了重启也不会重复抓历史数据省时间也省对方服务器资源。第二个技巧是热词统计加时间窗口对比。不要只算「当前热词」而是算「最近 24 小时词频」和「前 7 天平均词频」的比值比值高的词才是真正在冒头的新话题。这个思路比单纯看词频有用得多因为高频词往往是「转发」「活动」这种无意义词突增词才代表舆情苗头。def rising_keywords(): recent db.analysis.aggregate([ {$match: {created_at: {$gte: datetime.now() - timedelta(hours24)}}}, {$unwind: $words}, {$group: {_id: $words, cnt: {$sum: 1}}} ]) recent {r[_id]: r[cnt] for r in recent} baseline db.keywords.find_one({type: baseline}) or {freq: {}} result [] for word, cnt in recent.items(): base baseline[freq].get(word, 1) result.append({word: word, ratio: cnt / base}) return sorted(result, keylambda x: -x[ratio])[:20]$unwind把 words 数组拆成单条记录$group统计词频。baseline 是提前算好的历史词频存进keywords集合。比值排序取前 20就是当天的突增词。这个接口接到前端用 ECharts 柱状图展示比词云更有指向性。第三个技巧是给负面舆情加告警。在分析脚本里当一条帖子的情感分低于 0.3 且来源是重点监控站点时往一个alerts集合写一条记录Flask 再加一个/api/alerts接口前端轮询到新告警就弹提示。这套机制不复杂但能把「6 小时才发现」压缩到「几分钟内看到」。我自己踩过最深的坑是早期图省事没建唯一索引结果系统跑了一周趋势图上的数字漂亮得不像话拿去汇报才发现全是重复数据。从那以后任何采集类项目我第一件事就是先把去重和索引做掉再谈分析和可视化。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

SQL窗口函数实战速查:排名、位移、聚合三类函数避坑指南 2026/10/2 5:19:38

SQL窗口函数实战速查:排名、位移、聚合三类函数避坑指南

简介:这是一份专为数据库从业者设计的《SQL窗口函数速查表》PDF文档,面向DBA、数据分析师、后端开发工程师及SQL进阶学习者,解决复杂数据分析场景下窗口函数选型难、语法易混淆、实际应用无参考等痛点。资源为单文件PDF(841KB&…

阅读更多 →
一个人半年用AI重写企业ERP:从架构调整到代码生成的完整实战 2026/10/2 5:19:31

一个人半年用AI重写企业ERP:从架构调整到代码生成的完整实战

1. 这半年我到底干了件什么事先说结论:我一个人,从零开始,用六个月的时间把公司跑了好几年的 ERP 系统从技术栈到业务模型全部重写了一遍。不是换皮,不是局部优化,而是把原来的单体架构、手工报表、人工对账逻辑全部打…

阅读更多 →
img2threejs实战:用AI将图片生成Three.js 3D代码 2026/10/2 5:19:31

img2threejs实战:用AI将图片生成Three.js 3D代码

1. 一张图变3D模型,这个项目到底在解决什么问题第一次看到 img2threejs 这个项目的时候,我正被一个需求折磨得够呛——客户丢过来十几张产品白底图,要求一周内出一套可以在网页里旋转、缩放、拆解的 3D 展示方案。传统路子无非两条&#xff1…

阅读更多 →
AI驱动的测试用例设计:Xmind思维导图实现需求到可执行用例的语义转化 2026/10/2 5:19:31

AI驱动的测试用例设计:Xmind思维导图实现需求到可执行用例的语义转化

1. 这不是“AI写测试用例”,而是把测试工程师的脑回路具象化成一张可执行的思维导图你有没有过这种体验:拿到一份30页的PRD文档,盯着需求列表发呆半小时,手边打开Xmind新建空白画布,光是“登录模块”四个字就卡在中心节…

阅读更多 →
GitHub日榜速报:从热词痛点看项目筛选与评估实战 2026/10/2 5:19:31

GitHub日榜速报:从热词痛点看项目筛选与评估实战

1. 日榜速报到底在解决什么问题很多人第一次接触 GitHub 日榜,是把它当成一个"今天有什么新东西"的资讯入口。但真正每天刷榜的人,目的往往更具体:找可复用的轮子、判断某个技术方向的热度拐点、或者单纯想看看别人今天在折腾什么。…

阅读更多 →
UDS诊断之get_seed:安全访问服务与seedkey机制全解析 2026/10/2 5:19:31

UDS诊断之get_seed:安全访问服务与seedkey机制全解析

没接触过 UDS 诊断开发的人,第一次看到get_seed这个词很容易懵。它既不是操作系统里的随机数接口,也不是某个开源库的种子生成函数。在汽车电子领域,get_seed是 UDS(Unified Diagnostic Services,统一诊断服务&#xf…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉