
温馨提示本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片1. 背景与意义在信息爆炸的时代用户每天面对海量的新闻资讯如何高效地获取自己感兴趣的内容成为一个重要挑战。传统的新闻门户网站采用“千人一面”的推送方式无法满足用户的个性化需求容易导致信息过载和用户流失。个性化新闻推荐系统应运而生它通过分析用户的历史行为数据如点击、阅读时长、点赞、收藏等构建用户画像并利用推荐算法预测用户可能感兴趣的新闻实现“千人千面”的精准推送。这种系统不仅能提升用户体验和粘性还能增加平台的点击率和商业价值。Django 作为 Python 领域最成熟、功能最全的 Web 框架之一以其“开箱即用”的特性、清晰的设计模式和强大的社区生态成为快速构建此类数据驱动型应用的理想选择。2. 技术栈详解2.1 后端框架与核心库Django (4.x)作为项目主体框架负责 URL 路由、视图逻辑、模板渲染、ORM 数据层和后台管理。Django REST Framework (DRF)用于构建 RESTful API为前端或移动端提供用户、新闻、推荐列表等数据的 JSON 接口。Python 3.8编程语言基础。2.2 数据存储PostgreSQL / MySQL作为主关系型数据库存储用户信息、新闻元数据、用户行为日志等结构化数据。Redis用作缓存数据库存储热门新闻列表、用户实时行为队列、模型计算的临时结果以提升系统响应速度。Elasticsearch (可选)用于新闻内容的全文检索和复杂查询提升新闻发现能力。2.3 推荐算法与机器学习scikit-learn实现经典的协同过滤、基于内容的推荐等机器学习算法。Surprise专注于推荐系统的 Python 库内置多种协同过滤算法如 SVD, KNNBaseline。LightFM适用于混合推荐协同过滤 基于内容的库能很好地处理冷启动问题。NumPy Pandas进行数据清洗、特征工程和数值计算。2.4 任务队列与异步处理Celery分布式任务队列用于异步处理耗时的任务如定时更新用户画像、离线训练推荐模型、批量计算推荐结果。RabbitMQ / Redis作为 Celery 的消息代理Broker。2.5 前端技术 (可选)Django 模板 Bootstrap快速构建管理后台和简单的展示页面。Vue.js / React构建现代化的单页面应用SPA前端提供更流畅的用户交互体验。2.6 部署与运维Docker Docker Compose实现应用和依赖服务的容器化保证环境一致性。Nginx作为反向代理和静态文件服务器。Gunicorn / uWSGI作为 Django 应用的 WSGI 服务器。3. 系统核心模块与代码示例3.1 数据模型设计 (models.py)核心数据表设计定义了系统的基础数据结构。from django.db import models from django.contrib.auth.models import User class News(models.Model): 新闻文章模型 title models.CharField(max_length200, verbose_name标题) content models.TextField(verbose_name内容) category models.CharField(max_length50, verbose_name类别) tags models.CharField(max_length200, blankTrue, verbose_name标签) # 逗号分隔 publish_time models.DateTimeField(auto_now_addTrue, verbose_name发布时间) # 新闻特征向量用于基于内容的推荐 feature_vector models.TextField(blankTrue, verbose_name特征向量) # 可存储JSON或序列化数组 class Meta: ordering [-publish_time] def __str__(self): return self.title class UserBehavior(models.Model): 用户行为日志模型 BEHAVIOR_TYPES ( (click, 点击), (read, 阅读), (like, 点赞), (collect, 收藏), (share, 分享), ) user models.ForeignKey(User, on_deletemodels.CASCADE, verbose_name用户) news models.ForeignKey(News, on_deletemodels.CASCADE, verbose_name新闻) behavior_type models.CharField(max_length20, choicesBEHAVIOR_TYPES, verbose_name行为类型) behavior_time models.DateTimeField(auto_now_addTrue, verbose_name行为时间) # 行为权重可用于计算用户兴趣度 weight models.FloatField(default1.0, verbose_name权重) class Meta: indexes [ models.Index(fields[user, -behavior_time]), ] class UserProfile(models.Model): 用户画像模型可定期更新 user models.OneToOneField(User, on_deletemodels.CASCADE, primary_keyTrue, verbose_name用户) # 兴趣向量基于历史行为计算得出 interest_vector models.TextField(blankTrue, verbose_name兴趣向量) last_update models.DateTimeField(auto_nowTrue, verbose_name最后更新时间) def __str__(self): return f{self.user.username}的画像3.2 基于内容的推荐核心逻辑 (recommendation/content_based.py)根据新闻特征和用户兴趣向量的相似度进行推荐。import json import numpy as np from sklearn.metrics.pairwise import cosine_similarity from django.db.models import Q from news.models import News, UserProfile class ContentBasedRecommender: 基于内容的推荐器 def __init__(self): self.news_vectors_cache {} # 简单缓存新闻特征向量 def get_user_interest_vector(self, user_id): 获取用户的兴趣向量 try: profile UserProfile.objects.get(user_iduser_id) if profile.interest_vector: return np.array(json.loads(profile.interest_vector)) except UserProfile.DoesNotExist: pass # 如果用户没有画像返回空向量或热门新闻的均值向量 return np.zeros(100) # 假设特征维度为100 def get_news_feature_vector(self, news_id): 获取新闻的特征向量 if news_id in self.news_vectors_cache: return self.news_vectors_cache[news_id] try: news News.objects.get(idnews_id) if news.feature_vector: vector np.array(json.loads(news.feature_vector)) self.news_vectors_cache[news_id] vector return vector except News.DoesNotExist: pass return np.zeros(100) def recommend_for_user(self, user_id, top_n10, exclude_readTrue): 为用户生成Top-N推荐 user_vector self.get_user_interest_vector(user_id) # 构建查询排除用户已读新闻如果要求 query News.objects.all() if exclude_read: read_news_ids UserBehavior.objects.filter( user_iduser_id, behavior_type__in[click, read] ).values_list(news_id, flatTrue) query query.exclude(id__inread_news_ids) # 计算相似度 recommendations [] for news in query[:200]: # 限制计算数量可优化 news_vector self.get_news_feature_vector(news.id) similarity cosine_similarity([user_vector], [news_vector])[0][0] recommendations.append((news, similarity)) # 按相似度排序返回Top-N recommendations.sort(keylambda x: x[1], reverseTrue) return [news for news, _ in recommendations[:top_n]]3.3 混合推荐策略视图 (views.py)在Django视图中整合多种推荐策略提供推荐API。from django.http import JsonResponse from django.views.decorators.http import require_GET from django.contrib.auth.decorators import login_required from recommendation.content_based import ContentBasedRecommender from recommendation.collaborative import CollaborativeFilteringRecommender import random login_required require_GET def get_personalized_news(request): 获取个性化新闻推荐列表 user request.user # 1. 获取基于内容的推荐 cb_rec ContentBasedRecommender() cb_news cb_rec.recommend_for_user(user.id, top_n15) # 2. 获取协同过滤推荐示例 cf_rec CollaborativeFilteringRecommender() cf_news cf_rec.recommend_for_user(user.id, top_n10) # 3. 混合策略加权合并、去重、打散 all_news list(set(cb_news cf_news)) # 4. 如果推荐结果不足用热门新闻补足 if len(all_news) 20: from django.db.models import Count hot_news News.objects.annotate( click_countCount(userbehavior, filterQ(userbehavior__behavior_typeclick)) ).order_by(-click_count, -publish_time)[:30] # 排除已推荐和已读 read_ids UserBehavior.objects.filter( useruser, behavior_type__in[click, read] ).values_list(news_id, flatTrue) hot_news [n for n in hot_news if n not in all_news and n.id not in read_ids] all_news.extend(hot_news[:20 - len(all_news)]) # 随机打散避免单一算法结果集中出现 random.shuffle(all_news) final_recommendations all_news[:20] # 构造返回数据 data { recommendations: [ { id: news.id, title: news.title, category: news.category, publish_time: news.publish_time.isoformat(), } for news in final_recommendations ] } return JsonResponse(data)3.4 用户行为收集与画像更新任务 (tasks.py)使用Celery异步任务处理用户行为并定期更新用户画像。from celery import shared_task from django.utils import timezone from datetime import timedelta import json import numpy as np from news.models import UserBehavior, UserProfile, News from sklearn.feature_extraction.text import TfidfVectorizer shared_task def log_user_behavior(user_id, news_id, behavior_type, weight1.0): 记录用户行为异步 UserBehavior.objects.create( user_iduser_id, news_idnews_id, behavior_typebehavior_type, weightweight, behavior_timetimezone.now() ) shared_task def update_user_profiles(): 定时任务更新所有用户的兴趣画像基于近期行为 # 1. 获取所有新闻的特征向量TF-IDF示例 all_news News.objects.all() vectorizer TfidfVectorizer(max_features100, stop_wordsenglish) # 假设新闻内容已预处理 contents [news.content for news in all_news] tfidf_matrix vectorizer.fit_transform(contents).toarray() # 2. 为每个用户计算兴趣向量 for profile in UserProfile.objects.all(): user profile.user # 获取用户最近30天的行为 since timezone.now() - timedelta(days30) behaviors UserBehavior.objects.filter( useruser, behavior_time__gtesince ).select_related(news) if not behaviors.exists(): continue # 加权平均新闻特征向量作为用户兴趣向量 interest_vector np.zeros(100) total_weight 0 for behavior in behaviors: try: news_index list(all_news).index(behavior.news) news_vector tfidf_matrix[news_index] interest_vector news_vector * behavior.weight total_weight behavior.weight except (ValueError, IndexError): continue if total_weight 0: interest_vector / total_weight # 更新用户画像 profile.interest_vector json.dumps(interest_vector.tolist()) profile.save()4. 总结与展望本文介绍了使用 Django 构建个性化新闻推荐系统的完整技术栈、核心模块与关键代码。该系统融合了基于内容的推荐和协同过滤算法并通过异步任务实时更新用户画像能够有效提升新闻分发的精准度。后续优化方向算法层面引入深度学习模型如 Wide Deep, YouTube DNN处理更复杂的特征交互。工程层面采用流式计算框架如 Apache Flink处理实时用户行为实现秒级画像更新。评估体系建立 A/B 测试平台量化不同推荐策略对点击率、阅读时长等核心指标的影响。通过持续迭代技术架构与算法模型可以打造出体验更优、效果更佳的个性化新闻推荐产品。