OpenAPI

统一接口服务。线上入口:https://openapi.rrrosmontis.icu

聚合层把 pixiv 图片服务与 bilibili 视频服务收敛到单一对外入口。三个后端进程全部只监听 127.0.0.1,对外仅由 nginx 暴露 80/443——即"一个入口、零暴露端口"。

架构

公网 443/80  nginx (server_name openapi.rrrosmontis.icu)
  ├── /pixiv/get_image?id=xxx      -> 127.0.0.1:9008 main.py 聚合层 -> 127.0.0.1:9007 pixiv
  ├── /bilibili/get_video?bv=xxx   -> 127.0.0.1:9008 main.py 聚合层 -> 127.0.0.1:9006 bilibili
  ├── /img-master/ /img-original/  -> nginx 直接反代 i.pximg.net(无本地后端)
  └── /                            -> 127.0.0.1:9008(302 跳转文章页)

端口与进程

服务 监听 入口源码 说明
openapi 127.0.0.1:9008 source/main.py(aiohttp) 聚合层,纯转发,唯一入口
pixiv 127.0.0.1:9007 source/pixiv/pixiv.py(Flask + waitress) 图片代理
bilibili 127.0.0.1:9006 source/bilibili/bilibili.py(aiohttp + yt-dlp) 视频代理
pixiv-token-refresh — source/pixiv/refresh_token.py token 刷新守护(每 30–60 分钟随机)
bilibili-refresh — source/bilibili/refresh_cookie.py cookie 刷新守护(每 50–70 分钟随机)

历史端口 9888 / 9088 / 19990 已于 2026-09-12 废弃,全部改为上述 900x。 pixiv 早期误绑 0.0.0.0:9088 对公网裸奔(绕过 nginx 的日志与限流),现已收口为 127.0.0.1。

结构

source/
├── main.py                       # 聚合层 (127.0.0.1:9008),三条路由:/ /pixiv/get_image /bilibili/get_video
├── pixiv/
│   ├── pixiv.py                  # Pixiv 图片服务 (127.0.0.1:9007)
│   ├── refresh_token.py          # Pixiv OAuth token 刷新守护
│   └── tokens.template.json      # token 模板(实际 tokens.json 不入库)
├── bilibili/
│   ├── bilibili.py               # bilibili 视频服务 (127.0.0.1:9006)
│   ├── refresh_cookie.py         # cookie 定时刷新守护
│   ├── qr_login.py               # 扫码登录获取 cookie
│   └── qr_login_fast.py
└── cache/                        # 运行时生成,不入库
    ├── pixiv/images              # 图片缓存
    └── bilibili/                 # 视频缓存
nginx/
└── openapi.rrrosmontis.icu.conf   # 统一入口(/pixiv/ /bilibili/ /img-master/ /img-original/)
systemd/
├── openapi.service                # 聚合层
├── pixiv.service                  # Pixiv 图片服务(waitress --threads=8)
├── bilibili.service               # bilibili 视频服务
├── bilibili-refresh.service       # cookie 刷新守护
└── pixiv-token-refresh.service    # Pixiv token 刷新守护
docs/
└── 部署与运维.md                   # 线上服务器的路径、缓存、迁移步骤与变更记录

缓存机制

pixiv(图片):check_cache() 以 glob 命中即直接回文件;未命中按 官方 App API → pixiv.re → pixiv.cat 三级回退抓取,落盘用 .tmp + os.replace 原子写。

缓存目录不再硬编码,由模块位置推导:

IMAGE_DIR = (Path(__file__).resolve().parent / "../cache/pixiv/images").resolve()
IMAGE_DIR.mkdir(parents=True, exist_ok=True)

即 source/cache/pixiv/images;线上常用 /home/images 软链指向它,便于访问。

bilibili(视频):以 BV 号为键缓存到 source/cache/bilibili/{BV}.mp4

  • 命中即直接 FileResponse,不再调用 yt-dlp
  • 未命中才下载,且先落到缓存目录内的隐藏暂存目录 .dl-XXXX,成功后 os.replace 原子落盘
  • 无论成功 / 失败 / 超时都会 shutil.rmtree(tmpdir) —— 早期实现只清理 cookie 临时文件、从不清理视频暂存目录,导致每次取视频都把完整视频永久留在 /tmp(无上限磁盘泄漏),已修复
  • 淘汰策略:单文件 CACHE_TTL_SECONDS(默认 7 天)未访问即过期;总量超过 CACHE_MAX_BYTES(默认 2 GiB)时按 mtime 从最旧开始删除
  • 命中/落盘会在日志打印 cache HIT / MISS / STORE(已 flush=True,实时可见)

运维接口(只绑本机):

curl -s 127.0.0.1:9006/bilibili/cache_info
# {cache_dir, cache_max_bytes, cache_ttl_seconds, count, total_bytes, free_bytes, files[]}

部署

  1. Python 环境:三服务共用一个环境,需含 flask、waitress、aiohttp、httpx、yt-dlp
  2. 凭据:
    • 复制 source/pixiv/tokens.template.json 为 source/pixiv/tokens.json(chmod 600)并填入实际 pixiv token
    • 放置 source/bilibili/cookies.txt(name=value 格式),或运行 qr_login.py 扫码生成
  3. 服务:将 systemd/*.service 安装到 /etc/systemd/system/,然后 systemctl daemon-reload && systemctl enable --now openapi pixiv bilibili bilibili-refresh pixiv-token-refresh
  4. nginx:将 nginx/openapi.rrrosmontis.icu.conf 放入 /etc/nginx/conf.d/(需存在 $connection_upgrade 的 map 定义),nginx -t && systemctl reload nginx
  5. 软链(可选):ln -s <部署根>/source/cache/pixiv/images /home/images
  6. 定时任务:无 cron/timer——两个刷新守护均为常驻循环(内部随机间隔),systemd Restart=always 兜底

验证

curl -k "https://openapi.rrrosmontis.icu/pixiv/get_image?id=147113746"
curl -k "https://openapi.rrrosmontis.icu/bilibili/get_video?bv=BV16a41157Q4"
curl -kI "https://openapi.rrrosmontis.icu/bilibili/get_video?bv=BV16a41157Q4"   # 只看头部,省流量
curl -s 127.0.0.1:9006/bilibili/cache_info

端口暴露自检(三个后端都应"不可达",仅 443/80 通):

for p in 9006 9007 9008; do timeout 3 bash -c "cat < /dev/null > /dev/tcp/<host>/$p" 2>/dev/null \
  && echo "$p 可连通(异常)" || echo "$p 不可达(正常)"; done

版本要点

  • 2026-09-12
    • 端口重排 9888/9088/19990 → 9008/9007/9006,全部仅绑 127.0.0.1;pixiv 由 0.0.0.0:9088 收口
    • 主入口 main.py 从 source/openapi/ 上移到 source/,systemd WorkingDirectory 同步为 source/
    • pixiv 缓存路径由硬编码 /home/pixiv/images 改为相对 ../cache/pixiv/images
    • pixiv 改由 waitress 线程池承载(--threads=8),替代 Flask 开发服务器(thread-per-request 无上限)
    • bilibili 新增 BV 真缓存(../cache/bilibili,2 GiB / 7 天淘汰),并修复视频暂存目录永不清理导致的 /tmp 泄漏
    • 新增 /bilibili/cache_info 运维接口;缓存日志加 flush=True
  • 2026-09-02:新增 pixiv token 刷新守护;补 /img-original/ 反代(App API 原图路径)
  • 2026-07-31:三服务迁移落位(Python 环境合并为单一 general)
S
Description
No description provided
Readme
223 KiB
Languages
Python 100%