基于Vue+Flask+Sqlite的RSS阅读器
任务要求
① 订阅管理:用户可以添加、编辑和删除订阅源,以选择他们感兴趣的网站和内容。
② 更新检测:阅读器定期检查订阅的源,以获取最新的内容更新。这可以是按计划的时间间隔,也可以是根据用户的设定来触发。
③ 内容聚合:阅读器将从不同源获取的内容聚合在一个统一的界面中,让用户能够方便地浏览和阅读多个网站的更新。
④ 阅读界面:阅读器提供一个可视化界面,显示每个源的更新内容。这通常以列表或卡片的形式呈现,其中包含文章标题、作者、发布日期和摘要等信息。
⑤ 阅读管理:用户可以标记文章为已读或未读状态,以便在后续使用中追踪阅读进度。一些阅读器还允许用户对文章进行标记、收藏、标签分类或筛选等操作。
⑥ 通知功能:一些阅读器支持推送通知,当订阅的源有新的更新时,用户会收到提醒,无需手动检查阅读器。
⑦ 搜索和过滤:阅读器通常提供搜索功能,让用户能够快速找到感兴趣的文章或主题。它们还可能支持过滤功能,让用户可以根据标签、日期范围或其他条件来筛选和浏览内容。
⑧ 导入和导出:阅读器通常允许用户导入和导出订阅列表,以便在不同设备或阅读器之间进行同步或备份。思路:先获取一部分RSS源,存入Sqlite数据库中,根据这些RSS源再获取其对应的文章;使用基于Python的Flask框架进行后端开发,并用Postman测试接口;使用Vue框架进行前端开发。
界面概览
开发软件
- Vscode:前端开发,使用Vue框架
- Pycharm:后端开发,使用Flask框架
- Navicat:数据库管理软件,使用SQLite
- 八爪鱼:爬虫,获取RSS源,网站: RSS-Source
数据库
- 三个数据表,分别是categories、rss_sources、articles
- categories
名 类型 含义 不是null 是否主键 id INTEGER 唯一标识 √ √ name TEXT 分类名称 created_at TEXT 创建时间 updated_at TEXT 更新时间 chname TEXT 中文名称 is_deleted TEXT 逻辑删除位 - rss_sources
名 类型 含义 不是null 是否主键 id INTEGER 唯一标识 √ √ url TEXT RSS地址 √ title TEXT RSS源名称 description TEXT 描述 image TEXT 图片 category_id TEXT 分类id(外键) created_at TEXT 创建时间 updated_at TEXT 更新时间 is_deleted TEXT 逻辑删除位 - articles
名 类型 含义 不是null 是否主键 id INTEGER 唯一标识 √ √ feed_id TEXT RSS源的id(外键) title TEXT 文章标题 link TEXT 文章链接 description TEXT 描述 content TEXT 内容 published_at TEXT 文章发布时间 is_read TEXT 已读标志位 is_favorite TEXT 收藏标志位 created_at TEXT 创建时间 updated_at TEXT 更新时间 is_deleted TEXT 逻辑删除位
后端
采用Flask框架,主要由两部分构成:model.py与app.py
# models.py
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
import pandas as pd
db = SQLAlchemy()
class Article(db.Model):
__tablename__ = 'articles'
id = db.Column(db.Integer, primary_key=True)
feed_id = db.Column(db.Integer,default=False)
title = db.Column(db.String(255), nullable=False)
link = db.Column(db.Text, nullable=False)
description = db.Column(db.Text, nullable=False)
published_at = db.Column(db.DateTime)
is_read = db.Column(db.Boolean, default=False)
is_favorite = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
is_deleted = db.Column(db.Boolean, default=False)
bookmark = db.Column(db.Boolean, default=False)
class Category(db.Model):
__tablename__ = 'categories'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
chname = db.Column(db.String(50), nullable=False)
is_deleted = db.Column(db.Boolean, default=False)
class RSSSource(db.Model):
__tablename__ = 'rss_sources'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
url = db.Column(db.String(255), nullable=False)
image = db.Column(db.String(255), nullable=False)
description = db.Column(db.String(255), nullable=False)
category_id = db.Column(db.Integer, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
is_deleted = db.Column(db.Boolean, default=False)
# app.py
from flask import Flask, jsonify, send_file
from flask_socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="http://localhost:8080")
# 数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///rssdata.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 初始化Sqlite数据库
db.init_app(app)
# 解决跨域
CORS(app, resources={r'/*': {'origins': '*'}})
# 省略其他的函数代码
if __name__ == '__main__':
# 这里使用socktio是因为使用了websocket的前后端通道
socketio.run(app)
前端
前端使用Vue框架,只有两个界面,一个组件。
router里的index.js的配置如下:
import Vue from 'vue'
import VueRouter from 'vue-router'
import IndexView from '../views/IndexView.vue'
import TestView from '../views/TestView.vue'
import Article from '../components/CardList.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'test',
component: TestView,
redirect:{name:"index"},
children: [{
path: "/article/:id",
name: 'article',
component: Article,
},
{
path: "/index",
name: 'index',
component: IndexView
},
]
},
]
const router = new VueRouter({
mode: 'history',
routes
})
router.beforeEach((to, from, next) =>{
next();
})
export default router