开始之前 你需要一个仓库、一个存储为秘密 LZ_KEY 的 Linkzoid 密钥,以及一个你拥有的域名。预算:每次运行每个目标约消耗 6 个积分,即 $0.0006。快照是对某个月份的事实记录,因此每周运行通常会重新获取相同的索引。以这种方式设置检查反向链接的方法,只需一个晚上即可完成。
运行手册步骤 01 1. 添加秘密 进入仓库设置,然后选择“秘密和变量”,再选择“Actions”。将其命名为 LZ_KEY。如果你将其粘贴到工作流文件中,请立即轮换密钥。
02 2. 提交脚本 将下面的 Python 代码保存为 snap.py。它将写入 data/YYYY-MM-DD/refdomains.json,并在响应 ok 为 false 时失败。
03 3. 提交工作流 使用下面的 YAML 文件。使用 workflow_dispatch 触发器手动运行一次,并在信任定时计划之前查看日志。
04 4. 检查第一个文件 打开 JSON 文件。将行数与 total 进行核对,并将该数字与免费 overview 调用针对你的域名报告的数量进行比较。
05 5. 添加警报 作业失败时默认会向仓库所有者发送邮件。保持此设置不变。作业静默停止是此类设置失效的常见方式。
snap.py 标准库。循环在达到计数后结束,而不是基于猜测。
python
import json, os, sys, datetime, pathlib, urllib.request as u
KEY = os.environ['LZ_KEY']
TARGET = sys.argv[1]
def get(**p):
q = '&'.join(f'{k}={v}' for k, v in p.items())
url = f'https://linkzoid.pro/api.php?{q}&key={KEY}'
with u.urlopen(url, timeout=30) as r:
return json.load(r)
rows, page = [], 1
while True:
d = get(action='refdomains', q=TARGET, page=page, per=1000)
if not d['ok']:
sys.exit(f'bad response: {d}')
rows += d['rows']
if not d['rows'] or len(rows) >= d['total']:
break
page += 1
day = datetime.date.today().isoformat()
out = pathlib.Path('data') / day
out.mkdir(parents=True, exist_ok=True)
(out / 'refdomains.json').write_text(json.dumps(rows))
print(len(rows), 'rows, balance', d['_credits']).github/workflows/snapshot.yml GitHub 中的 Cron 在 UTC 时间运行,当运行器繁忙时可能会延迟启动。不要构建依赖于具体分钟的任务。
yaml
name: backlink-snapshot
on:
schedule:
- cron: '17 6 * * 1'
workflow_dispatch:
jobs:
snap:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- run: python snap.py example.com
env:
LZ_KEY: ${{ secrets.LZ_KEY }}
- run: |
git config user.name snapshot-bot
git config user.email "snapshot-bot@localhost"
git add data
git commit -m "snapshot $(date -u +%F)" || exit 0
git push
在开启计划之前 密钥存储在仓库秘密中,YAML 仅通过名称引用它。 工作流文件位于默认分支,因为这是计划读取的副本。 使用 workflow_dispatch 的手动运行已完成,并生成了一个按日期命名的文件夹。 文件中的行数与 API 为该调用返回的总数匹配。 作业在响应不良时以非零退出码退出,因此失败会使运行显示为红色。
错误与修复 定时反向链接作业中首先出现的问题 错误 你看到的现象 修复方法 密钥粘贴在 YAML 中 密钥在仓库历史中可见 轮换密钥,并将其移至 secrets.LZ_KEY 奇数分钟,如 0 0 运行延迟 20 分钟开始 选择 17 6;整点时段通常较为拥挤 仓库闲置 60 天 GitHub 暂停计划 提交一些内容,或在 Actions 选项卡中重新启用它 循环仅在空页时停止 在页面上限时无限运行 当 len(rows) >= total 时也停止 退出码被忽略 绿色勾号,但文件夹为空 在 ok: false 时使用 sys.exit 无更改时提交失败 无意义的红色运行 在提交后添加 || exit 0
保护密钥和仓库 密钥是该设置中唯一需要保护的内容。将其视为密码,因为任何持有它的人都可以消耗你的余额。
定时作业会静默泄露。密钥粘贴到日志中、工作流复制到公共仓库,或者拥有写权限的前同事,这些都是常见的泄露途径。每季度检查一次。
人员离职时轮换密钥 当拥有访问权限的同事离职时,创建新密钥,更新秘密并停用旧密钥。然后确认下一次运行通过。变更后的一次绿色运行是你全年所做的最便宜的测试。在仓库笔记中记录轮换日期,以便下次轮换时不会感到意外。
限制谁可以编辑工作流 任何可以编辑 YAML 的人都可以运行中打印秘密。保持写权限范围尽可能小,并以审查代码的方式审查工作流文件的更改。对于小型仓库,两人拥有写权限通常就足够了。
永远不要打印请求 URL 打印余额和行数,但不要打印请求 URL。密钥位于查询字符串中,因此打印 URL 的调试行会将密钥写入日志。如果必须在问题中共享请求,请先用占位符替换密钥。
快照是什么,不是什么 你获得的是月度快照。我们的爬虫每月刷新一次索引,因此同一个月内的两个周一运行通常会返回相同的行。这是预期内的现象。
每周的频率是可行的。它保持了习惯的延续,并且你可以在七天内而不是三十天内发现作业故障。如果你在周二建立的链接在周一缺失,请耐心等待下一次刷新,不要惊慌。
当你拥有三到四个按日期命名的文件夹后,可以转向 SQLite 差异对比 。如果你卡在顽固的响应代码上,速率限制表 列出了每个状态对循环的含义。
保留第一个文件夹作为基准。每次后续比较都指向它,按日期命名的文件夹比记忆去年春季的数字外观更值得信赖。保持一致性。
添加锚文本和顶级页面 每个文件一个操作可使差异对比更易读。复制 snap.py 中的循环,将 refdomains 更改为 anchors 或 toppages,并写入第二个文件名。每个操作消耗 2 个积分。
合并文件会隐藏哪部分发生了更改,而审查者在滚动拉取请求时希望每个差异只展示一个概念。保持分离。如果你跟踪三个域名,在工作流中使用矩阵循环遍历短列表,以便每个目标都有自己独立的作业和独立的失败状态。
锚文本是第二个文件,在差异对比中有自己的上限,因此应将其与引用域名分开审查。每次运行成本低廉且可重复,这正是其核心思想。
阅读运行日志 打开第一次运行的日志。在信任计划之前务必查看。查找行数、余额和提交行。如果其中任何一项缺失,说明作业执行的内容少于其声称的数量。同时记录每次运行的余额,以便在不打开仪表板的情况下即可看到月度支出。
绿色勾号说明不了多少。它仅表示进程干净地退出。它并不表示文件包含正确的行,这就是脚本打印自身摘要的原因。在脚本的不同版本之间保持这些摘要行不变,以便两个日志的差异仅显示真正的更改。
健康日志的样子 健康的运行会打印一行包含行数和信用余额,然后是一次带有当天日期的提交。任何将这些行淹没在额外噪音中的情况都值得再次查看。
发现静默故障 注意空文件夹、从未出现的提交或行数与总数不符的情况。这些都指向循环或解析问题,而非 API 本身。保存第一个健康日志作为后续比较的参考。
某些故障会留下一个文件夹,其中的行数少于往常。在庆祝绿色运行之前,将计数与上周进行比较,因为静默截断看起来与静默的月份完全相同。
安全地添加第二个目标 第二个域名是一个矩阵条目,而不是整个工作流的副本。为每个目标分配独立的工作,以便一个故障不会掩盖另一个故障。保持每个作业独立。检查路径是否包含域名名称,以便两次运行不会写入同一个文件。
先从第二个目标开始。一旦其文件夹看起来正确,再添加其余部分。中途失败的矩阵比两个简单的运行更难阅读。
按目标命名文件夹 在路径中包含域名,例如 data/<domain>/YYYY-MM-DD,即使两个作业在同一分钟运行,文件夹也能保持分离。旧文件夹可以保留在原处,因为路径中的日期使它们易于查找。
对每个目标使用相同的命名规则。这样脚本就可以列出文件夹而无需特殊处理。
首先规划信用预算 将每个目标的调用次数乘以目标数量,然后在第一次运行之前将总数与余额进行比较。矩阵使支出像作业数量一样快速增加。在工作流旁边的仓库中记录预期的月度总额。当余额下降速度快于预期时,循环可能正在重新获取页面,你可以在下一次运行之前停止它。
第一周会出现的问题
我可以在私有仓库上免费运行此程序吗? 通常可以,在 GitHub 免费账户提供的每月分钟数范围内。快照作业运行时间远低于一分钟,因此每周计划使用的分钟数很少。检查你当前计划的配额,因为 GitHub 会不时更改它。
如果有多人推送,密钥应该放在哪里? 在组织或仓库秘密中,永远不要放在文件中。任何可以编辑工作流的人都可以将秘密打印到日志中,因此限制拥有写权限的人员,并在有人离开项目时轮换密钥。
为什么我的计划运行没有触发? 三个常见原因。工作流文件不在默认分支上,仓库闲置了 60 天导致 GitHub 暂停了计划,或者 cron 字符串有拼写错误。使用 workflow_dispatch 手动运行一次以排除脚本本身的问题。
数据文件夹会变大吗? 很小。一千个引用域名仅占几百千字节的 JSON。一个域名一年的每周文件总大小远低于一百兆字节,这对 git 来说没问题,但如果介意,你可以压缩旧文件夹。