股票资讯聚合系统开发:行情API、爬虫与定时任务全解析
2026/9/24 19:56:10 网站建设 项目流程

如果你拿到的是《查询股票信息与新闻系统》这种毕设题目,心里多半会犯嘀咕:行情数据从哪来?新闻怎么自动抓到?系统要做到什么程度才算合格?我当初做同类项目时也一步步踩过这些坑。把这个题目拆开看,本质就是一个带用户体系的行业信息聚合Web应用:左边是股票行情数据,右边是新闻资讯流,中间用数据库和定时任务把它们串起来。这类题目的好处是技术栈非常完整,前后端交互、HTTP请求、数据解析、爬虫、定时任务、数据库建模全都能涉及,而且数据源可以用公开免费接口,不碰交易和资金安全,非常适合做毕设。

这篇文章会直接给你一条从需求拆解、技术选型到核心实现、答辩准备的完整链路。不管你是准备从头写,还是手里已经有一套“附源码58899”的工程但完全看不懂,都能照着这份思路把它落地、讲清楚。

1. 先看懂这个毕设题目的本质

1.1 选题的隐藏考点

很多同学看到“股票”两个字就发怵,觉得金融类项目离自己太远。实际上这个题目考察的根本不是金融知识,而是三件事:你能不能稳定地拿到外部数据,能不能把数据处理后展示出来,能不能用工程手段让整个系统跑得顺畅。

“查询股票信息”考察的是HTTP请求、JSON/GBK解析、K线数据结构化处理;“新闻系统”考察的是爬虫采集、去重、文本存储和关键词匹配;“系统”两个字则暗示你要有完整的用户体系、数据库设计和前后端联动。把这个逻辑想明白,你会发现它和“天气查询系统”“电影资讯系统”没有任何本质区别,只是数据源不同。

1.2 功能拆解与模块划分

我习惯先列功能清单再写代码。一个能顺利通过答辩的版本,至少应该有下面这些模块:

功能模块核心内容技术要点
用户注册登录账号注册、登录、退出Session或JWT、密码加密
股票查询输入代码或名称查看实时行情HTTP请求、字段解析
K线展示日K、周K、月K图ECharts图表组件
股票列表按涨跌幅、成交额排行列表接口、分页展示
新闻聚合股票相关新闻抓取与展示爬虫、去重、入库
自选股管理添加删除自选股关联表设计、增删查
定时刷新缓存行情数据APScheduler或@Scheduled

很多二次开发的源码包其实只有前两个功能,后面几个模块是缺失的,这就给了你很大的提升空间。我建议你把“个股新闻”和“自选股”这两个模块重点补强,因为它们是评分老师最容易看出来你花过心思的地方。

2. 技术选型与总体架构:别上来就写代码

2.1 后端框架:Spring Boot 还是 Flask

这是每个做毕设的同学都要纠结的问题。我的建议很简单:看你们小组的教学主语言。学校一直用Java讲SSM、Spring Boot,那就老老实实用Java,答辩时老师问框架细节,你能对答如流。如果Java学得一般,Python的Flask确实上手更快,一个文件就能起服务,也方便后期加爬虫逻辑。

拿Spring Boot举例,我建议用经典的Controller-Service-Mapper三层结构,再加一个ScheduledTask做定时任务,一个HttpUtil封装对外请求。Python方案则用Flask蓝图拆成authstocknewswatchlist几个模块。无论哪种,一定要让包结构看得懂,这比用什么框架重要得多。

2.2 前端方案:别整花活,稳定最重要

前端部分最稳妥的组合是Bootstrap加jQuery,或者Vue3加Element Plus。选Bootstrap的好处是页面不改也能看,适合时间紧张的同学;选Vue3则方便用ECharts做图表,K线交互会更流畅。

K线图直接用ECharts的candlestick系列,不用自己画坐标轴,把数据组装成[日期, 开, 收, 低, 高]传进去就行。需要提醒的是,ECharts体积不小,用npm按需引入,不要全量打包,不然首屏加载会很慢。

2.3 数据库表结构设计

毕设系统不需要复杂表,四张表足够:用户表、股票基础信息表、自选股表、新闻表。设计时抓住几个关键点。

用户表必须有salt字段配合密码加密,不能用明文。股票基础信息表存代码、名称、交易所、行业,插入一次基本不再变动。自选股表用user_id + stock_code做联合唯一索引,防止同一用户重复添加同一只股票。新闻表的核心字段是标题、来源、链接、发布时间,并且给标题列加唯一索引或存一个title_hash,这是后面做去重的基础。

CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, salt VARCHAR(32) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP );

股票代码的存储我建议直接用varchar(10),格式统一成sh600000sz000001这种带交易所前缀的形式。这样后面调用行情接口时可以直接拼URL,省去判断沪市深市的麻烦。

2.4 行情与新闻数据源怎么选

这是整个项目最容易卡住的地方。很多同学一上来就去找付费金融数据库,其实完全没必要。目前免费的方案有三种,实测都稳定。

新浪行情接口返回字段最全,但要求请求头带Referer,编码是GBK。腾讯行情接口速度稍快,但字段顺序需要自己认真数。东方财富接口适合拿K线历史数据,参数丰富,返回JSON,解析最简单。

新闻数据相对麻烦一点。可以用东方财富的个股新闻接口,也可以直接爬新浪财经的新闻列表页,用BeautifulSoup解析<a>标签里的标题和链接。如果你所在学校对实时性要求不高,更省事的方案是用第三方免费新闻API,申请一个key就能用,缺点是覆盖面和字段有限制。

3. 核心功能实现拆解

3.1 实时行情查询:一个请求解析出现价涨跌

行情接口看起来神秘,拆开就是一个普通HTTP请求。我用新浪接口给你演示最核心的解析逻辑:

import requests def get_stock(code): url = f"https://hq.sinajs.cn/list={code}" headers = { "Referer": "https://finance.sina.com.cn", "User-Agent": "Mozilla/5.0" } resp = requests.get(url, headers=headers) resp.encoding = "gbk" line = resp.text.split('"')[1] fields = line.split(',') return { "name": fields[0], "open": float(fields[1]), "pre_close": float(fields[2]), "price": float(fields[3]), "high": float(fields[4]), "low": float(fields[5]), "volume": int(fields[8]), "amount": float(fields[9]) }

这里有两个非常关键的细节。第一,新浪接口不带头Referer直接返回403,这是反爬基本手段。第二,接口返回的是GBK编码,如果你用默认UTF-8解析,中文名称和部分字段会乱码。我在第一次调试时就因为这两点浪费了两个小时。

拿到字段后,涨跌幅和涨跌额推荐在后端算好再传给前端。因为前端只需要显示,把计算逻辑放在后端,接口数据更干净,也方便以后做排行榜排序。

3.2 K线数据获取与ECharts绘图

K线数据我推荐用东方财富的接口,因为它返回的就是标准JSON,省去大量解析工作。请求格式大致如下:

https://push2his.eastmoney.com/api/qt/stock/kline/get ?secid=1.600000 &fields1=f1,f2,f3,f4,f5 &fields2=f51,f52,f53,f54,f55,f56,f57 &klt=101 &fqt=1 &beg=20230101 &end=20241231

其中secid规则是沪市以1.开头,深市以0.开头,600000换成你需要查询的股票代码即可。klt=101表示日K,102是周K,103是月K。fields2里的f51到f57分别对应日期、开盘、收盘、最高、最低、成交量、成交额。

后端拿到这些数据后,转成ECharts需要的格式:

// ECharts candlestick 数据格式 const klineData = rawData.map(item => [ item[0], // 日期 item[1], // 开盘价 item[2], // 收盘价 item[3], // 最低价 item[4] // 最高价 ]);

注意ECharts的kline系列要求的是[开盘,收盘,最低,最高]顺序,很多人会不小心按日期、开、高、低、收盘传,结果图形完全不对。如果你想让项目多点技术含量,在此基础上算一个MACD或KDJ指标,做成副图展示,答辩时绝对是个加分项。这类指标计算逻辑可以直接参考开源社区的金融技术指标库,不用自己从头推导公式。

3.3 新闻聚合:抓取、去重、入库一套带走

新闻模块的难点不在爬虫本身,而在怎么保证数据不脏、不重复。最早我做的时候图省事,每次页面加载都直接爬一次新闻源,结果接口被限流,页面加载还慢。后来改成定时任务抓取加数据库去重,才解决问题。

抓取用最简单的requests加BeautifulSoup即可:

from bs4 import BeautifulSoup import requests def crawl_news(keyword): url = f"https://finance.sina.com.cn/roll/index.d.html" headers = {"User-Agent": "Mozilla/5.0"} html = requests.get(url, headers=headers).text soup = BeautifulSoup(html, "html.parser") items = soup.select(".list_009 a") # 根据实际页面结构调整 for item in items[:20]: title = item.get_text(strip=True) link = item.get("href") # 入库前先算标题哈希 yield title, link

去重逻辑我在入库前对标题做了一次MD5,生成title_hash字段,数据库里加唯一索引。插入时用INSERT IGNORE,重复的标题直接跳过,这样爬虫写多简单都不会产生重复数据。如果你还想做关键词匹配,可以给新闻表加一个industrytags字段,保存抓取时携带的行业分类,方便前端按板块过滤。

3.4 用户登录与自选股:关联表是核心

用户模块直接用框架自带方案最省事。Java的Spring Security可能配置略重,建议直接用JWT或者简单的Session拦截器。Python方案用Flask-Login或者手动写登录装饰器都可以。

自选股表的本质是用户与股票的多对多关系,核心字段只有三个:

CREATE TABLE watchlist ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, stock_code VARCHAR(10) NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_user_stock (user_id, stock_code) );

添加自选股时先查一次这个联合唯一索引,返回冲突就提示用户已经添加过。删除自选股时需要注意,前端表格传过来的可能是多个股票代码,建议后端接收逗号分隔的字符串,然后在SQL里用IN批量删除。这个细节能在并发操作时明显减少数据库压力,实际体验也比一条条删顺畅很多。

3.5 定时任务与缓存:不要让用户请求打到外部接口

行情接口虽然免费,但不代表没有频率限制。我做压力测试时发现,如果每个用户刷新页面都实时请求新浪接口,几十个并发就会触发风控,导致IP被临时限制。解决方案很简单:加一层缓存。

后台起一个定时任务,每3分钟把自选股列表里涉及的行情数据批量刷新到内存缓存或Redis。用户查询时直接读缓存,只有缓存过期或首次查询时才会回源请求外部接口。Python写法可以这样:

from apscheduler.schedulers.background import BackgroundScheduler def refresh_stock_cache(): codes = get_all_watchlist_codes() for code in codes: stock_cache[code] = get_stock(code) print(f"缓存已刷新,共 {len(codes)} 只股票") scheduler = BackgroundScheduler() scheduler.add_job(refresh_stock_cache, "interval", minutes=3) scheduler.start()

Java的Spring Boot也差不多,在启动类上加上@EnableScheduling,然后在方法上写@Scheduled(cron = "0 */3 * * * ?")就可以。这一步在很多源码包里是缺失的,自己补上以后,性能上和答辩故事上都好讲很多。

4. 常见问题与排查技巧实录

4.1 高频报错与解决方案

这个项目我刚做完时遇到过一堆问题,后来整理了一张速查表,基本覆盖了毕设阶段的常见坑:

现象原因解决办法
新浪行情接口返回403缺少Referer头请求头添加Referer: https://finance.sina.com.cn
解析出的中文乱码接口是GBK编码设置resp.encoding = "gbk"
股票代码无法区分市场sh/sz/bj前缀写错维护一只股票所属交易所的表,拼接前缀
请求一多就超时接口限流定时任务加缓存,每只股票间隔0.3秒以上
新闻数据重复多来源抓取未去重标题MD5加唯一索引
K线图显示空白数据格式顺序不对确认传入顺序为开盘、收盘、最低、最高

这里再提一个容易被忽视的问题:学生机房出口IP经常是共享的,同一时间多个人访问同一个行情接口,很容易被一起封禁。我建议开发调试时尽量用本地测试数据,部署演示时才让系统真正请求外部接口。

4.2 答辩演示的黄金节奏

毕设答辩时间通常只有10到15分钟,演示顺序不对,很可能核心功能还没展示完就被叫停。我推荐的演示脚本是:注册新账号(体现用户体系完整)→ 在搜索框输入股票代码(体现查询核心功能)→ 切到自选股页面展示添加和删除(体现关联表操作)→ 打开个股K线图(体现数据可视化)→ 展示新闻列表(体现爬虫模块)→ 最后停在定时任务日志页面,让老师看到系统是自动刷新的。

前三个步骤控制在3分钟以内,后面给新闻和定时任务留足时间。老师最关心的是“数据来源是否可靠”和“系统是不是你自己写的”,所以每个环节都要准备一句话解释数据从哪来、缓存策略是什么。如果老师追问“系统崩溃了怎么办”,你就说核心数据有MySQL落地,外部接口失败时有缓存兜底,做到这一层就已经超过大多数同学了。

4.3 源码管理与文档规范

很多同学拿到源码包第一件事就是解压跑通,然后把readme.md删掉直接改名字提交,这是非常危险的。我见过太多人因为源码包里的数据库脚本和自己的配置对不上,导致运行失败。正确的做法是:先建一个干净的Git仓库,把源码包作为初始提交,然后逐步修改代码并留下清晰的commit记录。这样既能体现工作量,也能在源码出现诡异bug时随时回退。

文档方面,README至少写清楚四部分:项目简介、环境要求、启动步骤、功能说明。数据库初始化SQL一定要单独放一个.sql文件,并且带上测试数据。启动步骤要用步骤列表写清楚,而不是一句话带过。答辩演示时电脑上最好提前准备好完整的运行环境,不要现场临时装依赖,网络一波动非常尴尬。

5. 一些能让你项目更出彩的想法

5.1 低成本扩展方向:指标计算、股票筛选、新闻分析

基础功能做完以后,如果想往高分冲一冲,我不建议加一些看起来很炫但根本讲不清楚的功能,比如机器学习预测股价或实时期货数据。性价比最高的三个扩展方向是技术指标计算、条件筛选器和新闻情感分析。

技术指标计算就是自己实现MACD、KDJ、RSI这类常见指标,算完在K线图下方用折线图展示。条件筛选器可以做一个简单的表单,让用户输入涨跌幅区间、成交量下限,后端用SQL或内存过滤返回结果。新闻情感分析更简单,准备一个包含积极词和消极词的词典,对新闻标题分词后打分,给每条新闻标一个正面、中性、负面的标签。这三个方向都不需要额外依赖,工作量可控,而且每一个都能在答辩时展开讲至少两分钟。

5.2 拿到源码包之后,怎么把它变成自己的东西

如果你手里已经有一套“毕设附源码58899”这种工程,第一步是先把它跑起来,理解启动脚本、数据库配置、第三方接口这三个入口。第二步画一张架构图,标出哪些是现成的、哪些是查不到文档的死代码。第三步就是动手改,随便挑一个页面,比如把行情表格加一列“换手率”,或者把新闻列表改成卡片风格,这个过程中你会被迫读懂一半代码。

我个人的经验是,不要急着把所有功能都重写,那样容易把整个项目改挂。保留核心框架,在边角功能上做增量修改,既能保证演示稳定,又能让你在答辩时说出“这块是我加的”“那块的逻辑我优化过”。就算老师问到底层实现,你也有真实经验可讲,而不是背别人的代码。

这个项目做下来,最有价值的地方恰恰是那几次调试失败的过程。第一次被接口403拦截,第一次K线图渲染成空白,第一次数据库出现重复数据,每一次踩坑都会让你对系统整体设计有更深的理解。所以如果你正在为这个题目发愁,不用怕,把一个模块一个模块拆开做,最后你会发现它只是你熟悉HTTP、爬虫和数据库设计的一个载体而已。

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

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

立即咨询