{"openapi":"3.1.0","info":{"title":"WeChat Download API","description":"\n微信公众号文章下载 API，支持文章解析、公众号搜索、文章列表获取等功能。\n\n## 快速开始\n\n1. 访问 `/login.html` 扫码登录微信公众号后台\n2. 调用 `GET /api/public/searchbiz?query=公众号名称` 搜索目标公众号\n3. 从返回结果中取 `fakeid`，调用 `GET /api/public/articles?fakeid=xxx` 获取文章列表\n4. 对每篇文章调用 `POST /api/article` 获取完整内容\n\n## 认证说明\n\n所有核心接口都需要先登录。登录后凭证自动保存到 `.env` 文件，服务重启后无需重新登录（有效期约 4 天）。\n","license":{"name":"AGPL-3.0","url":"https://www.gnu.org/licenses/agpl-3.0.html"},"version":"1.0.0"},"paths":{"/api/health":{"get":{"tags":["健康检查"],"summary":"健康检查","description":"检查服务健康状态，包括 HTTP 引擎和代理池信息。","operationId":"health_check_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/stats":{"get":{"tags":["统计信息"],"summary":"获取API统计信息","description":"获取API统计信息\n\n包括:\n- 限频统计\n- 请求统计","operationId":"get_stats_api_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsResponse"}}}}}}},"/api/article":{"post":{"tags":["文章内容"],"summary":"获取文章内容","description":"解析微信公众号文章，返回标题、正文、图片等结构化数据。\n\n**请求体参数：**\n- **url** (必填): 微信文章链接，支持 `https://mp.weixin.qq.com/s/xxxxx` 格式\n\n**返回字段：**\n- `title`: 文章标题\n- `content`: HTML 正文（保留原始排版）\n- `plain_content`: 纯文本正文（去除所有 HTML 标签，适合直接阅读或 AI 处理）\n- `author`: 作者\n- `publish_time`: 发布时间戳\n- `images`: 文章内的图片列表","operationId":"get_article_api_article_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/articles":{"get":{"tags":["文章列表"],"summary":"获取文章列表","description":"获取指定公众号的文章列表，支持分页。\n\n**使用流程：**\n1. 先调用 `GET /api/public/searchbiz` 搜索目标公众号\n2. 从搜索结果中获取目标公众号的 `fakeid`\n3. 使用 `fakeid` 调用本接口获取文章列表\n\n**查询参数：**\n- **fakeid** (必填): 目标公众号的 FakeID\n- **begin** (可选): 偏移量，默认 0\n- **count** (可选): 获取数量，默认 10，最大 100\n- **keyword** (可选): 在该公众号内搜索关键词","operationId":"get_articles_api_public_articles_get","parameters":[{"name":"fakeid","in":"query","required":true,"schema":{"type":"string","description":"目标公众号的 FakeID（通过搜索接口获取）","title":"Fakeid"},"description":"目标公众号的 FakeID（通过搜索接口获取）"},{"name":"begin","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"偏移量，从第几条开始","default":0,"title":"Begin"},"description":"偏移量，从第几条开始"},{"name":"count","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"获取数量，最大 100","default":10,"title":"Count"},"description":"获取数量，最大 100"},{"name":"keyword","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"在该公众号内搜索关键词（可选）","title":"Keyword"},"description":"在该公众号内搜索关键词（可选）"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticlesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/articles/search":{"get":{"tags":["文章列表"],"summary":"搜索公众号文章","description":"在指定公众号内按关键词搜索文章。\n\n**查询参数：**\n- **fakeid** (必填): 目标公众号的 FakeID\n- **query** (必填): 搜索关键词\n- **begin** (可选): 偏移量，默认 0\n- **count** (可选): 获取数量，默认 10，最大 100","operationId":"search_articles_api_public_articles_search_get","parameters":[{"name":"fakeid","in":"query","required":true,"schema":{"type":"string","description":"目标公众号的 FakeID","title":"Fakeid"},"description":"目标公众号的 FakeID"},{"name":"query","in":"query","required":true,"schema":{"type":"string","description":"搜索关键词","title":"Query"},"description":"搜索关键词"},{"name":"begin","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"偏移量，默认 0","default":0,"title":"Begin"},"description":"偏移量，默认 0"},{"name":"count","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"获取数量，默认 10，最大 100","default":10,"title":"Count"},"description":"获取数量，默认 10，最大 100"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticlesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/public/searchbiz":{"get":{"tags":["公众号搜索"],"summary":"搜索公众号","description":"按关键词搜索微信公众号，获取 FakeID。\n\n**查询参数：**\n- **query** (必填): 搜索关键词（公众号名称）\n\n**返回字段：**\n- `list[]`: 匹配的公众号列表，每项包含 `fakeid`、`nickname`、`alias`、`round_head_img`\n- `total`: 匹配数量","operationId":"search_accounts_api_public_searchbiz_get","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string","description":"公众号名称或关键词","title":"Query"},"description":"公众号名称或关键词"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/admin/status":{"get":{"tags":["管理"],"summary":"获取登录状态","description":"获取当前登录状态\n\nReturns:\n    登录状态信息","operationId":"get_status_api_admin_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/api/admin/logout":{"post":{"tags":["管理"],"summary":"退出登录","description":"退出登录，清除凭证\n\nReturns:\n    操作结果","operationId":"logout_api_admin_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/login/session/{sessionid}":{"post":{"tags":["登录"],"summary":"初始化登录会话","description":"初始化登录会话，必须在获取二维码之前调用。\n\n**路径参数：**\n- **sessionid**: 会话标识，由前端生成","operationId":"create_session_api_login_session__sessionid__post","parameters":[{"name":"sessionid","in":"path","required":true,"schema":{"type":"string","title":"Sessionid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/login/getqrcode":{"get":{"tags":["登录"],"summary":"获取登录二维码","description":"获取微信公众号登录二维码图片，用微信扫码登录。\n\n**返回：** 二维码图片（PNG/JPEG 格式）","operationId":"get_qrcode_api_login_getqrcode_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/login/scan":{"get":{"tags":["登录"],"summary":"检查扫码状态","description":"轮询检查二维码扫描状态。\n\n**返回状态：** 等待扫码 / 已扫码待确认 / 确认成功 / 二维码过期","operationId":"check_scan_status_api_login_scan_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/login/bizlogin":{"post":{"tags":["登录"],"summary":"完成登录","description":"扫码确认后调用此接口完成登录，成功后凭证自动保存到 `.env`。\n\n**返回：** Token、Cookie、FakeID、昵称等登录凭证","operationId":"biz_login_api_login_bizlogin_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/login/manual":{"post":{"tags":["登录"],"summary":"手动配置登录凭证","description":"手动提交登录凭证（适用于已通过其他方式获取凭证的场景）。\n\n**请求体参数：**\n- **token** (必填): 微信 Token\n- **cookie** (必填): 微信 Cookie\n- **fakeid** (可选): 公众号 FakeID\n- **nickname** (可选): 公众号昵称\n- **expire_time** (可选): 过期时间戳","operationId":"manual_login_api_login_manual_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/login/info":{"get":{"tags":["登录"],"summary":"获取登录信息","description":"获取当前登录用户的昵称、FakeID、过期时间等信息。","operationId":"get_login_info_api_login_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/image":{"get":{"tags":["图片代理"],"summary":"图片代理下载","description":"代理下载微信图片，避免防盗链\n\nArgs:\n    url: 图片URL（仅允许微信CDN域名）\n\nReturns:\n    图片数据流\n\nRaises:\n    HTTPException: 当下载失败时","operationId":"proxy_image_api_image_get","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","description":"图片URL","title":"Url"},"description":"图片URL"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/rss/subscribe":{"post":{"tags":["RSS 订阅"],"summary":"添加 RSS 订阅","description":"添加一个公众号到 RSS 订阅列表。\n\n添加后，后台轮询器会定时拉取该公众号的最新文章。\n\n**请求体参数：**\n- **fakeid** (必填): 公众号 FakeID，通过搜索接口获取\n- **nickname** (可选): 公众号名称\n- **alias** (可选): 公众号微信号\n- **head_img** (可选): 公众号头像 URL","operationId":"subscribe_api_rss_subscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/rss/subscribe/{fakeid}":{"delete":{"tags":["RSS 订阅"],"summary":"取消 RSS 订阅","description":"取消订阅一个公众号，同时删除该公众号的缓存文章。\n\n**路径参数：**\n- **fakeid**: 公众号 FakeID","operationId":"unsubscribe_api_rss_subscribe__fakeid__delete","parameters":[{"name":"fakeid","in":"path","required":true,"schema":{"type":"string","title":"Fakeid"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/rss/subscriptions":{"get":{"tags":["RSS 订阅"],"summary":"获取订阅列表","description":"获取当前所有 RSS 订阅的公众号列表。\n\n返回每个订阅的基本信息、缓存文章数和 RSS 地址。","operationId":"get_subscriptions_api_rss_subscriptions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionListResponse"}}}}}}},"/api/rss/poll":{"post":{"tags":["RSS 订阅"],"summary":"手动触发轮询","description":"手动触发一次轮询，立即拉取所有订阅公众号的最新文章。\n\n通常用于首次订阅后立即获取文章，无需等待下一个轮询周期。","operationId":"trigger_poll_api_rss_poll_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollerStatusResponse"}}}}}}},"/api/rss/status":{"get":{"tags":["RSS 订阅"],"summary":"轮询器状态","description":"获取 RSS 轮询器运行状态。","operationId":"poller_status_api_rss_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollerStatusResponse"}}}}}}},"/api/rss/all":{"get":{"tags":["RSS 订阅"],"summary":"聚合 RSS 订阅源","description":"获取所有订阅公众号的聚合 RSS 2.0 订阅源。\n\n将此地址添加到 RSS 阅读器，即可在一个订阅源中查看所有公众号文章。\n订阅增减后自动生效，无需更换链接。","operationId":"get_aggregated_rss_feed_api_rss_all_get","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"文章数量上限","default":50,"title":"Limit"},"description":"文章数量上限"}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/rss/export":{"get":{"tags":["RSS 订阅"],"summary":"导出订阅列表","description":"导出当前订阅列表。\n\n- **csv**: 包含公众号名称、FakeID、RSS 地址、文章数、订阅时间\n- **opml**: 标准 OPML 格式，可直接导入 RSS 阅读器","operationId":"export_subscriptions_api_rss_export_get","parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","pattern":"^(csv|opml)$","description":"导出格式: csv 或 opml","default":"csv","title":"Format"},"description":"导出格式: csv 或 opml"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/rss/{fakeid}":{"get":{"tags":["RSS 订阅"],"summary":"获取 RSS 订阅源","description":"获取指定公众号的 RSS 2.0 订阅源（XML 格式）。\n\n将此地址添加到任何 RSS 阅读器即可订阅公众号文章。\n\n**路径参数：**\n- **fakeid**: 公众号 FakeID\n\n**查询参数：**\n- **limit** (可选): 返回文章数量上限，默认 20","operationId":"get_rss_feed_api_rss__fakeid__get","parameters":[{"name":"fakeid","in":"path","required":true,"schema":{"type":"string","title":"Fakeid"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"文章数量上限","default":20,"title":"Limit"},"description":"文章数量上限"}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ArticleData":{"properties":{"title":{"type":"string","title":"Title","description":"文章标题"},"content":{"type":"string","title":"Content","description":"文章 HTML 正文（保留原始排版）"},"plain_content":{"type":"string","title":"Plain Content","description":"纯文本正文（去除所有 HTML 标签，适合直接阅读或 AI 处理）","default":""},"images":{"items":{"type":"string"},"type":"array","title":"Images","description":"文章内图片 URL 列表"},"author":{"type":"string","title":"Author","description":"作者","default":""},"publish_time":{"type":"integer","title":"Publish Time","description":"发布时间戳（秒）","default":0},"publish_time_str":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Publish Time Str","description":"可读发布时间，如 2026-02-24 09:00:00"}},"type":"object","required":["title","content"],"title":"ArticleData","description":"文章数据"},"ArticleRequest":{"properties":{"url":{"type":"string","title":"Url","description":"微信文章链接，如 https://mp.weixin.qq.com/s/xxxxx"}},"type":"object","required":["url"],"title":"ArticleRequest","description":"文章请求"},"ArticleResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"是否成功"},"data":{"anyOf":[{"$ref":"#/components/schemas/ArticleData"},{"type":"null"}],"description":"文章数据，失败时为 null"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"错误信息，成功时为 null"}},"type":"object","required":["success"],"title":"ArticleResponse","description":"文章响应"},"ArticlesResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"data":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Data"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["success"],"title":"ArticlesResponse","description":"文章列表响应"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LoginRequest":{"properties":{"token":{"type":"string","title":"Token"},"cookie":{"type":"string","title":"Cookie"},"fakeid":{"type":"string","title":"Fakeid"},"nickname":{"type":"string","title":"Nickname"},"expire_time":{"type":"integer","title":"Expire Time"}},"type":"object","required":["token","cookie","fakeid","nickname","expire_time"],"title":"LoginRequest","description":"手动登录请求模型"},"LoginResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"}},"type":"object","required":["success","message"],"title":"LoginResponse","description":"登录响应模型"},"PollerStatusResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"data":{"type":"object","title":"Data","default":{}}},"type":"object","required":["success"],"title":"PollerStatusResponse"},"SearchResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"data":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Data"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["success"],"title":"SearchResponse","description":"搜索响应模型"},"StatsResponse":{"properties":{"rate_limit":{"type":"object","title":"Rate Limit"}},"type":"object","required":["rate_limit"],"title":"StatsResponse","description":"统计响应","example":{"rate_limit":{"active_ips":2,"article_requests":3,"global_limit":10,"global_requests":5}}},"StatusResponse":{"properties":{"authenticated":{"type":"boolean","title":"Authenticated"},"loggedIn":{"type":"boolean","title":"Loggedin"},"account":{"type":"string","title":"Account"},"nickname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nickname","default":""},"fakeid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fakeid","default":""},"expireTime":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expiretime","default":0},"isExpired":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Isexpired","default":false},"status":{"type":"string","title":"Status"}},"type":"object","required":["authenticated","loggedIn","account","status"],"title":"StatusResponse","description":"状态响应模型"},"SubscribeRequest":{"properties":{"fakeid":{"type":"string","title":"Fakeid","description":"公众号 FakeID"},"nickname":{"type":"string","title":"Nickname","description":"公众号名称","default":""},"alias":{"type":"string","title":"Alias","description":"公众号微信号","default":""},"head_img":{"type":"string","title":"Head Img","description":"头像 URL","default":""}},"type":"object","required":["fakeid"],"title":"SubscribeRequest"},"SubscribeResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message","default":""}},"type":"object","required":["success"],"title":"SubscribeResponse"},"SubscriptionListResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"data":{"items":{},"type":"array","title":"Data","default":[]}},"type":"object","required":["success"],"title":"SubscriptionListResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}