1. 从手动打卡到自动化签到的真实痛点
每天早上八点,闹钟一响,第一件事不是刷牙洗脸,而是摸手机打开某个网站或者小程序,找到打卡入口,点进去,填体温、填健康状况、勾选承诺书、提交。整个过程熟练的话两分钟,不熟练或者网络卡顿的时候五分钟都搞不定。更让人崩溃的是,有时候忙起来彻底忘了这回事,等想起来的时候已经是晚上十一点,赶紧补卡,心惊胆战怕被通报。
这个场景我相信很多人都经历过。不管是学校的健康信息填报,还是某些平台的每日签到领积分,本质上都是重复性、低价值、但又不得不做的机械操作。作为一个写了多年代码的人,我的第一反应永远是:这种事能不能让机器替我干?
答案是肯定的。而且方案比你想的要简单得多——GitHub Actions。你不需要买服务器,不需要租云主机,不需要配置什么复杂的定时任务框架。GitHub 本身就提供了免费的定时触发能力,你只需要写一个配置文件,把你的打卡逻辑塞进去,它就会在每天你指定的时间自动帮你跑一遍。跑完还能给你发通知,告诉你成功了还是失败了。
这篇文章要聊的就是这套方案的完整落地过程。我会从最核心的原理讲起,把每一步为什么这么做、坑在哪里、怎么绕过去都说清楚。适合有基本 Git 操作经验、想让重复劳动自动化的朋友。哪怕你之前没写过 GitHub Actions,跟着走也能跑通。
注意:本文讨论的是个人效率工具的技术实现思路,所有案例均为模拟场景,请确保你的自动化操作符合所在平台的使用条款。
2. 为什么选 GitHub Actions 而不是其他方案
2.1 常见自动化方案的横向对比
在决定用 GitHub Actions 之前,我认真评估过几种主流方案。这里把我的对比思路分享出来,方便你根据自己的情况做选择。
| 方案 | 成本 | 技术门槛 | 稳定性 | 维护成本 | 适合人群 |
|---|---|---|---|---|---|
| 本地电脑定时脚本 | 零 | 低 | 差(关机就断) | 低 | 有常开电脑的人 |
| 云服务器 + cron | 每月几十元 | 中 | 好 | 中 | 有运维基础的人 |
| 树莓派等小型设备 | 一次性硬件成本 | 中高 | 一般(断电断网) | 中 | 喜欢折腾硬件的人 |
| GitHub Actions | 免费 | 低 | 好 | 极低 | 有 GitHub 账号的开发者 |
| 第三方自动化平台 | 免费额度有限 | 低 | 一般 | 低 | 不想碰代码的人 |
本地电脑跑脚本的问题很明显:你得保证那个时间点电脑是开着的,网络是通的,脚本没被误删。我试过在自己笔记本上挂定时任务,结果出差三天,打卡断了三天,回来被提醒了。云服务器倒是稳定,但一年下来也是一笔开销,就为了跑一个每天两分钟的脚本,性价比太低。
GitHub Actions 的优势在于:它天然就是为定时任务设计的。你只需要一个公开仓库(私有仓库也有免费额度),把脚本放进去,配置好 cron 表达式,剩下的交给 GitHub 的服务器。它不会因为你关机而停止,不会因为你换网络而中断,而且完全免费。
2.2 GitHub Actions 的定时触发机制
GitHub Actions 的定时触发靠的是on.schedule事件,底层用的是标准的 cron 表达式。但这里有一个很多人第一次用都会踩的坑:GitHub 的 cron 用的是 UTC 时间,不是北京时间。
北京时间是 UTC+8,所以如果你想让任务在北京时间早上 7 点执行,cron 表达式应该写成 UTC 的 23 点(前一天)。比如:
on: schedule: - cron: '0 23 * * *'这行配置的意思是每天 UTC 23:00 触发,对应北京时间早上 7:00。
还有一个更隐蔽的坑:GitHub Actions 的定时任务并不保证精确执行。官方文档明确说了,在高负载时段,任务可能会延迟几分钟甚至更久。我实测下来,延迟通常在 3 到 15 分钟之间。所以如果你打卡有严格的时间窗口,建议把触发时间设得稍微早一点,留出缓冲。
另外,定时任务只会在默认分支上生效。如果你的仓库默认分支是main,那 workflow 文件必须放在main分支的.github/workflows/目录下,放在其他分支上不会触发。
2.3 免费额度的真实消耗情况
很多人担心免费额度不够用。我算一笔账:GitHub 对公开仓库的 Actions 是完全免费的,不消耗额度。对私有仓库,免费账户每月有 2000 分钟的额度。一个打卡脚本单次运行通常不超过 1 分钟,一个月 30 次也就是 30 分钟,远远用不完。
但要注意,如果你的脚本里包含了安装依赖、编译等步骤,单次运行时间可能会拉长到 2-3 分钟。即便如此,一个月也就 60-90 分钟,依然在安全范围内。真正消耗额度的是那些需要跑大型构建、测试套件的项目,单纯的打卡签到脚本完全不用担心。
提示:如果你的仓库是私有的,建议在 workflow 里设置
timeout-minutes,防止脚本卡死导致额度被白白消耗。一般设 5 分钟足够了。
3. 打卡脚本的核心逻辑拆解
3.1 从浏览器操作到 HTTP 请求的转换
手动打卡的过程,本质上就是浏览器向服务器发送了一系列 HTTP 请求。我们要做的,就是用代码模拟这些请求。关键在于搞清楚三件事:请求发到哪个地址、带了什么参数、需要什么身份凭证。
获取这些信息最直接的方法是打开浏览器的开发者工具。按 F12,切到 Network 面板,然后手动完成一次打卡操作。你会看到一串请求记录,找到那个提交打卡数据的请求(通常是 POST 方法),点进去看它的 Request URL、Request Headers 和 Request Payload。
这里有几个关键信息需要提取:
- Request URL:打卡接口的完整地址
- Request Method:通常是 POST
- Content-Type:一般是
application/json或application/x-www-form-urlencoded - Request Payload:提交的具体数据,比如体温、位置、健康状况等
- Cookie 或 Authorization:身份凭证,这是最关键也最容易过期的东西
我建议把这次请求完整地复制为 cURL 命令(开发者工具里右键就有这个选项),然后拿这个 cURL 命令去逐步转换成 Python 或 JavaScript 代码。这样比对着面板一个个抄要准确得多。
3.2 身份凭证的获取与保活策略
身份凭证是整个方案里最脆弱的一环。大部分平台的登录态都是通过 Cookie 或 Token 维持的,而这些凭证通常有有效期。短的可能几小时,长的可能几天到几周。
我的处理策略是这样的:
第一步,先确认凭证的有效期。手动登录一次,把 Cookie 复制出来,然后隔一段时间用这个 Cookie 发请求,看什么时候开始返回未登录状态。这个测试能帮你判断需要多久更新一次凭证。
第二步,把凭证存到 GitHub Secrets 里。绝对不要把 Cookie 或 Token 直接写在代码里然后提交到仓库,哪怕是私有仓库也不安全。GitHub 提供了 Secrets 功能,在仓库的 Settings → Secrets and variables → Actions 里添加,然后在 workflow 里通过${{ secrets.XXX }}引用。
第三步,设置失效通知。在脚本里加一个判断:如果请求返回的是未登录状态,就触发一个失败通知。这样你就能及时知道凭证过期了,需要手动更新。
import os import requests cookie = os.environ.get('CHECKIN_COOKIE') headers = { 'Cookie': cookie, 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Content-Type': 'application/json' } resp = requests.post('https://example.com/api/checkin', headers=headers, json={ 'temperature': '36.5', 'health': 'normal' }) if resp.status_code == 200 and 'success' in resp.text: print('打卡成功') else: print('打卡失败,请检查凭证') exit(1) # 非零退出码会让 Action 标记为失败,触发通知这段代码里,exit(1)很关键。GitHub Actions 通过退出码判断步骤是否成功,非零退出码会触发失败通知,这样你就能第一时间知道出问题了。
3.3 请求参数的构造与常见陷阱
构造请求参数看起来简单,但实际操作中有几个容易翻车的地方。
时间戳和签名的处理。有些平台会在请求里带一个时间戳或者签名参数,这个值是根据当前时间动态计算的。如果你直接复制之前的请求参数,时间戳对不上,服务器就会拒绝。遇到这种情况,你需要找到签名的计算逻辑,通常是在某个 JavaScript 文件里,把它逆向出来用代码实现。
必填字段的遗漏。手动操作时,浏览器会自动带上一些你看不见的字段,比如_csrf、token、sessionId之类的。复制 cURL 命令的时候要仔细检查,确保所有字段都带上了。
编码问题。如果请求体里有中文,要注意编码格式。application/json默认是 UTF-8,但application/x-www-form-urlencoded可能需要额外处理。我遇到过因为中文姓名编码不对导致打卡失败的情况,排查了半天才发现是编码问题。
重定向处理。有些接口会返回 302 重定向,requests库默认会自动跟随重定向,但有时候重定向后的请求会丢失 Cookie 或 Header。如果发现请求返回 200 但数据不对,可以试试设置allow_redirects=False手动处理。
4. 把脚本搬进 GitHub Actions 的完整流程
4.1 仓库结构与 workflow 文件编写
一个典型的打卡自动化仓库结构是这样的:
checkin-bot/ ├── .github/ │ └── workflows/ │ └── daily-checkin.yml ├── checkin.py ├── requirements.txt └── README.mddaily-checkin.yml是核心配置文件,定义了什么时候跑、跑什么、怎么跑。下面是一个完整的示例:
name: Daily Checkin on: schedule: # 每天 UTC 23:00 触发,对应北京时间 7:00 - cron: '0 23 * * *' workflow_dispatch: # 支持手动触发,方便调试 jobs: checkin: runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: 检出代码 uses: actions/checkout@v4 - name: 设置 Python 环境 uses: actions/setup-python@v5 with: python-version: '3.11' - name: 安装依赖 run: pip install -r requirements.txt - name: 执行打卡 env: CHECKIN_COOKIE: ${{ secrets.CHECKIN_COOKIE }} NOTIFY_URL: ${{ secrets.NOTIFY_URL }} run: python checkin.py这个配置里,workflow_dispatch是我强烈建议加上的。它允许你在 GitHub 网页上手动点击运行,调试的时候非常方便,不用等到第二天定时触发才能看结果。
4.2 Secrets 配置与敏感信息隔离
Secrets 的配置路径是:仓库页面 → Settings → Secrets and variables → Actions → New repository secret。添加之后,在 workflow 里通过${{ secrets.名称 }}引用。
有几个细节需要注意:
- Secret 名称只能包含字母、数字和下划线,不能以数字开头
- Secret 的值一旦保存就无法再查看,只能重新设置
- Secret 在日志里会被自动打码,但如果你的脚本把 Secret 打印到了非标准输出,可能会泄露
- 在
if条件里不能直接使用 Secrets,需要先通过env传递
我一般会把所有敏感信息都放进 Secrets:Cookie、Token、通知服务的 Webhook 地址、邮箱密码等。代码里只通过环境变量读取,这样即使仓库不小心变成公开的,也不会泄露凭证。
4.3 通知机制的接入方式
打卡成功与否,你得知道结果。GitHub Actions 本身在失败时会发邮件通知,但邮件容易被忽略,而且成功时不会通知。我建议接入一个更及时的通知渠道。
常见的通知方式有几种:
Server 酱。国内用得比较多,通过一个 Webhook 地址发送消息到微信。配置简单,免费额度够个人使用。
Bark。iOS 用户的首选,推送到 iPhone 的通知中心,实时性很好。
Telegram Bot。如果你用 Telegram,可以创建一个 Bot,通过 Bot API 发送消息。免费且稳定。
邮件通知。用 Python 的smtplib发送邮件,适合不想依赖第三方服务的人。
以 Server 酱为例,在脚本末尾加上这样的代码:
import os import requests def notify(title, content): url = os.environ.get('NOTIFY_URL') if url: requests.post(url, json={ 'title': title, 'content': content }) # 打卡成功后调用 notify('打卡成功', '今日打卡已完成')这样每天打卡完成后,你会在微信里收到一条消息,心里踏实。
5. 调试与排错:那些我踩过的坑
5.1 本地能跑但 Action 里失败的原因排查
这是最常见的问题:在本地电脑上跑得好好的脚本,放到 GitHub Actions 里就报错。原因通常有这几类:
环境差异。本地是 Windows,Action 里是 Ubuntu,路径分隔符、换行符、默认编码都可能不一样。解决办法是在本地也用 Docker 跑一个 Ubuntu 环境测试,或者直接在 Action 里加调试输出。
依赖版本不一致。本地装的requests是 2.31,Action 里装的是最新版 2.32,某些 API 可能有变化。解决办法是在requirements.txt里锁定版本号,比如requests==2.31.0。
网络环境差异。本地能访问的某些地址,在 GitHub 的服务器上可能访问不了,或者需要额外的代理配置。这个只能通过日志排查,看具体卡在哪一步。
时区问题。本地是北京时间,Action 里默认是 UTC。如果脚本里有跟时间相关的逻辑,比如判断今天是不是工作日,就可能出错。解决办法是在脚本开头设置时区:
import os os.environ['TZ'] = 'Asia/Shanghai'5.2 定时任务不触发或延迟的应对
前面提到过,GitHub Actions 的定时任务不保证精确。我遇到过几次延迟超过 30 分钟的情况,也遇到过偶尔完全不触发的情况。
应对策略有几个:
设置多个触发时间点。比如你想在 7 点打卡,可以设置 6:30、7:00、7:30 三个触发时间,脚本里加一个判断:如果今天已经打卡成功过,就直接退出。这样即使某个时间点延迟或没触发,还有其他机会。
用外部服务做兜底。如果打卡非常重要,可以考虑用一个免费的监控服务(比如 UptimeRobot)定时访问你的 Action 触发接口。不过 GitHub 没有直接提供 HTTP 触发 Action 的接口,需要绕一下,用repository_dispatch事件配合一个中间服务来实现。
接受不完美。说实话,大部分打卡场景对时间的容忍度还是比较高的,延迟十几分钟通常没问题。如果实在要求精确到分钟,那 GitHub Actions 可能不是最佳选择,需要考虑云服务器方案。
5.3 凭证过期导致失败的预警设计
凭证过期是必然会发生的,关键是要在它发生时第一时间知道,而不是等到被提醒才发现。
我的做法是在脚本里加一个"凭证有效性检查"步骤,放在打卡之前:
# 先检查凭证是否有效 check_resp = requests.get('https://example.com/api/user/info', headers=headers) if check_resp.status_code == 401 or 'login' in check_resp.url: notify('凭证已过期', '请及时更新 CHECKIN_COOKIE') exit(1)这样一旦凭证失效,你会立刻收到通知,有时间去手动更新。更新之后,在 GitHub 上手动触发一次 Action 验证,确认没问题就行了。
另外,我建议在 README 里记录凭证的更新日期和预计有效期,这样心里有个数,可以提前准备。
6. 扩展思路:从打卡到更广泛的自动化
6.1 多平台签到的统一管理
如果你有多个平台需要每日签到,没必要每个都建一个仓库。可以在一个仓库里放多个脚本,用一个 workflow 依次执行,或者用 matrix 策略并行执行。
jobs: checkin: runs-on: ubuntu-latest strategy: matrix: task: [platform_a, platform_b, platform_c] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.11' - run: pip install -r requirements.txt - run: python checkin_${{ matrix.task }}.py env: COOKIE: ${{ secrets[format('{0}_COOKIE', matrix.task)] }}这样三个平台会并行执行,互不影响,而且日志分开,排查问题很方便。
6.2 用 Actions 做更多定时任务
打卡只是冰山一角。GitHub Actions 的定时能力可以用在很多地方:
- 每天定时抓取某个网站的数据,存到仓库里做趋势分析
- 定时检查某个商品的价格,降价时发通知
- 定时备份某个 API 的数据到 GitHub 仓库
- 定时运行测试套件,监控服务可用性
- 定时生成日报、周报并发送
核心思路是一样的:把重复的、有规律的操作写成脚本,用 cron 触发,用通知反馈结果。掌握了这个模式,你能自动化的东西远超想象。
6.3 安全边界与合规使用的个人体会
最后聊几句实在的。自动化工具本身是中性的,但使用的时候要注意边界。
第一,不要高频请求。每天一次、两次没问题,但如果设置成每分钟跑一次,那就是在给服务器添堵,也可能触发风控。合理使用,利人利己。
第二,不要分享凭证。你的 Cookie 和 Token 就是你的身份,泄露出去别人就能冒充你操作。Secrets 功能要用好,不要图省事直接写在代码里。
第三,关注平台规则。有些平台明确允许自动化签到,有些则不允许。使用前花两分钟看看用户协议,避免不必要的麻烦。
第四,做好失效准备。任何自动化方案都可能因为平台改版而失效。脚本报错的时候不要慌,按本文的排查思路一步步来,大部分问题都能解决。
我自己用这套方案跑了很长时间,中间经历过接口变更、凭证过期、Action 延迟等各种情况,但整体来说,它帮我省下的时间和精力远远超过维护成本。每天早上不再需要惦记打卡这件事,那种感觉还是很爽的。