本地版:https://blog.mikulab.com/archives/20
由于服务器物理位置限制,导致该API请求时耗时经常超过1000ms,因此考虑将请求程序存放于CF/GitHub仓库中,通过CF提供的边缘计算加快访问速度,减少不必要的物理传输时间。
追加支持:通过增加域名后缀实现对不同相册的访问,需更改CF worker及GitHub sync 脚本。
1.创建CF-KV存储用于储存图床中相册特定内的所有图片链接,以在后续请求中直接调用,加快访问速度的同时减少服务器资源消耗,将KV命名为IMG_LIST_KV,帮记录其ID。随后登录控制台,创建API Tokens,选择Custom Token,设置如下:
Token name: GitHub_Sync_KV。
Permissions:
Account | Worker KV Storage | Edit
Account Resources: 选择 Include | Your Account。
记录该Token。
2.创建CF-Worker,并将KV与其绑定。
export default {
async fetch(request, env) {
// 1. 从 KV 数据库读取名为 "images" 的键值对
const listStr = await env.IMG_LIST_KV.get("images");
if (!listStr) {
return new Response("列表尚未同步,请运行 GitHub Actions", { status: 404 });
}
const imgList = JSON.parse(listStr);
// 2. 本地随机算法
const randomUrl = imgList[Math.floor(Math.random() * imgList.length)];
// 3. 返回 302 重定向
return Response.redirect(randomUrl, 302);
}
};
多相册版:
export default {
async fetch(request, env) {
const url = new URL(request.url);
// 获取路径并去掉斜杠,例如 "/6" 变成 "6"
let albumId = url.pathname.replace(/\//g, '');
// 如果直接访问根域名没有带路径,默认指向相册 5
if (!albumId) {
albumId = "5";
}
// 从 KV 数据库中读取对应相册 ID 的列表
const listStr = await env.IMG_LIST_KV.get(albumId);
if (!listStr) {
return new Response(`未找到相册 ID ${albumId} 的同步数据。请确认 GitHub Actions 已运行并同步了此 ID。`, {
status: 404,
headers: { "Content-Type": "text/plain;charset=UTF-8" }
});
}
const imgList = JSON.parse(listStr);
const randomUrl = imgList[Math.floor(Math.random() * imgList.length)];
// 执行重定向
return Response.redirect(randomUrl, 302);
}
};
3.创建新的Github仓库,并在根目录创建同步脚本sync.py。
import requests
import json
import os
# 环境变量 (在 GitHub Secrets 中配置)
LSKY_API = "https://image.mikulab.com/api/v1/images?album_id=5"
LSKY_TOKEN = os.getenv("LSKY_TOKEN")
CF_ACCOUNT_ID = os.getenv("CF_ACCOUNT_ID")
CF_KV_ID = os.getenv("CF_KV_ID")
CF_API_TOKEN = os.getenv("CF_API_TOKEN")
def sync():
# 1. 获取兰空图床相册数据
headers = {"Authorization": LSKY_TOKEN, "Accept": "application/json"}
try:
response = requests.get(LSKY_API, headers=headers)
res = response.json()
if res.get('status'):
# 提取所有图片链接
urls = [img['links']['url'] for img in res['data']['data']]
# 2. 推送到 Cloudflare KV (Key 为 "images")
kv_url = f"https://api.cloudflare.com/client/v4/accounts/{CF_ACCOUNT_ID}/storage/kv/namespaces/{CF_KV_ID}/values/images"
kv_headers = {
"Authorization": f"Bearer {CF_API_TOKEN}",
"Content-Type": "text/plain"
}
put_res = requests.put(kv_url, headers=kv_headers, data=json.dumps(urls))
if put_res.status_code == 200:
print(f"同步成功!已同步 {len(urls)} 张图片。")
else:
print(f"KV 更新失败: {put_res.text}")
except Exception as e:
print(f"运行出错: {e}")
if __name__ == "__main__":
sync()
随后在Secrets and variables 中选取Actions,创建四个变量:
| Secret 名称 | 获取值的方法 |
LSKY_TOKEN | 兰空图床 Token(格式:Bearer x|...) |
CF_ACCOUNT_ID | Cloudflare 仪表板首页右下角看到的 Account ID |
CF_KV_ID | KV Namespace 的 ID |
CF_API_TOKEN | Cloudflare API Token |
多相册版:
import requests
import json
import os
# --- 唯一需要手动维护的地方:在列表里增加相册 ID ---
ALBUM_IDS = [5, 6, 7, 8]
LSKY_TOKEN = os.getenv("LSKY_TOKEN")
CF_ACCOUNT_ID = os.getenv("CF_ACCOUNT_ID")
CF_KV_ID = os.getenv("CF_KV_ID")
CF_API_TOKEN = os.getenv("CF_API_TOKEN")
def sync():
headers = {"Authorization": LSKY_TOKEN, "Accept": "application/json"}
for album_id in ALBUM_IDS:
print(f"正在同步相册 {album_id}...")
api_url = f"https://image.mikulab.com/api/v1/images?album_id={album_id}"
try:
res = requests.get(api_url, headers=headers).json()
if res.get('status'):
# 提取图片 URL
urls = [img['links']['url'] for img in res['data']['data']]
# 使用相册 ID 作为 KV 的 Key
kv_endpoint = f"https://api.cloudflare.com/client/v4/accounts/{CF_ACCOUNT_ID}/storage/kv/namespaces/{CF_KV_ID}/values/{album_id}"
kv_headers = {
"Authorization": f"Bearer {CF_API_TOKEN}",
"Content-Type": "text/plain"
}
requests.put(kv_endpoint, headers=kv_headers, data=json.dumps(urls))
print(f"相册 {album_id} 同步成功,共 {len(urls)} 张图片。")
except Exception as e:
print(f"相册 {album_id} 同步失败: {e}")
if __name__ == "__main__":
sync()
4.配置Github actions定时任务:
在Actions中手动创建文件sync.yml
name: Hourly Sync API Cache
on:
schedule:
- cron: '0 * * * *' # 每小时的第 0 分钟执行一次
workflow_dispatch: # 允许你在 GitHub 页面上点击按钮手动执行
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Requests
run: pip install requests
- name: Run Sync Script
env:
LSKY_TOKEN: ${{ secrets.LSKY_TOKEN }}
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
CF_KV_ID: ${{ secrets.CF_KV_ID }}
CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
run: python sync.py
手动执行Actions,并在CF中绑定自定义域名,如 rdapi1.mikulab.com
默认域名将会随机返回相册5中图片,如需访问其他相册,仅需添加对应相册编号如rdapi1.mikulab.com/6
Comments NOTHING