资讯动态

Python舆情分析系统源码实战:从数据采集到情感分析全链路

发布时间:2026/10/9 19:49:18 来源:尧图企业网站定制
简介这份资源是面向计算机相关专业学生与项目实战学习者的Python人工智能大作业完整资料包聚焦网络舆情分析系统的设计与实现适合正在准备期末大作业、毕业设计或需要积累AI项目经验的人群。压缩包共118个文件约45.2MB以27个py源码文件为核心辅以36个txt说明、12个jar与10个class等Java组件、7个java文件、6个xml配置、2个ipynb笔记本及json、xlsx等数据文件涵盖算法实现、界面设计与依赖库目录结构清晰便于按模块查阅。项目经导师指导并获评审98分源码均经本地编译调试可稳定运行内容由助教老师审定难度适中。已有144人学习关注。读者可获取完整可运行工程、舆情分析核心代码、界面与图表实现思路及配套说明文档用于快速复现、二次开发与答辩准备。1. 从一份“高分大作业”说起这套 Python 舆情分析系统到底能跑出什么如果你正在为期末的人工智能大作业发愁大概率会遇到一个尴尬局面想做一个“看起来像那么回事”的项目但爬虫、清洗、情感分析、可视化这几块拼起来代码量直接飙到两三千行调通一个另一个又崩。这套基于 Python 的网络舆情分析系统源码和全套资料解决的就是这个场景——它不是玩具级的 demo而是一个能完整跑通“数据采集 → 文本清洗 → 情感倾向判断 → 关键词提取 → 可视化看板”全链路的课程设计级项目。适合谁一是需要交期末大作业、但不想从零手搓所有模块的本科生二是想拿一个完整 Python 项目练手、理解 NLP 落地流程的转行者。它最大的价值在于把舆情分析这个听起来很玄学的任务拆成了可复现的工程步骤每一步都有对应的源码文件和说明资料你照着改参数就能跑出自己的结果。2. 拆开源码包四个核心模块与它们的技术选型2.1 数据采集层为什么用 requests BeautifulSoup 而不是 Scrapy拿到源码后第一件事是看数据从哪来。这套系统默认走的是公开论坛和新闻站点的结构化页面采集模块用的是 requests 发请求、BeautifulSoup 做解析而不是上 Scrapy 框架。原因很实际大作业场景下目标站点通常只有三五个页面结构固定Scrapy 的调度器和中间件反而增加了调试成本。源码里采集部分的核心逻辑大概长这样import requests from bs4 import BeautifulSoup import time import random def fetch_page(url, retry3): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36 } for i in range(retry): try: resp requests.get(url, headersheaders, timeout10) resp.encoding resp.apparent_encoding # 防止中文乱码 if resp.status_code 200: return resp.text except requests.RequestException as e: print(f第{i1}次请求失败: {e}) time.sleep(random.uniform(1, 3)) # 随机延时降低被封风险 return None def parse_list(html): soup BeautifulSoup(html, html.parser) items [] for node in soup.select(.article-item): # 选择器需按目标站点调整 title node.select_one(.title).get_text(stripTrue) link node.select_one(a)[href] items.append({title: title, link: link}) return items这段代码有两个关键参数需要你动手改headers里的 User-Agent 要换成你本机浏览器的真实值否则部分站点会返回 403timeout建议设 10 秒太短容易误判失败太长会拖慢整体采集。apparent_encoding这行是血泪经验——很多新手直接写resp.encoding utf-8结果遇到 GBK 编码的站点全是乱码用 apparent_encoding 让 chardet 自动判断更稳。采集频率上源码里用了random.uniform(1, 3)做随机延时这是常见做法但如果你要采的页面超过 500 条建议把延时调到 2 到 5 秒否则目标站点大概率会限流。2.2 文本清洗与分词jieba 的自定义词典怎么配采集回来的文本不能直接喂给模型里面混着 HTML 标签、特殊符号、停用词。源码里清洗模块分三步走正则去标签、jieba 分词、停用词过滤。重点说 jieba 这块因为舆情文本里经常出现网络新词和领域术语默认词典根本切不对。比如“情绪价值”会被切成“情绪”和“价值”“破防了”会被切成“破”和“防了”。解决办法是加载自定义词典import jieba import re jieba.load_userdict(user_dict.txt) # 每行格式词语 词频 词性 def clean_text(raw): # 去掉 HTML 标签和 URL text re.sub(r[^], , raw) text re.sub(rhttp[s]?://\S, , text) # 只保留中文、英文和数字 text re.sub(r[^\u4e00-\u9fa5a-zA-Z0-9], , text) return text.strip() def segment(text, stopwords): words jieba.lcut(text) return [w for w in words if w not in stopwords and len(w) 1]user_dict.txt的格式是每行一个词后面可以跟词频和词性词频越高越容易被切出来。我一般会把目标领域的高频词手动加进去比如做舆情分析就加“热搜”“控评”“带节奏”“反转”这类词。停用词表源码里带了一份约 1200 词的通用表但建议你根据实际语料再补——比如“转发”“点赞”“楼主”这些在论坛文本里高频出现但对情感判断没用的词加进去能明显提升关键词提取的质量。注意len(w) 1这个过滤条件它会丢掉单字词如果你做的任务对单字敏感比如某些缩写可以改成len(w) 1。2.3 情感分析模块SnowNLP 与规则引擎的混合策略这是整套系统里最容易被质疑“准不准”的部分。源码没有用 BERT 这类大模型而是走了 SnowNLP 加规则修正的路线。SnowNLP 对通用中文文本的情感倾向判断在 70% 到 80% 左右直接拿来用会出现“虽然但是”句式判反的情况。源码里的做法是先用 SnowNLP 打分再用否定词表和程度副词表做二次修正。from snownlp import SnowNLP NEGATION_WORDS [不, 没, 无, 非, 莫, 勿, 别, 未] DEGREE_WORDS {非常: 1.5, 很: 1.3, 太: 1.4, 稍微: 0.8, 有点: 0.7} def sentiment_score(text): if not text: return 0.5 base SnowNLP(text).sentiments # 返回 0~1越接近 1 越正面 # 否定词修正如果否定词出现在情感词前 3 个字符内翻转分数 for neg in NEGATION_WORDS: idx text.find(neg) if idx ! -1 and idx len(text) - 1: base 1 - base break # 程度副词修正 for word, weight in DEGREE_WORDS.items(): if word in text: base base * weight if base 0.5 else base / weight break return max(0.0, min(1.0, base))参数上base的阈值划分建议大于 0.6 判正面小于 0.4 判负面中间算中性。源码里用的是 0.65 和 0.35偏保守你可以根据自己语料的分布调。否定词修正那段逻辑有个坑如果文本里出现多个否定词比如“不是不”代码只处理第一个结果会偏。更稳的做法是用滑动窗口匹配但大作业场景下这个简化版够用了。程度副词的权重表也是经验值你可以拿几十条标注好的样本跑一遍看准确率再微调。2.4 可视化与结果导出Flask 看板与 Excel 报表分析结果最终要落到能看的东西上。源码提供了两个出口一个是 Flask 搭的简易 Web 看板展示情感分布饼图、关键词词云、时间趋势折线另一个是导出 Excel 报表方便写报告时直接截图。Flask 部分的核心路由from flask import Flask, render_template import pandas as pd app Flask(__name__) app.route(/dashboard) def dashboard(): df pd.read_csv(result.csv) pos len(df[df[sentiment] 0.6]) neg len(df[df[sentiment] 0.4]) neu len(df) - pos - neg keywords df[keywords].str.split(,).explode().value_counts().head(50) return render_template(dashboard.html, pospos, negneg, neuneu, keywordskeywords.to_dict())result.csv是上游分析模块的输出字段包括text、sentiment、keywords、publish_time。词云用 jieba 分词后统计词频再交给前端 wordcloud2.js 渲染。注意 Flask 默认跑在 5000 端口如果你本机这个端口被占启动时加app.run(port5001)换一个。导出 Excel 用的是 pandas 的to_excel需要额外装 openpyxl源码的 requirements.txt 里已经列了但很多人 pip install 的时候漏掉跑起来报ModuleNotFoundError: No module named openpyxl补装就行。3. 从零跑通环境配置与分步执行3.1 依赖安装与版本对齐拿到源码包后别急着python main.py。先看 requirements.txt里面列了 requests、beautifulsoup4、jieba、snownlp、flask、pandas、openpyxl、wordcloud 这几个包。Python 版本建议 3.8 到 3.103.11 以上有些包编译会出问题。安装命令python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple用国内镜像源能快不少。如果 snownlp 安装时报错大概率是缺少 setuptools先pip install setuptools再装。wordcloud 在 Windows 上可能需要手动下载对应的 whl 文件这个包编译依赖 C 环境新手容易在这里翻车。实在装不上可以先把词云模块注释掉不影响主流程跑通。3.2 配置文件修改三个必须改的参数源码里有一个config.py里面有三个参数你必须按自己的情况改参数名默认值说明修改建议TARGET_URL示例站点地址采集入口换成你要分析的公开页面MAX_PAGES10最大翻页数测试时设 2正式跑设 50 以内OUTPUT_PATH./result.csv结果输出路径确保目录存在否则报错TARGET_URL不要填需要登录才能看的页面源码没有处理 cookie 和 session。MAX_PAGES设太大容易触发目标站点限流建议先设 2 跑通流程再逐步加。OUTPUT_PATH如果指向不存在的目录pandas 会直接抛异常跑之前先mkdir一下。3.3 执行流程与中间结果检查跑的顺序是先采集再清洗再分析最后可视化。源码里main.py把这四步串起来了但建议你分步跑方便定位问题python crawler.py # 生成 raw_data.csv python cleaner.py # 生成 clean_data.csv python analyzer.py # 生成 result.csv python app.py # 启动看板每跑完一步打开对应的 csv 看一眼。raw_data.csv里应该有 title 和 content 两列如果 content 大量为空说明解析选择器写错了回去改parse_list里的soup.select。clean_data.csv里如果出现大量单字或乱码检查停用词表和编码。result.csv里 sentiment 列如果全是 0.5说明 SnowNLP 没正常加载重装一下。4. 避坑与排查五个真实翻车现场4.1 采集返回 403 或空内容现象requests 拿到状态码 403或者返回的 HTML 里没有目标数据。原因目标站点做了 UA 校验或频率限制。解决把 headers 里的 User-Agent 换成浏览器真实值同时把延时调大到 3 到 5 秒。如果还不行检查目标页面是不是 JS 动态渲染的——这套源码只处理静态 HTML遇到 Vue 或 React 渲染的页面requests 拿到的只是空壳需要换 Selenium 或直接找数据接口。4.2 jieba 分词结果全是单字现象分词后输出的词列表里大量单字比如“的”“了”“是”。原因停用词表没加载成功或者user_dict.txt路径不对。解决检查stopwords变量是否为空列表确认jieba.load_userdict的路径是绝对路径或相对于执行目录的正确路径。另外len(w) 1这个过滤条件如果被误删单字就会全跑出来。4.3 SnowNLP 情感打分全部偏向 0.5现象所有文本的 sentiment 值都在 0.5 附近区分度极低。原因SnowNLP 的默认模型对短文本和网络用语不敏感。解决一是加长文本长度把标题和正文拼在一起再打分二是引入规则修正就是 2.3 节里那套否定词和程度副词逻辑三是如果语料领域特殊可以拿几百条标注数据重新训练 SnowNLP 的模型源码资料里附了训练脚本。4.4 Flask 看板启动后页面空白现象浏览器打开 127.0.0.1:5000 显示空白或 500 错误。原因result.csv不存在或字段缺失模板渲染时取不到数据。解决先确认result.csv在项目根目录且包含 sentiment 和 keywords 两列。如果字段名不对改dashboard函数里的列名引用。另外Flask 的模板文件必须放在templates/目录下很多人把 html 放在根目录导致TemplateNotFound。4.5 导出 Excel 时报 openpyxl 缺失现象ModuleNotFoundError: No module named openpyxl。原因requirements.txt 里虽然写了但 pip 安装时可能因为网络问题跳过了。解决单独pip install openpyxl即可。如果还报错检查 pandas 版本老版本 pandas 的to_excel接口和新版 openpyxl 不兼容升级 pandas 到 1.3 以上。5. 进阶技巧把情感阈值调准与批量跑多主题跑通之后你大概率会发现默认的情感阈值0.6/0.4在你的语料上不准。我一般会做一步验证从result.csv里随机抽 50 条人工标一遍正面/负面/中性然后画 ROC 曲线找最佳截断点。代码不复杂import pandas as pd from sklearn.metrics import roc_curve df pd.read_csv(result.csv) # 假设 manual_label 是你人工标的 0/1 fpr, tpr, thresholds roc_curve(df[manual_label], df[sentiment]) best_threshold thresholds[(tpr - fpr).argmax()] print(f最佳阈值: {best_threshold:.3f})这个阈值因语料而异新闻评论和论坛帖子的分布完全不同别直接抄别人的。另一个进阶用法是批量跑多主题把TARGET_URL和OUTPUT_PATH做成列表循环调用采集和分析函数最后把多个 result.csv 合并对比不同主题的情感分布差异。源码资料里附了一个batch_runner.py的示例改一下 URL 列表就能用。从那以后我每次拿到新的舆情语料都强制先跑一遍人工抽样验证再调阈值不然写进报告里的结论自己都不敢信。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑