<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>扣扣空间</title><description>日常技术分享与实践</description><link>https://blog.yukiryou.top/</link><language>zh_CN</language><item><title>Setu Cloud v2.5 音乐功能重磅上线！</title><link>https://blog.yukiryou.top/posts/setu_cloud_v25/</link><guid isPermaLink="true">https://blog.yukiryou.top/posts/setu_cloud_v25/</guid><description>全新网易云音乐集成功能，打造一站式娱乐控制台</description><pubDate>Sat, 27 Dec 2025 22:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;序言&lt;/h1&gt;
&lt;p&gt;距离 Setu Cloud v2 正式上线已经过去两周了，这段时间收到了很多小伙伴的反馈和建议。在保持原有图片 API 服务稳定运行的基础上，我们决定做一些&quot;不务正业&quot;的事情——给控制台加入音乐播放功能！&lt;/p&gt;
&lt;p&gt;没错，现在你可以一边管理 API Key，一边听着网易云音乐放松心情了。这次更新不仅仅是简单的功能堆砌，而是从用户体验出发，打造了一套完整的音乐管理系统。&lt;/p&gt;
&lt;p&gt;Setu Cloud 地址: &lt;a href=&quot;https://cloud.yukiryou.icu/&quot;&gt;https://cloud.yukiryou.icu/&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;核心更新&lt;/h1&gt;
&lt;h3&gt;1. 全局音乐播放器&lt;/h3&gt;
&lt;p&gt;我们在控制台底部集成了一个&lt;strong&gt;全局音乐播放器&lt;/strong&gt;，无论你切换到哪个页面，音乐都不会停止。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特性：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;固定底部设计&lt;/strong&gt;：采用毛玻璃效果，与整体 UI 风格完美融合&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;展开/收缩模式&lt;/strong&gt;：可一键切换简洁/完整模式，节省屏幕空间&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;完整播放控制&lt;/strong&gt;：上一曲、播放/暂停、下一曲、播放模式切换&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实时进度条&lt;/strong&gt;：可拖拽跳转到任意时间点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;音量调节&lt;/strong&gt;：支持静音和音量滑块控制&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;歌词展示&lt;/strong&gt;：点击展开歌词面板，支持点击跳转、自动滚动跟踪&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;预览&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-12-27-22-05-32-image.4ZbK4EV4.png&quot; alt=&quot;播放器&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;2. 音乐搜索与播放&lt;/h3&gt;
&lt;p&gt;集成了网易云音乐 API，可以搜索海量曲库并在线播放。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;核心功能：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;智能搜索&lt;/strong&gt;：支持歌曲名、歌手、专辑全文检索&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;快速操作&lt;/strong&gt;：每首歌提供 4 个快捷按钮
&lt;ul&gt;
&lt;li&gt;🎵 &lt;strong&gt;播放&lt;/strong&gt;：立即播放并加入播放列表&lt;/li&gt;
&lt;li&gt;📋 &lt;strong&gt;添加到播放列表&lt;/strong&gt;：仅添加不播放，适合批量收藏&lt;/li&gt;
&lt;li&gt;➕ &lt;strong&gt;添加到歌单&lt;/strong&gt;：保存到自定义歌单&lt;/li&gt;
&lt;li&gt;⬇️ &lt;strong&gt;下载&lt;/strong&gt;：一键下载高品质音频&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;字段映射优化&lt;/strong&gt;：完美适配网易云 API 返回格式&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;超时处理&lt;/strong&gt;：30 秒超时配置，避免长时间等待&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;预览&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-12-27-22-06-11-image.BBijBQIT.png&quot; alt=&quot;音乐搜索&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;3. 我的歌单&lt;/h3&gt;
&lt;p&gt;支持创建自定义歌单，管理你的音乐收藏。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;歌单管理功能：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;创建歌单&lt;/strong&gt;：自定义名称、描述、封面 URL&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;编辑歌单&lt;/strong&gt;：随时修改歌单信息&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;播放模式&lt;/strong&gt;：支持 4 种播放模式
&lt;ul&gt;
&lt;li&gt;顺序播放：按顺序播放到最后停止&lt;/li&gt;
&lt;li&gt;随机播放：随机选择下一首&lt;/li&gt;
&lt;li&gt;列表循环：播放完自动回到第一首&lt;/li&gt;
&lt;li&gt;单曲循环：重复播放当前歌曲&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;歌曲排序&lt;/strong&gt;：拖拽调整播放顺序&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;一键播放&lt;/strong&gt;：直接播放整个歌单&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;公开/私密&lt;/strong&gt;：控制歌单是否对外可见&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;预览&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-12-27-22-06-33-image.Dt0Kk-vO.png&quot; alt=&quot;我的歌单&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;4. 播放历史&lt;/h3&gt;
&lt;p&gt;自动记录播放历史，最多保留 50 条记录。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;历史功能亮点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;智能时间显示&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;1 分钟内 → &quot;刚刚&quot;&lt;/li&gt;
&lt;li&gt;1 小时内 → &quot;5 分钟前&quot;&lt;/li&gt;
&lt;li&gt;今天 → &quot;今天 14:30&quot;&lt;/li&gt;
&lt;li&gt;昨天 → &quot;昨天 20:15&quot;&lt;/li&gt;
&lt;li&gt;其他 → &quot;12 月 25 日 18:00&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;分页浏览&lt;/strong&gt;：支持 10/20/50 条每页&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;快速播放&lt;/strong&gt;：点击历史记录直接播放&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;清空历史&lt;/strong&gt;：一键清空所有记录&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;预览&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-12-27-22-08-03-image.WB4qNZUT.png&quot; alt=&quot;播放历史&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;5. 播放列表管理&lt;/h3&gt;
&lt;p&gt;类似网易云音乐的播放队列功能。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;列表特性：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;实时队列&lt;/strong&gt;：显示当前播放列表&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;音波动画&lt;/strong&gt;：正在播放的歌曲有动态指示器&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;快速操作&lt;/strong&gt;：点击播放、移除歌曲、清空列表&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数字徽章&lt;/strong&gt;：显示列表中的歌曲数量&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;抽屉设计&lt;/strong&gt;：侧边滑出，不遮挡主要内容&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1&gt;技术实现细节&lt;/h1&gt;
&lt;p&gt;这次音乐功能的实现，涉及了不少技术挑战：&lt;/p&gt;
&lt;h3&gt;前端架构&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;全局状态管理&lt;/strong&gt;：使用 Pinia 管理音乐播放状态、歌单、历史记录&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTML5 Audio API&lt;/strong&gt;：原生 audio 元素控制播放&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动播放优化&lt;/strong&gt;：监听 &lt;code&gt;canplay&lt;/code&gt; 事件，确保音频加载完成后再播放&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;歌词解析&lt;/strong&gt;：正则表达式解析 LRC 格式歌词 &lt;code&gt;[mm:ss.xx]歌词内容&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;播放模式逻辑&lt;/strong&gt;：根据不同模式计算下一曲索引&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;后端集成&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;网易云 Token 管理&lt;/strong&gt;：管理员可配置多个 Cookie，自动轮换使用&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;播放历史存储&lt;/strong&gt;：每次播放自动调用后端 API 记录&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;字段映射&lt;/strong&gt;：前端转换网易云 API 字段 (ar→artists, al→album, dt→duration)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;用户体验优化&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;请求超时&lt;/strong&gt;：默认 30 秒超时，搜索结果限制 10 条避免卡顿&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;毛玻璃效果&lt;/strong&gt;：backdrop-filter: blur(20px) 打造视觉统一性&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;响应式设计&lt;/strong&gt;：移动端自动隐藏部分信息，保持界面简洁&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;平滑动画&lt;/strong&gt;：过渡动画让交互更流畅&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1&gt;快速上手指南&lt;/h1&gt;
&lt;p&gt;想要体验音乐功能？只需两步：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一步：登录控制台&lt;/strong&gt;
访问 Setu Cloud 官网并登录你的账号。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二步：开始听歌&lt;/strong&gt;
在左侧菜单点击 &lt;strong&gt;「音乐搜索」&lt;/strong&gt;，输入你想听的歌曲，点击播放按钮即可。底部会出现全局播放器，切换页面也不会停止播放！&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可选：创建歌单&lt;/strong&gt;
点击 &lt;strong&gt;「我的歌单」&lt;/strong&gt; -&amp;gt; &lt;strong&gt;「创建新歌单」&lt;/strong&gt;，输入歌单名称和描述，然后从搜索页面添加歌曲到歌单。下次可以直接播放整个歌单。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;可选：查看历史&lt;/strong&gt;
点击 &lt;strong&gt;「播放历史」&lt;/strong&gt;，可以看到最近播放的 50 首歌曲，点击即可重新播放。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;技术栈更新&lt;/h1&gt;
&lt;p&gt;音乐功能基于以下技术实现：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;前端：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vue 3 Composition API (script setup)&lt;/li&gt;
&lt;li&gt;Pinia 状态管理 (音乐 store)&lt;/li&gt;
&lt;li&gt;HTML5 Audio API&lt;/li&gt;
&lt;li&gt;Naive UI (NModal, NDrawer, NBadge 等组件)&lt;/li&gt;
&lt;li&gt;TypeScript 严格类型检查&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;后端集成：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;网易云音乐 API 代理&lt;/li&gt;
&lt;li&gt;Cookie 池管理与轮换&lt;/li&gt;
&lt;li&gt;播放历史持久化存储&lt;/li&gt;
&lt;li&gt;歌单 CRUD 接口&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;优化细节：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;音频预加载与缓冲处理&lt;/li&gt;
&lt;li&gt;歌词实时滚动算法&lt;/li&gt;
&lt;li&gt;播放模式状态机&lt;/li&gt;
&lt;li&gt;全局播放器生命周期管理&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1&gt;已知问题 &amp;amp; 后续计划&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;已知问题：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;部分歌曲因版权原因无法播放（网易云 API 限制）&lt;/li&gt;
&lt;li&gt;歌词可能存在时间轴不准的情况（取决于网易云数据质量）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;后续计划：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ ] 支持歌单分享功能&lt;/li&gt;
&lt;li&gt;[ ] 添加歌词翻译显示&lt;/li&gt;
&lt;li&gt;[ ] 引入歌手/专辑详情页&lt;/li&gt;
&lt;li&gt;[ ] 支持本地上传音乐&lt;/li&gt;
&lt;li&gt;[ ] 添加音乐可视化效果&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1&gt;结语&lt;/h1&gt;
&lt;p&gt;Setu Cloud 从一个简单的图片 API 服务，逐渐演变成了一个多功能的娱乐控制台。音乐功能的加入，让开发者在管理 API 的同时也能享受片刻的放松。&lt;/p&gt;
&lt;p&gt;这次更新耗时约一周，从需求设计到功能实现，再到 UI 打磨，每一个细节都经过了反复推敲。虽然&quot;不务正业&quot;，但确实提升了使用控制台的幸福感😊&lt;/p&gt;
&lt;p&gt;欢迎大家登录体验，如果有任何建议或遇到 BUG，欢迎通过邮件或 QQ 反馈！&lt;/p&gt;
&lt;p&gt;说个题外话，一边写代码一边循环播放《昔涟》真的很上头，崩铁的音乐制作真的绝了！推荐大家搜索试试这首歌～&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;strong&gt;相关链接：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setu Cloud: &lt;a href=&quot;https://cloud.yukiryou.icu/&quot;&gt;https://cloud.yukiryou.icu/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;反馈邮箱: yuki@yukiryou.online&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Setu Cloud v2正式上线！</title><link>https://blog.yukiryou.top/posts/setu_cloud-v2/</link><guid isPermaLink="true">https://blog.yukiryou.top/posts/setu_cloud-v2/</guid><description>setu_cloud用户端正式上线，主要还是以学习为目的</description><pubDate>Sat, 13 Dec 2025 22:30:00 GMT</pubDate><content:encoded>&lt;h1&gt;序言&lt;/h1&gt;
&lt;p&gt;最近一段时间没有更新博客了主要原因就是在写需求文档然后空闲时间在给setu_api完善好并写一个用户端和管理端。时间紧每天太累了，懒得更新了就。不过现在也是正式完工了。不过写什么都是以学习为目的，以交流为主，有问题希望锐评我。&lt;/p&gt;
&lt;p&gt;Setu Cloud地址:&lt;a href=&quot;https://cloud.yukiryou.icu/&quot;&gt;https://cloud.yukiryou.icu/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;相比于 v1 版本，v2 不仅仅是一次简单的版本号迭代，更是从交互体验到底层架构的一次全面升级。引入了全新的设计语言，重写了 API 管理逻辑，旨在为开发者提供更稳定、更美观、更易用的图片 API 服务。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;核心更新&lt;/h1&gt;
&lt;h3&gt;1.UI设计&lt;/h3&gt;
&lt;p&gt;我们抛弃了传统枯燥的后台管理界面，基于 &lt;strong&gt;Naive UI&lt;/strong&gt; 打造了一套全新的“极光毛玻璃”设计系统。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;沉浸式体验&lt;/strong&gt;：全站背景采用动态模糊与半透明卡片设计，视觉层次丰富。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;响应式布局&lt;/strong&gt;：无论是桌面大屏还是移动端，控制台都能完美适配，随时随地管理你的服务。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;预览&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-12-13-23-14-59-image.CXooTaJC.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;2. 更加灵活的 API Key 管理&lt;/h3&gt;
&lt;p&gt;在 v2 版本中，我们引入了更完善的鉴权机制。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;自主创建&lt;/strong&gt;：用户登录控制台后，可自助创建多个 API Key，用于区分不同的项目或环境。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;配额可视化&lt;/strong&gt;：在仪表盘中，你可以实时查看每个 Key 的&lt;code&gt;今日调用&lt;/code&gt;、&lt;code&gt;总调用&lt;/code&gt;以及&lt;code&gt;剩余配额&lt;/code&gt;，用量一目了然。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;安全可控&lt;/strong&gt;：支持随时重命名、禁用或删除泄露的 Key，保障账户安全。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;预览&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-12-13-23-18-53-image.MkgMVZcE.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;3. 服务稳定性提升&lt;/h3&gt;
&lt;p&gt;后端架构进行了优化，引入了更完善的 IP 频率限制与黑名单防御机制，有效防止恶意刷接口导致的服务波动，确保正常用户的请求更加极速、稳定。&lt;/p&gt;
&lt;h3&gt;看板娘预览&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-12-13-23-22-00-image.DN6azugU.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;快速上手指南&lt;/h1&gt;
&lt;p&gt;想要使用 Setu Cloud v2 的服务非常简单，只需三步：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一步：注册与登录&lt;/strong&gt; 访问 Setu Cloud 官网，使用邮箱注册账号。登录后，你将直接进入全新的用户仪表盘。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二步：获取 API Key&lt;/strong&gt; 在左侧菜单点击 &lt;strong&gt;「API Key 管理」&lt;/strong&gt; -&amp;gt; &lt;strong&gt;「新建 API Key」&lt;/strong&gt;。 输入一个备注名称（例如 &quot;My Blog&quot;），点击创建。系统会生成一串密钥，请务必立即复制并保存。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三步：发起调用&lt;/strong&gt; 现在，你可以使用任何 HTTP 客户端调用接口了。记得在 Header 中带上你的 Key：&lt;/p&gt;
&lt;p&gt;Bash&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 示例：使用 cURL 调用
curl -X GET &quot;https://api.yukiryou.icu/setu/v2&quot; \
     -H &quot;X-API-Key: sk-你的密钥&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;技术栈一览&lt;/h1&gt;
&lt;p&gt;对于感兴趣的开发者，Setu Cloud v2 的前端构建于以下现代技术栈之上：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;核心框架&lt;/strong&gt;：Vue 3 (Script Setup)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;构建工具&lt;/strong&gt;：Vite 5&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;UI 组件库&lt;/strong&gt;：Naive UI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;状态管理&lt;/strong&gt;：Pinia&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;语言&lt;/strong&gt;：TypeScript&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;结语&lt;/h1&gt;
&lt;p&gt;Setu Cloud 的初衷是提供简单、好用的二次元图片接口服务。v2 的上线是一个新的开始，未来我们将持续引入更多实用的功能（如更多维度的图片筛选、图库搜索等）。&lt;/p&gt;
&lt;p&gt;欢迎大家注册体验，如果有任何建议或遇到 BUG，欢迎通过邮件或 QQ 提交反馈！&lt;/p&gt;
&lt;p&gt;说个题外话，今天打一下午未许之地突袭8，谁能告诉我这玩意到底怎么过，越打越破防。
&lt;img src=&quot;https://blog.yukiryou.top/_astro/987f5c8f6b10836f7f3c05ac51e0bcbb.lVS1t2i0.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>二次元随机美图api</title><link>https://blog.yukiryou.top/posts/setu_api/</link><guid isPermaLink="true">https://blog.yukiryou.top/posts/setu_api/</guid><description>把pixiv的图片信息存储在数据库中，并提供代理服务</description><pubDate>Thu, 04 Dec 2025 02:22:00 GMT</pubDate><content:encoded>&lt;h1&gt;起因&lt;/h1&gt;
&lt;p&gt;一直以来总想根据自己的性趣去部署一个图片api，最近购置了阿里云服务器进行备案，就干脆把阿里云的服务器拿来搭建好了。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;API v2&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://www.pixiv.net/&quot;&gt;https://api.yukiryou.icu/setu/v2&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;接口地址（GET / POST 通用）&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;
/setu/v2

&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;返回格式：JSON&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1&gt;请求参数说明&lt;/h1&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数名&lt;/th&gt;
&lt;th&gt;数据类型&lt;/th&gt;
&lt;th&gt;默认值&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;r18&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0 非 R18，1 R18，2 混合&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;num&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;返回数量，范围 1–20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;uid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;int[]&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;按作者 UID 过滤（最多 20 个）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;keyword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;标题 / 作者 / 标签模糊匹配&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tag&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string[]&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;标签 AND / OR 组合匹配&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string[]&lt;/td&gt;
&lt;td&gt;[&quot;original&quot;]&lt;/td&gt;
&lt;td&gt;返回图片尺寸（可多选）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;proxy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;i.pixiv.re&lt;/td&gt;
&lt;td&gt;替换图片 URL 域名&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dateAfter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;long&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;上传时间 ≥ 此时间（毫秒）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dateBefore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;long&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;上传时间 ≤ 此时间（毫秒）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dsc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;禁用自动缩写转换&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;excludeAI&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;排除 AI 作品（aiType = 2）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aspectRatio&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;图片宽高比过滤&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h1&gt;标签（tag）高级匹配规则&lt;/h1&gt;
&lt;p&gt;标签匹配支持 AND / OR 组合，大小写不敏感。&lt;/p&gt;
&lt;h2&gt;AND 规则（数组之间）&lt;/h2&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
tag=萝莉|少女

tag=黑丝|白丝

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这代表：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
(萝莉 OR 少女) AND (黑丝 OR 白丝)

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;OR 规则（同一个字符串内用 &lt;code&gt;|&lt;/code&gt; 分隔）&lt;/h2&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
tag=巨乳|おっぱい

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;表示匹配其中任意一个即可。&lt;/p&gt;
&lt;h2&gt;匹配范围：&lt;/h2&gt;
&lt;p&gt;| 字段 | 是否参与匹配 |&lt;/p&gt;
&lt;p&gt;|------|-------------|&lt;/p&gt;
&lt;p&gt;| 标签（tags） | ✔ |&lt;/p&gt;
&lt;p&gt;| 标题（title） | ✔ |&lt;/p&gt;
&lt;p&gt;| 作者（author） | ✔ |&lt;/p&gt;
&lt;p&gt;全部以 &lt;strong&gt;小写&lt;/strong&gt; + &lt;strong&gt;包含（contains）匹配&lt;/strong&gt;方式处理。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;GET 示例&lt;/h1&gt;
&lt;h2&gt;1️⃣ 获取 1 个非 R18 的随机图（默认 original 尺寸）&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
GET https://api.yukiryou.icu/setu/v2

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2️⃣ 获取 5 张 original + regular 尺寸图片&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
GET https://api.yukiryou.icu/setu/v2?num=5&amp;amp;size=original&amp;amp;size=regular

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3️⃣ 标签高级匹配示例&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
GET https://api.yukiryou.icu/setu/v2?tag=萝莉|少女&amp;amp;tag=白丝|黑丝

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;即：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
(萝莉 OR 少女) AND (白丝 OR 黑丝)

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;4️⃣ 按关键字模糊搜索&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
GET https://api.yukiryou.icu/setu/v2?keyword=碧蓝航线

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;5️⃣ 按作者 uid 搜索&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
GET https://api.yukiryou.icu/setu/v2?uid=12345&amp;amp;uid=67890

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;6️⃣ 限制长宽比&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
GET https://api.yukiryou.icu/setu/v2?aspectRatio=1.6-1.8

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;7️⃣ 过滤 AI 图&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
GET https://api.yukiryou.icu/setu/v2?excludeAI=true

&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h1&gt;📨 POST 示例&lt;/h1&gt;
&lt;p&gt;POST 支持 JSON 的二维 tag：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
{

  &quot;num&quot;: 5,

  &quot;r18&quot;: 0,

  &quot;tag&quot;: [

    [&quot;萝莉&quot;, &quot;少女&quot;],

    [&quot;黑丝&quot;, &quot;白丝&quot;]

  ],

  &quot;size&quot;: [&quot;original&quot;, &quot;regular&quot;, &quot;small&quot;],

  &quot;excludeAI&quot;: false

}

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;就是：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
tag=萝莉|少女

tag=黑丝|白丝

&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h1&gt;返回格式&lt;/h1&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
{

  &quot;error&quot;: &quot;&quot;,

  &quot;data&quot;: [

    {

      &quot;pid&quot;: 82675630,

      &quot;p&quot;: 0,

      &quot;uid&quot;: 8244461,

      &quot;title&quot;: &quot;水着ル・マラン&quot;,

      &quot;author&quot;: &quot;Vldjm13&quot;,

      &quot;r18&quot;: false,

      &quot;width&quot;: 3360,

      &quot;height&quot;: 3960,

      &quot;tags&quot;: [&quot;アズールレーン&quot;,&quot;碧蓝航线&quot;,&quot;水着&quot;],

      &quot;ext&quot;: &quot;png&quot;,

      &quot;aiType&quot;: 0,

      &quot;uploadDate&quot;: 1593535904000,

      &quot;urls&quot;: {

        &quot;original&quot;: &quot;https://i.yukiryou.top/img-original/...png&quot;,

        &quot;regular&quot;: &quot;https://i.yukiryou.top/img-master/..._master1200.jpg&quot;,

        &quot;small&quot;: &quot;/c/540x540_70/img-master/..._master1200.jpg&quot;,

        &quot;thumb&quot;: &quot;/c/250x250_80_a2/img-master/..._square1200.jpg&quot;,

        &quot;mini&quot;: &quot;/c/48x48/img-master/..._square1200.jpg&quot;

      }

    }

  ]

}

&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h1&gt;🔄 图片 URL 自动生成逻辑&lt;/h1&gt;
&lt;p&gt;你只需要 original，即：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/img-original/.../90551655_p0.jpg
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;API 会自动生成：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;size&lt;/th&gt;
&lt;th&gt;URL 规则&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;original&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/img-original/.../90551655_p0.jpg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;regular&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/img-master/.../p0_master1200.jpg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;small&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/c/540x540_70/img-master/..._master1200.jpg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;thumb&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/c/250x250_80_a2/img-master/..._square1200.jpg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mini&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/c/48x48/img-master/..._square1200.jpg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h1&gt;⚠️ 注意事项&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;num 最大为 20&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;original 为唯一保证存在的尺寸&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;PNG 原图不一定有 regular/small/thumb/mini&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;标签大小写不敏感&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;tag 与 keyword 组合可能降低性能&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h1&gt;其他服务&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://yukiryou.icu/posts/api_plugin/&quot;&gt;QQ Bot&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;后续可能优化一下并公开插件&lt;/p&gt;
</content:encoded></item><item><title>QQbot插件优化</title><link>https://blog.yukiryou.top/posts/api_plugin/</link><guid isPermaLink="true">https://blog.yukiryou.top/posts/api_plugin/</guid><description>通过pixiv官方refresh_token去获取图片</description><pubDate>Tue, 02 Dec 2025 02:22:00 GMT</pubDate><content:encoded>&lt;h1&gt;起因&lt;/h1&gt;
&lt;p&gt;最近一直在做p站的api，目前进度只有6000+的图片信息，数据库部分信息类似下图
&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-12-02-21-25-14-image.K1QwrchD.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;所有图片均来自 &lt;a href=&quot;https://www.pixiv.net/&quot;&gt;Pixiv&lt;/a&gt;，版权也归作品的作者所有，API 仅储存了作品的基本信息，不提供图片的储存服务&lt;/li&gt;
&lt;li&gt;为保证质量的话，所有图片信息都是根据本人xp来的，这里不过多解释了
总之就是任务还没完成，只能偷工减料了。&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;QQ Bot&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;qq号:2830323446&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;成果一览&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;发图插件&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;- &lt;code&gt;setu&lt;/code&gt; 随机仅从 &lt;strong&gt;外部 API + 数据库&lt;/strong&gt; 取图；&lt;/p&gt;
&lt;p&gt;- &lt;code&gt;setu pid=... / uid=... / tag=...&lt;/code&gt;：&lt;strong&gt;官方优先&lt;/strong&gt;→失败自动回退 &lt;strong&gt;API → DB&lt;/strong&gt;，并 **通知主人 ；&lt;/p&gt;
&lt;p&gt;- 随机策略：&lt;strong&gt;随机跳页 + 水库采样&lt;/strong&gt;，避免“第一页偏置”；&lt;/p&gt;
&lt;h1&gt;优化过程&lt;/h1&gt;
&lt;p&gt;::github{repo=&quot;Tsuk1ko/pxder&quot;}
通过以上项目可以获取到你自己账号的refresh_token，然后就可以愉快的获取pixiv的信息了。&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;具体实现（可直接复用的核心函数）&lt;/h1&gt;
&lt;h2&gt;1) Pixiv 官方认证（refresh_token → access_token）&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
import requests

from pixivpy3 import AppPixivAPI

  

_OAUTH_TOKEN_URL = &quot;https://oauth.secure.pixiv.net/auth/token&quot;

_CLIENT_ID = &quot;MOBrBDS8blbauoSck0ZfDbtuzpyT&quot;

_CLIENT_SECRET = &quot;lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj&quot;

_UA = &quot;PixivAndroidApp/5.0.234 (Android 11; Pixel 5)&quot;

  

def exchange_by_refresh_token(refresh_token: str):

    headers = {

        &quot;User-Agent&quot;: _UA,

        &quot;Referer&quot;: &quot;https://app-api.pixiv.net/&quot;,

        &quot;App-OS&quot;: &quot;android&quot;,

        &quot;App-OS-Version&quot;: &quot;11&quot;,

        &quot;App-Version&quot;: &quot;5.0.234&quot;,

    }

    data = {

        &quot;client_id&quot;: _CLIENT_ID,

        &quot;client_secret&quot;: _CLIENT_SECRET,

        &quot;grant_type&quot;: &quot;refresh_token&quot;,

        &quot;refresh_token&quot;: refresh_token,

        &quot;include_policy&quot;: &quot;true&quot;,

    }

    r = requests.post(_OAUTH_TOKEN_URL, headers=headers, data=data, timeout=30)

    r.raise_for_status()

    j = r.json()

    if &quot;access_token&quot; not in j:

        raise RuntimeError(f&quot;token 交换失败：{j}&quot;)

    return j[&quot;access_token&quot;], j.get(&quot;refresh_token&quot;, refresh_token)

  

def make_aapi(refresh_token: str) -&amp;gt; AppPixivAPI:

    at, rt = exchange_by_refresh_token(refresh_token)

    aapi = AppPixivAPI(timeout=30)

    aapi.set_auth(at, rt)

    try: aapi.set_accept_language(&quot;zh-CN&quot;)

    except: pass

    return aapi

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;2) 随机策略：随机跳页 + 水库采样&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
import random

  

def extract_pages(ill: dict) -&amp;gt; list[str]:

    out = []

    if ill.get(&quot;meta_pages&quot;):

        for p in ill[&quot;meta_pages&quot;]:

            img = p.get(&quot;image_urls&quot;) or {}

            u = img.get(&quot;original&quot;) or img.get(&quot;large&quot;) or img.get(&quot;medium&quot;)

            if u: out.append(u)

    if not out:

        if ill.get(&quot;meta_single_page&quot;, {}).get(&quot;original_image_url&quot;):

            out.append(ill[&quot;meta_single_page&quot;][&quot;original_image_url&quot;])

        else:

            img = ill.get(&quot;image_urls&quot;) or {}

            u = img.get(&quot;original&quot;) or img.get(&quot;large&quot;) or img.get(&quot;medium&quot;)

            if u: out.append(u)

    return out

  

def random_one_from_uid(aapi, uid: int, max_jumps: int = 30) -&amp;gt; str | None:

    res = aapi.user_illusts(uid)

    if not res or not getattr(res, &quot;illusts&quot;, None): return None

    jumps = random.randint(0, max_jumps)

    cur = res

    for _ in range(jumps):

        if not getattr(cur, &quot;next_url&quot;, None): break

        qs = aapi.parse_qs(cur.next_url)

        cur = aapi.user_illusts(**qs)

        if not cur or not getattr(cur, &quot;illusts&quot;, None): break

    cand = getattr(cur, &quot;illusts&quot;, []) or []

    if not cand: return None

    pages = extract_pages(random.choice(cand))

    return random.choice(pages) if pages else None

  

def random_one_from_tag(aapi, tag: str, max_jumps: int = 30) -&amp;gt; str | None:

    res = aapi.search_illust(tag, search_target=&quot;partial_match_for_tags&quot;)

    if not res or not getattr(res, &quot;illusts&quot;, None): return None

    jumps = random.randint(0, max_jumps)

    cur = res

    for _ in range(jumps):

        if not getattr(cur, &quot;next_url&quot;, None): break

        qs = aapi.parse_qs(cur.next_url)

        cur = aapi.search_illust(**qs)

        if not cur or not getattr(cur, &quot;illusts&quot;, None): break

    cand = getattr(cur, &quot;illusts&quot;, []) or []

    if not cand: return None

    pages = extract_pages(random.choice(cand))

    return random.choice(pages) if pages else None

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3) 官方→API→DB 回退链路&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;
async def notify_owner(bot, owner_qq: int, text: str, event=None):

    try:

        if hasattr(bot, &quot;send_private&quot;):

            await bot.send_private(owner_qq, f&quot;[setu告警] {text}&quot;); return

    except Exception:

        pass

    if event is not None:

        await bot.send(event, f&quot;[setu告警] @{owner_qq} {text}&quot;)

  

async def get_by_pid_uid_tag_with_fallback(session, bot, event, owner_qq, refresh_token,

                                           pid: int|None, uid: int|None, tag: str|None,

                                           fetch_from_api, fetch_from_db):

    try:

        aapi = await asyncio.to_thread(make_aapi, refresh_token)

        if pid is not None:

            det = await asyncio.to_thread(aapi.illust_detail, pid)

            ill = det.illust

            urls = extract_pages(ill) if ill else []

        elif uid is not None:

            u = await asyncio.to_thread(random_one_from_uid, aapi, uid)

            urls = [u] if u else []

        elif tag:

            u = await asyncio.to_thread(random_one_from_tag, aapi, tag)

            urls = [u] if u else []

        else:

            urls = []

        if urls: return urls

        await notify_owner(bot, owner_qq, &quot;官方为空，回退 API&quot;, event)

    except Exception as e:

        await notify_owner(bot, owner_qq, f&quot;官方异常：{e}，回退 API&quot;, event)

  

    # API

    try:

        api_urls = await fetch_from_api(session, [] if pid or uid else ([f&quot;tag={tag}&quot;] if tag else []))

        if api_urls: return api_urls[:1]

        await notify_owner(bot, owner_qq, &quot;API 为空，回退 DB&quot;, event)

    except Exception as e:

        await notify_owner(bot, owner_qq, f&quot;API 异常：{e}，回退 DB&quot;, event)

  

    # DB

    try:

        db_urls = await fetch_from_db(1, None, tag, uid)

        return db_urls[:1] if db_urls else []

    except Exception as e:

        await notify_owner(bot, owner_qq, f&quot;DB 异常：{e}，最终失败&quot;, event)

        return []

&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h1&gt;结果&lt;/h1&gt;
&lt;p&gt;结果就是我发现标签查询效果更好了，标签匹配更吻合了，非常满意
&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-12-02-21-59-34-image.DqpsqFib.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>首次提交备案</title><link>https://blog.yukiryou.top/posts/icp/</link><guid isPermaLink="true">https://blog.yukiryou.top/posts/icp/</guid><description>第一次备案，分享一下</description><pubDate>Sat, 29 Nov 2025 02:22:00 GMT</pubDate><content:encoded>&lt;h1&gt;准备工作&lt;/h1&gt;
&lt;p&gt;我们都知道国内服务器是需要备案的，但备案需要准备些什么呢？&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;首先选择一家合适的域名服务商进行代备案，我选择的是阿里云。&lt;/li&gt;
&lt;li&gt;其次我们需要准备一个可备案域名和国内云服务器。&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;开始&lt;/h1&gt;
&lt;p&gt;准备好之后就可以申请备案了，我本以为备案会很复杂，但我提交申请到阿里云提交到管局审核也没花很长时间，不过我申请的时间是在周末，我想应该需要下周六才能通过了吧。&lt;/p&gt;
&lt;h1&gt;结束&lt;/h1&gt;
&lt;p&gt;附一张申请记录做为纪念
&lt;img src=&quot;https://blog.yukiryou.top/_astro/2025-11-29-17-12-11-image.DbOeRBQI.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>关于我对“赞助”的思考</title><link>https://blog.yukiryou.top/posts/sponsor/</link><guid isPermaLink="true">https://blog.yukiryou.top/posts/sponsor/</guid><description>对于自己喜欢的文章、博客、游戏mod，会给予赞助，突然就有了一个思考</description><pubDate>Fri, 28 Nov 2025 02:22:00 GMT</pubDate><content:encoded>&lt;h1&gt;开始&lt;/h1&gt;
&lt;p&gt;首先我们要弄明白什么叫赞助。在我的常识里，赞助就是用户为了某个活动、某个项目、某篇文章(具体来说就是某件事或物)提供经济支持。当我对别人赞助时，我不禁在思考，别人收到我的赞助会有什么心情和想法。虽然我知道我赞助的不算多，也并不是为了什么而去选择赞助。我仅仅是因为看到某些对我有帮助的文章，才会选择赞助对方，也希望对方能够提供更多有趣有帮助的文章。&lt;/p&gt;
</content:encoded></item><item><title>Ciallo～ (∠・ω&lt; )⌒★，搭建博客，重新开始</title><link>https://blog.yukiryou.top/posts/admin/</link><guid isPermaLink="true">https://blog.yukiryou.top/posts/admin/</guid><description>发现自己一直以来还是没有好好搭建一个自己的博客，就重新搞一下</description><pubDate>Wed, 26 Nov 2025 02:22:00 GMT</pubDate><content:encoded>&lt;h1&gt;开始&lt;/h1&gt;
&lt;p&gt;闲着没事做，就想着好好搭建一个博客玩一下，正好觉得平时比较喜欢的&lt;a href=&quot;https://2x.nz&quot;&gt;博主:2x树树&lt;/a&gt;魔改的博客网站还不错，自己也部署一个试试。不过我也没啥文笔，没什么说的就这样吧。&lt;/p&gt;
</content:encoded></item></channel></rss>