资讯动态

Python股票分析系统:网络舆情数据流水线实战拆解

发布时间:2026/10/18 13:36:48 来源:尧图企业网站定制
简介一份面向计算机相关专业学生及初学者的高分大作业项目围绕网络舆情与股票市场的关联展开综合利用Python爬虫、情感分析、数据可视化与预测建模等技术实现从舆情数据采集到价格趋势预判的完整流程。资源共包含89个文件其中49个Python源码文件构成系统主体另配套CSV数据表、HTML展示页面、SQL数据库脚本、Word说明文档及环境配置文件整体压缩包约2.87MB模块划分清楚便于按功能点学习与二次开发。已有88人学习下载。项目中不仅提供新闻/社交媒体舆情抓取、股票行情数据接口、情感倾向分析、可视化图表等核心模块还附带项目立项文档、需求分析文档与软件计划说明可帮助快速理解一个评分98分项目的设计思路与代码结构。所有源码经调试可本地运行适合课程答辩、毕业设计参考及数据分析实战练习。1. 基于网络舆情的 Python 股票分析系统一套能跑通的数据流水线你盯着一只股票的新闻刷了一上午评论区情绪从“利好”刷到“完了”可 K 线上还没动静。这时候你最需要的不是再读十条快讯而是一套能把舆情量化成数字的流程。这个基于网络舆情的 Python 股票分析系统就是一条从抓取新闻、情感打分、关联股价到给出预测的完整数据流水线。它不是只写写 PPT 的演示项目而是带 MySQL 数据库、带 Web 界面、带爬虫模块、带 Python 源码和说明文档的高分大作业成品适合计算机专业学生拿去消化课程设计也适合想入门舆情分析与金融数据处理的从业者研究它的工程结构。2. 系统架构与数据链路三个核心模块怎么打通拿到项目压缩包先别急着跑把文件结构看懂后面排查问题会省一半时间。整个系统的骨架非常清晰app.py作为应用入口controller管路由service管业务逻辑model管数据库表映射templates和static是 Web 页面层news_data是爬虫落地的原始数据目录外加environment.yml和两个 SQL 文件负责环境与数据初始化。这是课程设计里最标准的 MVC 变体也方便你在此基础上改成自己的选题。2.1 从文件结构反推技术选型技术栈从文件名里基本能读出来app.py加templates加static典型的 Flask 项目结构model目录里放着 ORM 映射配合stocksystem0107.sql和database.sql说明持久层用的是 MySQLnews_data目录说明爬虫不是只在内存里跑一圈而是会把原始数据落盘。再加上environment.yml里锁定的数据分析、自然语言处理类依赖整套系统就是“Flask 做壳、MySQL 做存储、爬虫做采集、NLP 做分析”的经典组合。选 Flask 而不是 Django对这个场景是合理的。项目核心是舆情分析和股票数据展示不是内容管理Flask 的轻量路由和自由目录结构能让每个模块独立成文件调试时只需要盯着一个函数看。MySQL 则是课程设计的“安全牌”导师评审时看到明确的建库脚本和初始数据比 SQLite 显得完整得多。这套组合很适合做演示页面能交互数据库能查数据爬虫能实时更新每个环节都有可见的产物。2.2 舆情数据采集链路news_data 目录承担的角色采集链路是这套系统里最容易被忽略、但最值得拆开看的部分。很多初学者写爬虫习惯抓一条处理一条直接入库这个项目却先把数据落到news_data目录再做后续清洗。这个设计有两个实际好处一是爬虫目标网站的页面结构经常调整选择器失效是常事原始数据落盘后可以反复调试解析逻辑不用每次重新请求二是导师检查时能看到真实的舆情样本而不是只有数据库里加工后的结果。具体流程是爬虫按股票名称或行业关键词抓取新闻标题和正文经过简单去重和清洗后写入本地文件再由service层的分析模块读取。这样做还有个隐藏优点——如果当天采集失败系统还能用历史落盘数据兜底跑通演示不会被现场反爬搞得下不来台。2.3 股价数据与舆情数据如何对齐代码关联与时间对齐舆情数据和股票价格数据天然存在对齐难题。新闻里很少直接写股票代码比如一条标题为“某公司发布业绩预增公告”的新闻正文里出现的通常是公司简称而不是六位代码所以采集时必须维护一张“公司简称 - 股票代码”的映射表按关键词匹配后手动绑定。另一个问题是时间对齐当天的舆情影响的是当天还是后面几天的股价没有定论所以系统在做相关性分析时会按 T 日舆情、T1 或 T2 日价格的方式做滞后对比。这个设计说明作者不只是在做展示而是认真考虑了金融数据的时序特性。你在复现时可以把时间窗口参数单独拎出来调后面第 6 章会讲具体怎么验证滞后效果。3. 本地部署与运行从 environment.yml 到页面出来的完整路径这个项目能不能跑起来九成卡在环境和数据库两步。源码本身不太可能出错——毕竟经过调试和评审但每个人的本机环境不一样最容易翻车的恰恰是版本、编码、端口这类“边角料”。下面按我实际复现的顺序走一遍。3.1 用 environment.yml 重建虚拟环境压缩包里的environment.yml是这个项目最友好的部分它把 Python 版本和主要依赖一次性锁好。打开命令行切到项目根目录conda env create -f environment.yml conda activate stocksystem第一条命令会按照 yml 文件里的依赖列表创建虚拟环境第二条命令激活它。需要注意如果 yml 里锁定的 Python 版本和你本机 conda 默认源不匹配创建可能失败报错信息通常指向某一个具体包下载不了。常见做法是先把 yml 里的 Python 版本号改成你本机已有的版本比如 3.9 到 3.11 之间再重新执行如果 conda 装到一半中断也不用重复跑整条命令改用pip install把缺的包补上即可。这个文件本身值得你多看一眼。它能告诉你这套系统的技术栈底线明确写了flask、pandas、requests、pymysql说明 Web 框架、数据处理、HTTP 请求、数据库驱动四个方向都有覆盖如果里面还有自然语言处理相关的库那对应的就是 4.2 节的情感分析环节。后续你想给它加功能第一件事就是往这个文件里补依赖。3.2 MySQL 初始化建库脚本与业务数据导入数据库初始化是最容易顺序搞反的一步。压缩包里给了两个 SQL 文件database.sql和stocksystem0107.sql。我的习惯是先打开database.sql看开头有没有CREATE DATABASE语句有就先执行它建库建表再导入业务数据如果database.sql只包含表结构那stocksystem0107.sql里大概率自带建库语句。命令行操作如下mysql -u root -p database.sql mysql -u root -p stocksystem0107.sql导入完成后进 MySQL 检查一下表数量和关键表的数据行数确认不是空库。这里有两个实用细节一是 MySQL 版本最好在 5.7 以上否则某些字段类型或字符集设置可能不兼容二是连接字符集务必用utf8mb4下面的 config 配置里会体现否则舆情数据里的中文和表情符号入库后就是乱码。这个项目的数据质量比一般大作业强的地方在于业务库里预置了新闻样本和股票历史行情导入完成后不用等爬虫跑完就能看到页面效果这对答辩演示很重要。3.3 config.py 连接配置与启动应用config.py是所有配置的集中地。数据库账号密码、密钥、连接参数都在这里不把它改对app.py一启动就会报数据库连接错误。核心配置段一般长这样# config.py 核心配置段按本机环境修改后即可用 import os class Config: # Flask 会话密钥生产环境务必替换 SECRET_KEY os.getenv(SECRET_KEY, dev-only-key) # MySQL 连接参数 HOST 127.0.0.1 PORT 3306 USER root PASSWORD 改成你自己的密码 # 本地 MySQL 密码 DB stocksystem # SQLAlchemy 连接串charsetutf8mb4 保证中文不乱码 SQLALCHEMY_DATABASE_URI ( fmysqlpymysql://{USER}:{PASSWORD}{HOST}:{PORT}/{DB} ?charsetutf8mb4 ) SQLALCHEMY_TRACK_MODIFICATIONS Falsemysqlpymysql表示用 PyMySQL 驱动连接 MySQL这是 Flask 项目里最常见的组合。charsetutf8mb4这一行必须保留舆情新闻里经常出现特殊符号和中文标点只用默认的utf8在部分 MySQL 版本上会报编码错误。SECRET_KEY是 Flask 的会话签名密钥本地调试用默认值没问题如果要部署到公网必须改成随机字符串。连接配置改完之后启动应用python app.py看到启动日志里出现Running on http://127.0.0.1:5000浏览器打开这个地址就能进入系统界面。如果端口被占用可以在启动命令里指定python app.py --host 0.0.0.0 --port 50010.0.0.0表示允许局域网内其他机器访问方便演示时让评委用手机或另一台电脑打开页面。这一步能过说明环境、数据库、代码三件事都通了。4. 舆情采集与情感分析把新闻变成情绪分数的实现细节系统最核心的价值不在 Web 界面而在“新闻怎么变成分数”。这个环节拆开看是三个步骤爬虫把新闻抓回来情感分析模块把文本转成分数最后再把分数和股票代码绑定。每一步都有值得记录的工程细节。4.1 爬虫模块按关键词抓取新闻并落盘news_data目录和采集模块承担的是数据入口。爬虫的设计思路是按股票名称、公司简称和行业关键词构造搜索 URL抓取标题和正文清洗后写入本地。一个典型的采集函数如下# crawler.py —— 按关键词抓取新闻标题与正文落到 news_data 目录 import requests import time from bs4 import BeautifulSoup from datetime import datetime HEADERS { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } def fetch_news(keyword: str, pages: int 3): results [] for page in range(1, pages 1): # 以关键词和页码构造检索地址选择器按目标站实际结构调整 url fhttps://search.example.com/news?q{keyword}p{page} try: resp requests.get(url, headersHEADERS, timeout10) resp.encoding utf-8 soup BeautifulSoup(resp.text, html.parser) # 常见的新闻列表结构外层 .news-item内部 .title 和 .content for item in soup.select(.news-item): title item.select_one(.title).get_text(stripTrue) content item.select_one(.content).get_text(stripTrue) results.append({ title: title, content: content, keyword: keyword, crawled_at: datetime.now().strftime(%Y-%m-%d %H:%M:%S) }) except requests.RequestException as e: print(f第 {page} 页抓取失败: {e}) time.sleep(1) # 限速避免高频请求触发反爬 return results代码逻辑是循环翻页每页解析新闻列表把标题、正文、关键词和时间组装成字典。参数里值得注意的有三个pages3控制抓取深度调成 5 会多抓两页但对时效性新闻差别不大timeout10是请求超时阈值目标网站响应慢或连接被重置时不会卡死整个脚本time.sleep(1)是限速这个数字不能去掉否则高频请求很快会触发反爬机制。爬虫跑完之后原始结果建议用 pandas 或 json 落盘到news_data目录再走清洗入库流程。这里有一个实践经验不要把“抓取”和“入库”写在同一个循环里抓取时只做采集入库前单独做去重和字段校验这样哪一步出错都只影响局部。4.2 情感分析基于金融词典的情绪打分文本情感分析是这个项目里最容易被导师追问的地方。常见的实现路线有两条一是用开源库如 SnowNLP 直接读文本出情感分二是自己做词典打分。这个项目更适合词典法因为 SnowNLP 的默认语料来自电商评论对金融文本的“利好、利空、增持、减持”这类词汇敏感度很差硬用会得出“业绩暴雷”是正面情感的荒谬结果。词典法实现简单、可解释性强答辩时也讲得清楚# sentiment.py —— 基于金融词典的情绪打分返回 0~1 之间的分数 import jieba # 金融领域词典按实际业务持续扩充 POSITIVE_WORDS {利好, 涨停, 增长, 盈利, 突破, 增持, 回购} NEGATIVE_WORDS {利空, 跌停, 下滑, 亏损, 违规, 减持, 退市, 调查} def score_text(text: str) - float: # jieba 分词后统计正负向词出现次数 words jieba.lcut(text) pos sum(1 for w in words if w in POSITIVE_WORDS) neg sum(1 for w in words if w in NEGATIVE_WORDS) total pos neg if total 0: return 0.5 # 没有命中的情感词判为中性 return round(pos / total, 4)这里的核心逻辑是分词后统计正向词和负向词的出现次数用正向占比作为情感分数。分数范围是 0 到 1大于 0.6 偏积极小于 0.4 偏消极0.5 是中性。jieba.lcut(text)返回分词列表这一步是词典法的基础两个词典集合是这套系统的“灵魂”你现在看到的正反向词条非常少实际工程里要扩充到几百个词才能覆盖足够多的新闻场景。这个实现有个明显的好处每一条新闻的打分依据都可以溯源导师问“为什么这条新闻是 0.8 分”你可以直接说是命中了“增长”和“盈利”两个正向词。换成深度学习模型反而很难解释。代价就是阈值敏感词典覆盖不全时中性判断会偏多所以第 5 章会专门讲怎么调这块。4.3 情感分数与股票代码的绑定策略情感分数算出来了还要和股票关联上。前面 2.3 节说过新闻里通常只有公司简称所以系统维护了一张映射关系把“公司简称、行业关键词”映射到股票代码。绑定流程是先对新闻正文做关键词匹配命中简称就绑定代码再按新闻发布时间归入对应的交易日。当天所有新闻的分数做加权平均得到这只股票当日的“舆情情绪指数”。这个指数的计算通常在service层完成核心逻辑就是按代码和日期分组聚合# service 层聚合逻辑示意按股票代码和日期求情感均值 import pandas as pd def daily_sentiment(news_df: pd.DataFrame) - pd.DataFrame: # 先按代码分组再按日期分组取情感分数的均值作为当日舆情指数 grouped ( news_df.groupby([stock_code, date])[sentiment_score] .mean() .reset_index() ) return grouped.rename(columns{sentiment_score: sentiment_index})groupby([stock_code, date])是先按股票代码聚合再按日期聚合两层维度缺一不可——只按日期会混淆多只股票只按代码会把不同日期的舆情混在一起。mean()是聚合方式也可以换成带权重的加权平均比如标题情感权重高、正文情感权重低。实际操作中我发现标题的权重应该比正文大因为标题是编辑提炼过的核心信息。5. 常见问题与避坑环境、采集、分析三个环节的翻车现场这个项目我前后复现了两轮第一次卡在环境第二次卡在数据为空。下面五条是踩过最深的坑按“现象 - 原因 - 处理”的顺序写你可以直接对照排查。5.1 conda 环境创建中断与 Python 版本错位现象是执行conda env create -f environment.yml时依赖装到一半提示找不到某个包或者 Python 版本解析失败整个环境建到一半就停了。原因是environment.yml里锁的 Python 版本可能在本机 conda 源里没有对应安装包尤其是跨小版本的组合比如锁了 3.8 但本机默认源只更新到 3.11解析时就断了。处理方法是打开environment.yml把 python 那行的版本号改成你本机已有的版本再重新执行创建命令如果只是个别包失败更快的做法是先把环境建出来再用pip install手动补缺失的包不用重跑整个 yml。从那以后我每次拿到新项目第一件事是先看 yml 里锁的 Python 版本而不是直接执行命令。5.2 SQL 导入后中文乱码或表结构缺失现象是 SQL 文件导入成功但页面查询出来的新闻标题全是“???”或者直接报“Table doesnt exist”。原因是字符集不匹配或者两个 SQL 文件的导入顺序反了。database.sql如果包含建库语句必须先执行它如果先导入了stocksystem0107.sql里面引用的表还没建出来自然报表不存在。乱码问题则几乎都是连接字符集不是utf8mb4造成的检查 config.py 里的连接串末尾有没有?charsetutf8mb4。处理方法是先确认两个 SQL 文件的导入顺序再用命令行登录 MySQL 查看SHOW CREATE TABLE的建表语句确认表定义里的DEFAULT CHARSET也是utf8mb4必要时手动ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4修复存量数据。5.3 爬虫抓回来的结果是空列表现象是爬虫脚本跑完没有任何报错但results列表长度是 0news_data目录里也没有新文件。原因是目标网站的页面结构变了代码里写的选择器select(.news-item)匹配不到任何元素或者网站返回了验证码页面resp.status_code是 200 但内容里没有新闻。处理方法是先打印resp.text[:500]看返回内容是不是正常 HTML如果是一段包含“验证”字样的脚本就是反爬拦截了如果页面结构变了用浏览器开发者工具重新定位新闻列表的 class 名改掉选择器。另外不要忽略time.sleep(1)这行限速去掉之后高频请求会在几分钟内被封。演示前如果实在抓不到实时数据就用news_data里的历史数据跑通流程这个项目设计时就留了这条后路。5.4 情感分析结果像“玄学”正面新闻打出低分现象是一条标题为“某公司签署重大合同”的新闻情感分析给出的分数只有 0.3明显与语义相反。原因是词典法只认词表里的词“签署”“重大”“合同”都不在正向词典里而正文里如果出现“风险提示”或“违规”负向词先命中了分数就被拉低。这本质上是词典覆盖不足和权重设计过于简单的问题。处理方法是扩充词典把“签署”“中标”“合同”“战略合作”“超预期”加进正向词表把“问询”“监管”“冻结”加进负向词表同时给标题里的情感词加 1.5 倍权重因为标题比正文更能代表新闻基调。做这一步时我一般会把历史新闻跑一遍把分数在 0.4 到 0.6 之间的样本抽出来人工看一眼找出漏掉的词条。5.5 页面能打开但图表数据为空现象是最难排查的一种Flask 服务正常启动页面渲染出来但图表区域是空的控制台也没有报错。原因是查询条件不匹配页面默认查的是“当天的舆情数据”但数据库里预置的数据日期不是今天或者默认股票代码和库里预置的不一致SQL 查询结果为空前端图表自然画不出东西。处理方法是打开数据库直接查SELECT DISTINCT stock_code, date FROM sentiment_daily看库里实际有哪些代码和日期范围然后在页面上选择库里真实存在的数据如果前端传参格式跟后端不匹配比如日期传成了2025-01-07而后端期望的是20250107也会查不到结果。这个坑的教训是页面空白时不要先怀疑前端代码先看后端接口返回的 JSON 是不是空数组。6. 进阶验证与延伸把情感指数和 K 线对齐到这里系统已经能跑通了但如果你只想让它停留在“能演示”的程度那还不够。导师追问频率最高的一个问题会是“你怎么证明舆情分析和股价有关系”这一章就把这件事做实——用相关性分析验证情感指数与股价是否存在统计意义上的关联。6.1 计算情感指数与收盘价的相关系数系统里已经有了每日情感指数和股票历史价格接下来要做的是把两张表按日期对齐算相关系数和滞后相关性# validate.py —— 验证舆情情感指数与股价的相关性 import pandas as pd # 情感指数表date, stock_code, sentiment_index sentiment pd.read_csv(sentiment_daily.csv, parse_dates[date]) # 股价表date, stock_code, close price pd.read_csv(price_daily.csv, parse_dates[date]) merged pd.merge( sentiment, price, on[date, stock_code], howinner ) # 当日相关性 corr_t0 merged[sentiment_index].corr(merged[close]) print(f当日相关系数: {corr_t0:.4f}) # 滞后 1~5 天的相关性T 日舆情对 TN 日收盘价的影响 for lag in range(1, 6): merged[sentiment_lag] merged[sentiment_index].shift(lag) corr_lag merged[sentiment_lag].corr(merged[close]) print(f滞后 {lag} 天: {corr_lag:.4f})pd.merge是按日期和股票代码把两张表对齐howinner表示只保留两边都有的日期避免空值影响相关系数。shift(lag)是滞后操作把情感指数整体往后移 N 行模拟“今天的情感影响 N 天后的股价”。实际跑出来的结果里当日相关系数如果偏低是正常的金融市场的反应本来就存在滞后滞后 1 到 3 天的相关性如果明显高于当日说明这套系统抓到了舆情扩散的节奏这就是你项目里的核心亮点。6.2 把验证脚本变成日常习惯相关系数算完之后我把这个验证脚本固化成了一个习惯动作每次修改情感词典或爬虫策略第一件事就是跑一遍当天数据的相关性看分数是变好还是变差。如果滞后 1 天的相关性明显提升说明新词典有效如果分数反而下降就得回退改动。从那以后我每次拿到这类舆情分析项目都强制自己先走一遍“采集 - 打分 - 对齐股价 - 算相关性”的完整闭环而不是只看页面能不能打开——数据流水线的价值在验证里不在界面上。希望这些拆解能帮到你祝顺利跑通。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑