友链挂了?自动检测+主页截图,GitHub Actions 全搞定
为什么要做这个
友链多了之后总有个头疼的问题——对方悄悄撤了你的链接,或者站点直接挂了,你还蒙在鼓里。手动一个个点进去检查?四五十个友链,想想就累。
所以我搞了个自动化方案:每天定时检测友链状态,每 6 天自动截一张主页图,结果输出成一个 JSON,博客前端直接拉取展示。全程跑在 GitHub Actions 上,不用服务器,不用花钱。

参考链接
| 项目 | 说明 |
|---|---|
| willow-god/check-flink | 友链状态检测核心(多线程延迟检测 + 反链检测) |
| thun888/Python-WebSite-Screenshot | Selenium 主页截图核心 |
| fqzlr/check-flink | 我的整合版(本文主角) |
| cfbed.sanyue.de | 图床 API 规范(截图上传用) |
| image.thum.io | 截图兜底服务(Selenium 挂了也不怕) |
实现思路
把两个开源项目深度整合,最终架构长这样:
博客 friends.json(唯一数据源) │ ▼┌─ check_links job(每天 2 次)─────────┐│ 多线程请求每个友链 ││ 统计:延迟 / 失败次数 / 反链存在 ││ 输出 → result.json │└────────────────────────────────────────┘ │ ▼┌─ take_screenshots job(每 6 天)──────┐│ 读取 result.json 中可达的友链 ││ Selenium 截图 → 上传图床 ││ 失败 → thum.io 兜底 ││ 截图 URL 写回 result.json │└────────────────────────────────────────┘ │ ▼ Vercel 托管 result.json(CDN 加速) │ ▼ 博客前端 fetch → 渲染友链卡片关键文件
| 文件 | 作用 |
|---|---|
main.py | 状态检测 + 反链检测 + 增量合并 |
screenshot.py | Selenium 截图 + 图床上传 + thum.io 兜底 |
screenshot_runner.py | 截图入口,从 result.json 读取目标 |
inject.css | 截图时注入目标页面(隐藏滚动条/弹窗) |
.github/workflows/check_links.yml | 调度核心:定时 + 手动 + 条件触发 |
反链检测怎么做的
访问对方的友链页面,用正则提取所有真实的 <a href> 链接,解析主机名后跟自己的域名比对。
注意:只有真实超链接才算反链。如果对方只是在文章里提了一嘴你的域名(纯文本),不算。之前旧版用字符串匹配,结果把 5 个只是文字提及的站点误判成了有反链,后来重写了这块逻辑。
怎么部署
完整 8 步教程在 README,这里挑重点说。
第一步:Fork 仓库
把 fqzlr/check-flink fork 到你自己的 GitHub。
第二步:配置 Secrets
在仓库 Settings → Secrets and variables → Actions 里添加:
| Secret | 说明 | 示例 |
|---|---|---|
AUTHOR_URL | 你的域名(反链检测用) | fqzlr.com |
SOURCE_URL | 友链 JSON 地址 | https://fqzlr.com/friends.json |
IMG_API_URL | 图床上传 API | https://tu.xxx.com/api/upload |
IMG_API_TOKEN | 图床 API Token | your-token |
第三步:开启 Actions 写权限
仓库 Settings → Actions → General → Workflow permissions → 选 Read and write permissions。
不然 workflow 没法把 result.json 提交回仓库。
第四步:准备友链数据源
你的博客需要暴露一个 JSON 接口,格式类似:
[ { "name": "番茄的博客", "link": "https://blog.example.com", "avatar": "https://...", "linkpage": "https://blog.example.com/friends" }]其中 linkpage 是对方的友链页面地址(反链检测会访问这个页面)。
第五步:准备图床
截图需要上传到图床。我用的是 Cloudflare-ImgBed(博客系列第 4 期讲过),API 兼容 cfbed.sanyue.de 规范。
第六步:首次触发
Actions → Run workflow → task 选 both → target_link 留空 → 跑!
首次全量跑一遍,之后日常就自动了。
第七步:部署到 Vercel
把仓库导入 Vercel,Output Directory 填 static,得到一个 CDN 地址。博客前端 fetch 这个地址的 result.json 就行。
怎么触发
这是我最满意的部分——灵活到可以只跑一个友链。
自动触发(不用管)
| 时间 | 执行内容 |
|---|---|
| 每天 01:00、13:00 | 仅状态检测(~1 分钟) |
| 每 6 天(1/7/13/19/25 号 01:30) | 状态检测 + 截图(~10 分钟) |
手动触发(按需)
进 Actions → Run workflow,有两个参数:
task(选执行内容):
status_only:仅状态检测(默认)screenshots_only:仅截图(用上次检测数据)both:检测 + 截图
target_link(只处理指定友链):
- 填友链名称或 URL 关键词,如
番茄或blog.example.com - 留空 = 处理全部
常见场景
| 我想… | task | target_link |
|---|---|---|
| 日常看看谁挂了 | status_only | 留空 |
| 新加了个友链,检测一下 | status_only | 新友链名字 |
| 新加了个友链,检测+截图 | both | 新友链名字 |
| 截图太旧了,全部重截 | screenshots_only | 留空 |
| 全量跑一遍 | both | 留空 |
增量处理是什么
当你填了 target_link,只有匹配的友链会被重新检测/截图,其余友链保留上次结果。不会出现”只跑了一个友链,其他 46 个数据全没了”的情况。total_count 始终不变。
一些细节
截图兜底链
Selenium 本地截图 ├─ 成功 → 上传图床 → 图床 URL └─ 失败 → thum.io 在线截图(永远可用)所以即使 GitHub Actions 环境抽风装不上 Chrome,也不会出现白屏。
截图频率为什么是 6 天
Selenium + Chrome 安装要 2-3 分钟,截完全部友链要 5-10 分钟。每天跑太浪费 Actions 配额(每月 2000 分钟),6 天一次刚刚好。
状态检测就轻量多了,纯 requests 请求,1 分钟跑完,所以每天 2 次不心疼。
数据源只维护一份
友链配置只在博客侧维护(我的 friends.json),检测仓库自动读取。不用两边同步,加友链只需要在博客加一次。
最后
整套方案跑下来零成本:GitHub Actions 免费额度足够,图床用 Cloudflare Workers 免费套餐,Vercel 也是免费的。
如果你也有几十号友链,与其隔三差五手动检查,不如让机器帮你盯着。
有问题欢迎评论区交流~






