# RSSKeeper API 接口文档 Base URL: `http://:7329` 所有接口返回 JSON 格式数据。 --- ## 目录 - [健康检查](#健康检查) - [RSS 源管理](#rss-源管理) - [获取源列表](#获取源列表) - [获取源详情](#获取源详情) - [添加源](#添加源) - [更新源](#更新源) - [删除源](#删除源) - [触发抓取](#触发抓取) - [批量抓取](#批量抓取) - [自动发现](#自动发现) - [获取分类列表](#获取分类列表) - [导入 OPML](#导入-opml) - [导出 OPML](#导出-opml) - [文章管理](#文章管理) - [获取文章列表](#获取文章列表) - [获取文章详情](#获取文章详情) - [全文搜索](#全文搜索) - [标记已读](#标记已读) - [仪表盘](#仪表盘) - [统计概览](#统计概览) - [健康度详情](#健康度详情) - [最近活动](#最近活动) - [外部 API(供 AI 集成)](#外部-api) - [获取最近文章](#获取最近文章) - [全文搜索](#全文搜索external) - [获取源列表(含筛选)](#获取源列表含筛选) - [获取指定源文章](#获取指定源文章) - [获取每日摘要](#获取每日摘要) --- ## 通用字段说明 ### 健康度 (health_status) | 值 | 含义 | |---|------| | `healthy` | 健康:成功率 >= 90%,7天内有抓取 | | `warning` | 警告:成功率 50%-90%,或超过3天未更新 | | `unhealthy` | 异常:成功率 < 50%,或超过7天未更新 | | `unknown` | 未知:尚未进行过任何抓取 | ### 错误类型 (error_type) | 值 | 含义 | |---|------| | `url_invalid` | URL 已失效(404) | | `forbidden` | 被站点拒绝(403) | | `rate_limited` | 频率限制(429) | | `timeout` | 连接超时 | | `dns_failure` | DNS 解析失败 | | `connection_refused` | 连接被拒绝 | | `connection_reset` | 连接中断 | | `ssl_error` | SSL/TLS 错误 | | `unreachable` | 服务器不可达 | | `url_malformed` | URL 格式错误 | | `server_error` | 服务器错误(5xx) | | `unknown` | 其他未知错误 | --- ## 健康检查 ### `GET /api/health` 检查服务是否运行。 **响应:** ```json { "status": "ok", "service": "rssKeeper" } ``` --- ## RSS 源管理 ### 获取源列表 ### `GET /api/feeds` **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `skip` | int | 否 | 0 | 跳过条数(分页偏移) | | `limit` | int | 否 | 100 | 每页条数 | | `category` | string | 否 | - | 按分类筛选 | | `search` | string | 否 | - | 按名称/URL/描述搜索 | | `is_active` | bool | 否 | - | 按启用状态筛选 | | `health_status` | string | 否 | - | 按健康度筛选:`healthy`/`warning`/`unhealthy`/`unknown` | **响应:** ```json { "total": 383, "items": [ { "id": 1, "url": "https://example.com/feed.xml", "title": "Example Feed", "description": "Feed description", "category": "科技", "is_active": true, "fetch_interval_minutes": 60, "last_fetch_at": "2026-06-11T08:33:36.474905", "last_fetch_status": "success", "last_error": "", "error_type": "", "success_count": 5, "fail_count": 0, "article_count": 42, "health_status": "healthy", "next_fetch_time": "2026-06-11T09:33:36.000000+00:00", "created_at": "2026-06-11T08:33:24.591074" } ] } ``` --- ### 获取源详情 ### `GET /api/feeds/{feed_id}` **路径参数:** | 参数 | 类型 | 说明 | |------|------|------| | `feed_id` | int | RSS 源 ID | **响应:** 同列表中的单条 items 结构。 --- ### 添加源 ### `POST /api/feeds` **请求体:** ```json { "url": "https://example.com/feed.xml", "title": "Example", "description": "", "category": "科技", "is_active": true, "fetch_interval_minutes": 60 } ``` | 字段 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `url` | string | **是** | - | RSS 源地址 | | `title` | string | 否 | "" | 源名称(留空则自动抓取) | | `description` | string | 否 | "" | 描述 | | `category` | string | 否 | "" | 分类 | | `is_active` | bool | 否 | true | 是否启用 | | `fetch_interval_minutes` | int | 否 | 60 | 抓取间隔(分钟),最小 15 | **响应:** ```json { "id": 1, "message": "RSS 源添加成功,正在后台抓取", "url": "https://example.com/feed.xml" } ``` 添加成功后会自动在后台触发首次抓取。 **错误:** `409` — 该 RSS 源已存在 --- ### 更新源 ### `PUT /api/feeds/{feed_id}` **请求体(只需传要修改的字段):** ```json { "title": "新名称", "category": "新闻", "is_active": false, "fetch_interval_minutes": 120 } ``` **响应:** ```json { "message": "RSS 源更新成功" } ``` --- ### 删除源 ### `DELETE /api/feeds/{feed_id}` 删除 RSS 源,**级联删除**关联的所有文章和抓取日志。 **响应:** ```json { "message": "RSS 源已删除" } ``` --- ### 触发抓取 ### `POST /api/feeds/{feed_id}/fetch` 手动触发单个源的抓取。同步执行,返回抓取结果。 **响应:** ```json { "success": true, "articles_count": 5, "feed_title": "Example Feed" } ``` --- ### 批量抓取 ### `POST /api/feeds/batch-fetch` 并发同步抓取多个源。适用于"全部抓取"等场景。 **请求体:** ```json { "feed_ids": [1, 2, 3, 4, 5] } ``` **响应:** ```json { "message": "完成:4 个成功,1 个失败", "total": 5, "success": 4, "fail": 1 } ``` --- ### 自动发现 ### `POST /api/feeds/discover` 从任意网页自动发现 RSS/Atom feed URL。 **参数:** | 参数 | 类型 | 必填 | 说明 | |------|------|------|------| | `url` | string | **是** | 网页地址 | **响应:** ```json { "source_url": "https://example.com", "found_feeds": [ "https://example.com/feed.xml", "https://example.com/rss" ] } ``` --- ### 获取分类列表 ### `GET /api/feeds/categories` 返回所有已使用的分类。 **响应:** ```json ["科技", "新闻", "设计"] ``` --- ### 导入 OPML ### `POST /api/feeds/import-opml` 从 OPML 内容批量导入 RSS 源。 **请求体:** ```json { "opml_content": "..." } ``` | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `opml_content` | string | **是** | OPML 文件内容(最大 5MB) | **响应:** ```json { "added": 15, "skipped": 3, "message": "成功导入 15 个 RSS 源" } ``` --- ### 导出 OPML ### `GET /api/feeds/export-opml` 导出所有 RSS 源为 OPML 格式。 **响应:** ```json { "opml": "..." } ``` --- ## 文章管理 ### 获取文章列表 ### `GET /api/articles` **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `skip` | int | 否 | 0 | 分页偏移 | | `limit` | int | 否 | 50 | 每页条数 | | `feed_id` | int | 否 | - | 按源筛选 | | `category` | string | 否 | - | 按分类筛选 | | `search` | string | 否 | - | 按标题/链接搜索 | | `since` | string | 否 | - | 起始时间(ISO 格式) | | `until` | string | 否 | - | 截止时间(ISO 格式) | | `is_read` | bool | 否 | - | 按已读状态筛选 | **响应:** ```json { "total": 120, "items": [ { "id": 1, "feed_id": 1, "title": "文章标题", "link": "https://example.com/article", "author": "作者", "published_at": "2026-06-11T06:00:00", "content": "文章正文内容...", "summary": "文章摘要...", "is_read": false, "created_at": "2026-06-11T08:33:36.474905", "feed_title": "Example Feed", "category": "科技" } ] } ``` --- ### 获取文章详情 ### `GET /api/articles/{article_id}` **响应:** 同列表中的单条 items 结构。 --- ### 全文搜索 ### `GET /api/articles/search/fulltext` 使用 SQLite FTS5 进行全文搜索。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `q` | string | **是** | - | 搜索关键词 | | `skip` | int | 否 | 0 | 分页偏移 | | `limit` | int | 否 | 50 | 每页条数 | **响应:** 同文章列表格式。 --- ### 标记已读 ### `PUT /api/articles/{article_id}/read` **响应:** ```json { "message": "已标记为已读" } ``` --- ## 仪表盘 ### 统计概览 ### `GET /api/dashboard/stats` **响应:** ```json { "total_feeds": 383, "active_feeds": 383, "total_articles": 1024, "healthy_feeds": 202, "warning_feeds": 0, "unhealthy_feeds": 167, "today_fetches": 45, "today_success": 40, "today_success_rate": 88.9 } ``` --- ### 健康度详情 ### `GET /api/dashboard/health` 获取每个 RSS 源的健康状态详情。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `skip` | int | 否 | 0 | 分页偏移 | | `limit` | int | 否 | 100 | 每页条数 | **响应:** ```json { "total": 383, "items": [ { "id": 1, "title": "Example Feed", "url": "https://example.com/feed.xml", "is_active": true, "health_status": "healthy", "health_label": "健康", "success_rate": 100.0, "success_count": 5, "fail_count": 0, "total_fetches": 5, "last_fetch_at": "2026-06-11T08:33:36.474905", "days_since_fetch": 0, "article_count": 42, "last_error": "", "recent_logs": [ { "status": "success", "articles_fetched": 3, "response_time_ms": 450, "created_at": "2026-06-11T08:33:36.474905", "error_message": null } ] } ] } ``` --- ### 最近活动 ### `GET /api/dashboard/recent-activity` 获取最近的抓取活动日志。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `limit` | int | 否 | 20 | 返回条数 | **响应:** ```json { "items": [ { "id": 1, "feed_id": 1, "feed_title": "Example Feed", "status": "success", "articles_fetched": 3, "error_message": "", "response_time_ms": 450, "created_at": "2026-06-11T08:33:36.474905" } ] } ``` --- ## 外部 API 供 AI 助手、外部系统调用的接口。前缀:`/api/v1/external`。 ### 获取最近文章 ### `GET /api/v1/external/recent` 获取最近 N 小时的文章,支持多条件组合筛选。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `hours` | int | 否 | 24 | 回溯小时数 | | `limit` | int | 否 | 50 | 最大返回条数 | | `feed_id` | int | 否 | - | 按源 ID 筛选 | | `category` | string | 否 | - | 按分类筛选 | | `search` | string | 否 | - | 按标题/摘要关键词筛选 | | `unread_only` | bool | 否 | false | 只返回未读文章 | **响应:** ```json { "query": { "hours": 24, "limit": 50, "feed_id": null, "category": null, "search": null, "unread_only": false }, "count": 15, "articles": [ { "id": 1, "title": "文章标题", "link": "https://example.com/article", "author": "作者", "summary": "摘要文本", "content": "正文内容(超过10000字符时返回摘要)", "published_at": "2026-06-11T06:00:00", "created_at": "2026-06-11T08:33:36", "feed_title": "Example Feed", "category": "科技" } ] } ``` --- ### 全文搜索 ### `GET /api/v1/external/search` 使用 FTS5 全文搜索引擎检索文章内容。**供 AI 按关键词精准查找文章**。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `q` | string | **是** | - | 搜索关键词 | | `limit` | int | 否 | 50 | 最大返回条数(1-200) | | `offset` | int | 否 | 0 | 分页偏移 | | `category` | string | 否 | - | 按分类二次筛选 | | `feed_id` | int | 否 | - | 按源 ID 二次筛选 | **响应:** ```json { "query": "LLM", "total": 12, "offset": 0, "limit": 50, "articles": [ { "id": 15674, "title": "文章标题", "summary": "匹配的摘要...", "link": "https://example.com/article", "published_at": "2026-06-11T06:00:00", "created_at": "2026-06-11T08:33:36", "feed_id": 1, "feed_title": "Example Feed", "category": "科技" } ] } ``` --- ### 获取源列表(含筛选) ### `GET /api/v1/external/feeds` 获取 RSS 源列表,支持按健康度、错误类型、分类等多维度筛选。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `health_status` | string | 否 | - | 按健康度筛选:`healthy`/`warning`/`unhealthy`/`unknown` | | `category` | string | 否 | - | 按分类筛选 | | `error_type` | string | 否 | - | 按错误类型筛选(见通用字段说明) | | `is_active` | bool | 否 | true | 按启用状态筛选 | **响应:** ```json { "count": 167, "feeds": [ { "id": 1, "title": "Example Feed", "url": "https://example.com/feed.xml", "category": "科技", "is_active": true, "health_status": "unhealthy", "error_type": "timeout", "article_count": 42, "last_fetch_at": "2026-06-11T08:33:36", "last_error": "HTTPSConnectionPool..." } ] } ``` **示例:** - 查看所有异常源:`/api/v1/external/feeds?health_status=unhealthy` - 查看 URL 失效的源:`/api/v1/external/feeds?error_type=url_invalid` - 查看指定分类:`/api/v1/external/feeds?category=科技` --- ### 获取指定源文章 ### `GET /api/v1/external/feeds/{feed_id}/articles` **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `feed_id` | int | **是** | - | RSS 源 ID(路径参数) | | `limit` | int | 否 | 100 | 最大返回条数 | | `since` | string | 否 | - | 起始时间过滤 | | `search` | string | 否 | - | 按标题/摘要关键词筛选 | | `unread_only` | bool | 否 | false | 只返回未读文章 | **响应:** ```json { "feed": { "id": 1, "title": "Example Feed", "url": "https://example.com/feed.xml" }, "count": 42, "articles": [ { "id": 1, "title": "文章标题", "link": "https://example.com/article", "author": "作者", "summary": "摘要", "published_at": "2026-06-11T06:00:00" } ] } ``` --- ### 获取每日摘要 ### `GET /api/v1/external/summary` 获取指定日期的文章摘要,按分类分组。 **参数:** | 参数 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | `date` | string | 否 | 今天 | 日期,格式 `YYYY-MM-DD` | | `category` | string | 否 | - | 按分类筛选 | **响应:** ```json { "date": "2026-06-11", "total_articles": 35, "by_category": { "科技": [ { "title": "文章标题", "link": "https://...", "feed": "Feed 名称", "summary": "文章摘要..." } ], "新闻": [...] } } ```