☰
文本分析驱动的新闻推荐系统:从中文分词到个性化推荐实践
2026/10/20 12:20:30 网站建设 项目流程

每年到毕业设计选题季,就会有一批同学盯着“文本分析的新闻推荐的设计与实现”这个题目反复纠结。这个项目编号77053,听起来像是带点算法门槛的“硬核毕设”,实际拆开看,它本质上就是把中文分词、关键词提取、相似度计算这些自然语言处理基础操作,和一套最简单的推荐逻辑拼在一起,再套上一个Web系统壳子。难度比纯管理系统高一些,但比深度学习类项目友好得多,很适合计算机、软件工程、大数据方向的同学做综合训练。

我当年带过好几个做类似题目的学生,也亲手把整套流程从零跑通过。这篇文章不做任何“成品”“定制”层面的讨论,只讲一个核心问题:如果你自己动手做,怎么把这个系统设计出来、代码怎么写、坑怎么避。全文按实际开发顺序展开,从需求拆解到算法实现,再到联调测试和扩展方向,尽量做到你照着写也能跑通。

1. 项目需求拆解:先搞清这个题目到底要做什么

1.1 别急着写代码,先把功能清单列清楚

很多同学拿到题目第一反应就是打开搜索引擎找参考代码,结果看了一堆名词:TF-IDF、Word2Vec、协同过滤、用户画像,越看越慌。我建议先关掉代码,拿一张纸把“这个系统最终给谁用、用的时候要看到什么”写清楚。

基于“文本分析的新闻推荐”这个核心,功能需求最少要覆盖两条线。用户侧:注册登录、浏览新闻列表、查看新闻详情、对新闻点赞或标记不感兴趣、查看系统为自己生成的个性化推荐列表。管理侧:新闻数据的录入与管理、用户管理、文本分析结果展示。这里的“文本分析结果”是题目拿分的重点,不能只是后台算完藏在数据库里,要在页面或接口里明确展示出:新闻的关键词、所属主题、情感倾向、推荐理由。

我习惯把功能拆成下面这张表,照着做不会漏:

模块功能点说明
用户模块注册、登录、个人信息用Session或Token做状态管理即可
新闻模块新闻列表、详情、分类筛选数据可来自爬虫或手工录入
文本分析模块分词、关键词提取、主题分类、情感分析这是系统的核心亮点
推荐模块用户画像生成、候选新闻召回、排序推荐基于文本相似度实现
行为反馈模块点赞、不感兴趣、阅读记录行为数据会反哺用户画像
后台管理新闻管理、用户管理、分析结果查看可选,但建议保留

在项目文档里,你不能只写“实现了一个推荐系统”,要把每个模块和题目里的“文本分析”建立对应关系。比如推荐模块的数据输入是文本分析产出的关键词向量,而不是原始的新闻字符串,这就是“基于文本分析的新闻推荐”和普通“新闻列表展示系统”的最大区别。

1.2 为什么新闻推荐要“文本分析”,而不是上来就推荐

新闻领域有个特点:用户几乎没有评分行为,点开一篇新闻后很少会打分。传统协同过滤算法要依赖“用户-物品”评分矩阵,在新闻场景下矩阵极度稀疏,基本算不出可靠结果。所以现实中新闻推荐普遍采用基于内容的思路:先分析新闻文本本身,提取关键词、主题、实体,再和用户的兴趣画像匹配。

另外一个重要原因是可解释性。你在答辩时老师大概率会问“你凭什么给这个用户推荐这条新闻”。如果你的回答是“我们通过文本分析提取出这条新闻的关键词是‘芯片、半导体、产业’,用户之前阅读的三条新闻里都有这些关键词,所以推荐”,这个回答远比“因为协同过滤说像”更有说服力。文本分析让推荐结果有据可查,这是这个题目最大的优势。

基于内容的推荐还有一个隐藏好处:冷启动相对容易。协同过滤面对新新闻或者新用户直接失效,而基于内容的推荐只需要做一次文本分析、提取出特征,就能参与推荐。这对毕设来说非常友好,不需要造一个很大的用户行为数据集来喂算法。

1.3 项目边界和验收标准要提前定好

毕设最怕的是“什么都想做,最后什么都没做完”。做这个项目前,建议把边界画死。数据规模不用大,几百篇经过清洗的新闻就足够展示效果;推荐方式以离线计算为主,把推荐结果生成好存进数据库即可,不要一上来就碰Spark、Flink那套实时流计算;算法模型用经典统计方法就行,不需要上BERT这类动辄几G的预训练模型,除非你的机器带得动并且自己有足够时间调参。

验收标准建议定成三条硬指标:第一,用户浏览至少三篇新闻后,推荐列表里能出现和这三篇主题明显相关的新闻;第二,文本分析模块能输出关键词、分类、情感标签,并且页面能看到;第三,推荐过程可解释,能指出推荐结果是由哪些关键词触发的。三条都达标,说明核心算法逻辑已经通了,论文和答辩材料也就有实实在在的内容可写了。

2. 技术选型与系统架构设计

2.1 后端语言和框架怎么选:Python 是首选

这个题目最终形态通常是一个Web系统加算法模块。我强烈建议后端主体用Python,原因是中文文本分析相关的库几乎全是Python生态的,用Java不是不行,但光是分词和向量化就会费力很多。

Python生态里最常用的一套组合是:Flask或Django做Web框架,jieba做中文分词,scikit-learn做TF-IDF向量化和余弦相似度计算,SQLite或MySQL做数据存储。Flask足够轻量,适合毕设这种中小型项目,接口返回JSON,配合Vue、Layui或者小程序前端都非常顺手。如果你熟悉Java,Spring Boot加HanLP也可以做,但代码量和配置成本明显更高。至于PHP,做管理后台还行,做文本分析就很别扭,不建议选。

有同学问小程序能不能做前端,可以。小程序只负责页面展示和请求接口,所有文本分析、推荐计算都在后端完成。这也符合题目中“小程序”关键词的定位,相当于把前端从PC网页扩展到了移动端,架构上不会增加太多复杂度。

2.2 文本分析的核心流程:从一行新闻文本到特征向量

一次完整的文本分析流程,我在项目里是分四步走的。

第一步是清洗。新闻文本可能包含HTML标签、多余空白、特殊符号、和内容无关的编辑署名。先用正则表达式把标签和噪声字符去掉,再过滤掉长度过短的无效文本。

第二步是分词。英文按空格切就好,中文必须靠分词工具。jieba是使用最广泛的工具,它支持精确模式、全模式、搜索引擎模式。毕设场景用精确模式加自定义词典就够了。自定义词典非常重要,新闻里很多专有名词,“神舟”“嫦娥”“ChatGPT”这类词如果不加进词典,分词会被切得乱七八糟,直接影响后续关键词质量。

第三步是停用词过滤。中文里“的、了、是、在、我、你”这类词频很高但没有实际语义,还有“我们、这个、一个”之类的无意义短语,需要维护一个停用词表,在分词后直接过滤掉。这一步没有多少技术含量,但直接影响关键词效果。

第四步是把文本转成向量。推荐系统要计算“两篇新闻像不像”,前提是把新闻表示成数学上可计算的对象。最经典的是TF-IDF向量:先统计每个词在文档中出现的次数(词频),再乘上逆文档频率,削弱“在所有文章里都出现的高频词”的干扰。得到每篇新闻的词权重向量后,用余弦相似度计算两个向量之间的夹角,夹角越小越相似。

公式上,余弦相似度就是两个向量A和B的点积除以各自模长的乘积,取值范围在-1到1之间。文本向量因为TF-IDF权重都非负,所以结果在0到1之间,1代表完全相同,0代表毫无关联。这个计算在scikit-learn里就一行代码,但理解原理对答辩非常有帮助。

2.3 数据库设计和用户画像表结构

数据库是整个系统的地基。我设计表时遵循一个原则:文本分析的结果要落库,不能每次推荐时重新算。

核心表我一般建这几张:用户表存储账号密码和基础信息;新闻表存储标题、正文、发布时间、分类;新闻特征表存储关键词、情感标签、主题分类,或者直接存文本向量;用户行为表存储阅读、点赞、不感兴趣记录;用户画像表存储算法算出的兴趣向量;推荐结果表存储为每个用户生成的推荐新闻列表。其中新闻特征表和用户画像表是这个项目区别于普通管理系统的关键。

以用户行为表为例,字段至少要包括:行为ID、用户ID、新闻ID、行为类型(0浏览、1点赞、2不感兴趣)、行为时间。行为时间不能丢,因为算用户兴趣时要考虑时间衰减,三天前读的新闻和昨天读的新闻,对当前用户的兴趣贡献完全不一样。推荐结果表则要冗余出推荐时间和推荐理由,方便前端直接展示“因为您关注了‘XX’标签,推荐本篇新闻”,也方便答辩时演示。

设计表结构时我踩过一个坑:向量字段类型。一篇新闻的TF-IDF向量维度可能上千,如果你用数据库字段去存这一千个浮点数,建表就会很痛苦。我的做法是向量不直接存数据库,而是用Python脚本离线计算后序列化成numpy文件,数据库只存新闻的关键词文本和分类标签,相似度计算时再临时加载向量文件。这么做既保证了推荐性能,又避免数据库表结构过于复杂。

3. 核心算法实现:文本分析新闻推荐全流程

3.1 新闻文本的向量化:从分词到TF-IDF矩阵

实际动手写代码时,先把所有新闻文本读进来,批量清洗分词,再统一向量化。这里用scikit-learn的TfidfVectorizer非常方便,它内部会自动做词频统计和逆文档频率计算,同时还能过滤掉出现频次过低的词。

import jieba from sklearn.feature_extraction.text import TfidfVectorizer # 自定义词典,提升专有名词识别率 jieba.load_userdict("userdict.txt") # 每行一个词 # 停用词表 stopwords = set() with open("stopwords.txt", "r", encoding="utf-8") as f: for line in f: stopwords.add(line.strip()) def clean_text(text): # 简单清洗:去掉换行和多余空白 text = text.replace("\n", " ").replace("\r", " ") return text.strip() def cut_words(text): text = clean_text(text) words = jieba.cut(text) result = [] for word in words: word = word.strip() if word and word not in stopwords and len(word) > 1: result.append(word) return " ".join(result) # 假设news_list是新闻全文列表 news_cut_list = [cut_words(news) for news in news_list] # TF-IDF向量化 vectorizer = TfidfVectorizer() tfidf_matrix = vectorizer.fit_transform(news_cut_list) # tfidf_matrix的每一行对应一篇新闻的向量

这里有几个容易出现问题的细节。第一,自定义词典文件必须是UTF-8编码,否则jieba加载会报错或乱码。第二,停用词过滤时要保留长度大于1的词,很多单字词单独看没有语义。第三,清洗阶段最好把英文大小写统一转成小写,否则“AI”和“ai”会被当成两个词。

我建议在向量化后保存一份特征词列表,后面解释推荐理由时要用到。用vectorizer.get_feature_names_out()就能拿到所有特征词,向量中每个位置对应的就是一个词。到时候取相似新闻时,可以把两个向量的权重差异按特征词排序,找出权重最大的几个词作为“推荐理由”,演示效果会非常好。

3.2 构建用户画像:用阅读行为加权兴趣标签

用户画像的输入是行为数据,输出是一个和新闻特征同维度的兴趣向量。基本逻辑很简单:用户读过哪些新闻,这些新闻的向量加权平均一下,就是用户的兴趣向量。

加权不是平均那么简单。我采用的策略是三类叠加:行为权重、时间衰减权重、文本相似度权重。点赞行为权重设为1.5,浏览行为设为1.0,不感兴趣设为负权重-0.3;三天内新闻权重不衰减,超过三天每增加一天乘0.9的衰减系数。这样画像能贴近用户近期兴趣,而不是永远停留在一个月前读过的老新闻上。

import numpy as np from datetime import datetime, timedelta def build_user_profile(user_id, behaviors, news_vectors): profile = np.zeros(news_vectors.shape[1]) now = datetime.now() total_weight = 0.0 behavior_weight = { "view": 1.0, "like": 1.5, "dislike": -0.3 } for b in behaviors: if b["user_id"] != user_id: continue news_id = b["news_id"] news_vec = news_vectors[news_id] if news_vec is None: continue # 时间衰减:3天内不衰减,之后每天衰减0.9 days_diff = (now - b["time"]).days time_decay = 1.0 if days_diff <= 3 else (0.9 ** (days_diff - 3)) w = behavior_weight.get(b["type"], 0) * time_decay profile += w * news_vec total_weight += abs(w) if total_weight > 0: profile /= total_weight else: profile = np.zeros(news_vectors.shape[1]) return profile

用户画像在用户行为变化后要重新计算,所以我建议把画像生成写成独立函数,在每次用户新增阅读记录后异步调用,结果存到用户画像表里。这样推荐接口查询时直接读画像结果,不用现场扫描全部行为数据。

有一点要提醒:不感兴趣的负权重要慎用。如果用户只标记了一个“不感兴趣”,就对一批有相关关键词的新闻全部降权,很容易出现画像被带偏。实际处理时,我更倾向于把负向行为的影响范围限制在同分类下,而不是全局。

3.3 推荐候选集的生成与排序:相似度加时间新鲜度

有了用户兴趣向量和新闻向量,推荐的核心就变成“在新闻集合里找与画像最相似的N篇”。最朴素的做法是遍历所有新闻,逐一计算余弦相似度,排序取前N,在几百篇新闻的数据集上完全没有性能问题。

真正的推荐代码我加入了一个修正因子:相似度分数乘以新闻时效系数。新闻是强时效内容,三天前的“突发事件”和今天的“突发事件”对用户的吸引力完全不同。我通常给发布时间在一天内的新闻乘1.0,两天内乘0.9,一周内乘0.7,超过一周乘0.5。这个系数不是死的,你可以根据自己的数据集调。

def recommend_news(user_profile, news_vectors, news_ids, top_n=10): scores = [] for news_id in news_ids: news_vec = news_vectors[news_id] if news_vec is None: continue # 计算余弦相似度 dot = np.dot(user_profile, news_vec) norm_user = np.linalg.norm(user_profile) norm_news = np.linalg.norm(news_vec) if norm_user == 0 or norm_news == 0: sim = 0 else: sim = dot / (norm_user * norm_news) # 时间因子 time_factor = get_time_factor(news_id) score = sim * time_factor scores.append((news_id, score, sim)) scores.sort(key=lambda x: x[1], reverse=True) return scores[:top_n]

选出候选后还有一个动作:去重。同一系列新闻经常出现高度重复文本,比如各大媒体转载同一条快讯,向量相似度接近1,如果不去重,推荐结果可能被同一事件霸屏。我采用的去重策略是,如果两篇新闻相似度高于0.85,只保留发布时间更新的一篇;如果关键词重合度极高,也只保留阅读量更高的一篇。

排序之后要记录推荐理由。取用户画像和新闻向量中权重最高的重叠特征词,拼成一句“因为您关注了‘XX、XX’主题,为您推荐本篇新闻”,存进推荐结果表。不要小看这句话,它既方便前端展示,也是论文中“可解释推荐”最直观的截图素材。

3.4 实现一个可运行的推荐接口

整个系统跑起来时,后端至少要暴露三个核心接口:新闻列表接口、文本分析结果接口、个性化推荐接口。以Flask为例,推荐接口可以这样写。

from flask import Flask, request, jsonify import json app = Flask(__name__) # 模拟从数据库读取数据 news_list = load_news_from_db() news_vectors = load_news_vectors() user_profiles = load_user_profiles() @app.route("/api/recommend/<user_id>", methods=["GET"]) def recommend(user_id): top_n = int(request.args.get("top_n", 10)) profile = user_profiles.get(user_id) if profile is None: return jsonify({"code": 1, "msg": "用户画像为空,请先产生阅读行为", "data": []}) result = recommend_news(profile, news_vectors, news_list.keys(), top_n) response_data = [] for news_id, score, sim in result: news = news_list[news_id] response_data.append({ "news_id": news_id, "title": news["title"], "category": news["category"], "similarity": round(sim, 4), "reason": generate_reason(profile, news_vectors[news_id]) }) # 将推荐结果写入推荐表 save_recommendations(user_id, response_data) return jsonify({"code": 0, "data": response_data}) if __name__ == "__main__": app.run(host="0.0.0.0", port=5000, debug=True)

这里建议把加载新闻、向量、画像的代码写成一个数据加载模块,启动服务时一次性加载到内存,不要在每次请求时重复读文件。如果你用的是SQLite或MySQL,也要避免在推荐循环里逐条查库,否则响应速度会非常慢。我在第一次联调时就是因为推荐接口里逐条查新闻详情,一个请求花了六秒,改成内存加载后直接降到几十毫秒。

4. 实操过程记录:从空项目到跑通推荐

4.1 准备数据集:不需要海量,但要干净

数据是毕业设计最容易卡住的环节。老老实实去找公开数据集,一般都能找到新闻语料。如果找不到合适的,最务实的方案是手工整理几百条带分类的新闻文本,来源可以是公开新闻报道改写,覆盖体育、科技、财经、娱乐、健康几个大类。类别不要太少,至少五个,否则推荐的“个性化”看不出来。

数据清洗是必做的一步。原始新闻文本里常见噪声包括:图片链接、浏览器分享提示、作者署名、发布时间混在正文里。我写清洗脚本时用了最简单的正则方案,先把所有非中英文字符和数字转成空格,再把连续空格合并。注意不要连标点都清没,推荐解释里还要展示原始句子片段。

清洗后的数据格式建议统一成CSV或JSON,字段包括news_id、title、content、category、publish_time。每条数据控制在100到500字之间,太短的新闻没有分词价值,太长的新闻处理起来也容易让向量维度膨胀。

4.2 离线分析:跑一遍分词和向量化

数据准备好后,先写一个独立脚本跑离线分析流程。脚本执行顺序是:读取新闻、清洗、分词、TF-IDF向量化、保存新闻向量和特征词列表、输出每个类别的Top关键词。

我第一次跑这个脚本时输出了一个文件,全量打印每条新闻的关键词,用来人工核对分词质量。这一步非常值得做。比如“华为发布新款折叠屏手机”这句话,如果分词结果是“华为/发布/新款/折叠屏/手机”,说明词典基本没问题;如果结果出现“华为发/布新款/折叠屏手/机”这种碎片,就得往自定义词典里补词了。

计算每个类别Top关键词用简单累加就行。把属于“科技”类的所有新闻向量逐列求和,取权重最高的20个词,基本就是这个类别的主题标签。这些标签后续可以手动维护一份“类别关键词表”,推荐引擎里给用户画像加了一个“分类偏好”维度时,可以直接用这张表。

4.3 Web端展示与完整功能联调

系统联调时我先跑通“用户注册到浏览新闻到推荐结果变化”这条闭环。用一个测试账号注册后,在该账号下依次阅读三篇科技类新闻和三篇体育类新闻,再刷新推荐接口看结果。正常情况是:推荐列表里前几条应该以科技和体育类新闻为主,并且推荐理由里能出现“芯片、手机、比赛、球员”等对应关键词。

前端展示上,我建议做一个“推荐解释”区域,把每条推荐新闻命中的关键词标签显示出来。这一块是答辩时的展示重点,也是老师最容易产生兴趣的地方。如果方便,可以把关键词做成词云页面,视觉冲击力很强,实现起来也不复杂。

新闻行为反馈也要完整联调。用户点击“不感兴趣”后再刷新推荐列表,被标记的那类新闻应该在列表中明显降权。这个功能如果没做,答辩时只能演示“推荐有结果”,但没法演示“推荐会根据用户反馈动态调整”,闭环就不完整。

调试中还发现一个常见问题:前端传入用户ID,后端要从数据库实时读用户行为,如果行为表里时间字段是字符串,在Python里计算时间衰减时直接相减会报错。解决办法是数据库里统一用日期时间类型,代码里再用datetime模块解析。字段类型不一致引发的迷之错误,在联调阶段占了很大比例,一定提前统一。

4.4 做个简单效果评估

毕设不需要写太复杂的评估,但建议做一组简单的指标计算。方法是准备一批带分类标签的新闻,对测试用户隐藏一部分新闻,让用户实际阅读若干条后,看推荐结果里有多少条属于用户偏好的类别,计算准确率、召回率、F1值。

以“体育类偏好的用户”为例:推荐10条新闻中7条属于体育类,准确率就是70%;测试集里体育类新闻共30条,推荐命中了其中7条,召回率就是23.33%。这个数字单独看意义不大,但作为“用户体验对比实验”就能派上用场:一套不采用文本分析、直接按新闻发布时间排序的冷启动推荐结果,准确率可能只有40%,对比说明基于文本分析的推荐确实有明显提升。

评估脚本建议独立保存,论文里放一张对比表格,既显得你做了实验分析,又不像凭空编造数据。注意实验设置要写清楚,种子用户、候选新闻集合、行为批次都要固定,保证结果可复现。

5. 我踩过的坑与常见问题排查实录

5.1 中文文本分析的“隐形坑”

中文分词最坑的不是分词工具本身,而是词典和停用词。默认的jieba词典对网络热词和新词识别很差,你不加自定义词典,“神舟十八号”会被切成“神舟/十八/号”,关键词效果直接崩。我的建议是,凡是新闻标题里出现的专业名词,手动收集起来放自定义词典里。量不需要大,200个词就够当前项目使用了。

停用词表也不能照搬网上的通用版本。很多通用停用词表会误杀“能、会、要”这类词,而它们在新闻里有时有实际含义。我实际实验后发现:停用词过滤宁可少过滤,也不要过度过滤。少几个无意义词只会让向量维度稍大,但关键词还能正常;过度过滤会把新闻主题词都删没,推荐结果就彻底乱了。

还有一个隐蔽问题是中文编码。Windows下用记事本保存的自定义词典和停用词表,默认可能是GBK编码,Python读取直接报错。所有文本文件统一用UTF-8编码,读取时显式指定encoding,能节省大量排查时间。

5.2 推荐结果看起来“不相关”怎么排查

推荐结果不相关,是整个项目里最容易遇到的挫败点。我通常会按照“从数据到算法”的顺序排查。

先检查新闻向量是否正常生成。打印一篇新闻向量的非零维度数量,如果为零,说明这篇新闻分词后所有词都被过滤掉了,要么是文本太短,要么是停用词表过狠。再检查用户画像是否全零,常见原因是测试用户没有阅读记录,或者行为记录里的新闻ID和新闻表对不上。最后检查相似度排序,临时打印几篇候选新闻的相似度数值,如果所有分数都在0.1以下,说明用户兴趣和新闻集合整体偏差较大,可以适当补充同类新闻语料。

我做一个项目时遇到过推荐列表全是旧新闻的情况,排查很久才发现是时间因子没有生效,所有新闻无论发布时间都被当成同一天处理,导致排序全看相似度。加上时间衰减后效果立刻正常。

5.3 系统响应慢的优化空间

对于几百篇新闻的数据量,推荐计算本身不会慢,慢的往往是数据库查询。最常见的问题是在循环里查询新闻详情,比如推荐5条新闻就查5次数据库,每次还有关联查询,时间自然爆炸。解决办法是先把需要用到的新闻信息全部加载到内存再用,或一次性用SQL的IN条件批量查出。

另一个性能堵点是TF-IDF向量维度太大。一篇新闻经过分词后特征词可能有几千个,如果每篇新闻都存稀疏矩阵还好,一旦转成普通numpy数组再参与计算,几百篇还好,几千篇就会明显卡顿。建议全程用scipy的稀疏矩阵保存新闻向量,只在单篇相似度计算时转成稠密数组。实际操作中,把向量维度限制在Top 5000特征词以内,效果和速度能兼顾。

5.4 联调和部署常见问题速查

联调阶段的错误五花八门,我把最常遇到的问题整理成表,方便对照:

问题现象常见原因解决办法
接口返回中文乱码Flask默认编码问题response的Content-Type设置为application/json; charset=utf-8
读数据库中文变成问号数据库连接字符串未指定charset连接参数加charset=utf8
用户没有推荐结果用户画像为空或读取异常检查行为数据和用户ID是否匹配
推荐理由里的词全是“的、了、是”停用词过滤没生效检查停用词表路径和编码
向量文件加载后维度不一致新增新闻后未重新训练向量器每次新增新闻后重新跑离线分析脚本
前端小程序请求接口跨域后端未开启CORSFlask安装flask-cors并全局注册

部署方面,如果只是本地演示,直接跑Flask开发服务器就可以了。如果要在实验室服务器上跑给老师看,建议用gunicorn跑Flask服务,前端静态页面用Nginx代理。但这一步不是必须的,大部分毕设答辩都是在自己电脑上演示,别在部署上花太多时间。

6. 完成之后的扩展建议:让项目从“能跑”到“能讲”

6.1 从离线推荐升级到实时推荐

离线推荐能跑通,但老师说“想看看实时性怎么办”,这个扩展方向就可以派上用场。思路很简单:在用户点击新闻详情的接口里同步触发一次画像更新,再把推荐结果重新计算一次,单用户单次计算在几百篇新闻规模下耗时不超过几十毫秒,完全可以做成同步接口。这样用户刷新页面时,推荐列表立刻反映最新阅读行为,演示效果非常直观。

6.2 引入混合推荐策略

纯基于内容的推荐有“信息茧房”问题:用户永远只能看到和过去兴趣相似的新闻。扩展方案是加一个协同过滤兜底:在生成推荐候选时,一部分来自内容相似度,一部分来自“和你兴趣相似的用户喜欢看什么”,两路结果按比例融合。实现方式也不复杂,用用户的阅读历史构造用户ID到新闻ID的映射,找最相似用户时直接算相同阅读记录的Jaccard系数。

6.3 加入词云和情感分布可视化

文本分析模块产出很多中间结果,不用可视化展示出来非常可惜。最简单的是把某个分类下的高频词生成词云,用现成的wordcloud库做就行;情感分布可以用snownlp对每条新闻算一个情感分数,再按分类聚合,展示成柱状图。这两块内容工作量不大,但能让系统的“文本分析”属性在界面上非常显眼。论文配图直接用系统截图,比画一堆架构图更落地。

我在实际做完这个项目后最大的体会是:不要把推荐系统当成一个黑盒去“调包”,而是要把文本分析到用户画像再到推荐排序的链路想清楚,每一步都知道输入输出是什么。题目里反复强调“文本分析”,就是希望你在答辩时能讲清楚新闻是怎么被理解、用户兴趣是怎么被表达的。做到这一点,哪怕代码朴素一些,也完全撑得起一篇优秀的毕业设计。另外再多说一句,网上那些“成品”“定制”的诱惑别碰,自己动手把文本分析流程跑一遍,收获比多写十个管理系统都大。

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

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

立即咨询