通过GitHub Actions实现自动爬取Bing壁纸并保存
由于Bing每天的壁纸都很好看,所以我想每天都保存一下当天的壁纸,供以后看。但是因为人工操作总会有各种问题,遗忘、误操作等,就存在会遗漏的情况。当然还有另外一个情况,就是懒,不想每天去执行,程序员不应该做这种无趣的事情。
附上项目地址
壁纸爬取程序的发展历史
通过Python
,每次电脑开机
时爬取最新的7天壁纸
缺点:
- 如果电脑有7天没开机,那么就会至少丢失一天的壁纸
- 通过打包程序打包成一个EXE程序,每次开机时会弹窗,影响开机使用体验,不知道的还以为中毒了
通过Java
,写一个SpringBoot
程序,跑在常年开启的主机上,通过定时任务
爬取最新的7天的壁纸
缺点
- 主机长期开机,存在不确定的问题。
- 可能会有网络、系统不大稳定的情况,导致保存失败
通过Java
和Github Actions
,依托于Github
的高可用性,以及Github
的网络环境,通过定时任务自动保存壁纸
这是第一个版本,虽然达到了标题的目的,但是有一个很明显的痛点,就是因为每次都是拉取仓库,然后执行程序,然后提交并推送变更。由于仓库较大且后续可能会变得更大,每次任务的执行时间会变得越来越长,目前已经需要执行10分钟+
新的思路
- 创建两个分支,一个是保存图片的分支(main),一个是保存代码的分支(code)
- 执行时拉取并签出code分支,然后打包、编译、执行。这样就会在本地产生变更
- 将变更提交并推送到一个非main/code分支的一个临时分支(pr-branch)
- 创建一个Push Request,由pr-branch分支到main分支
- 自动合并合并请求
分析
原先的时间较长的版本已经完成了第一步和第二步,比较复杂的就是提交到临时分支,创建PR请求,然后自动合并PR请求
实操
- 提交到临时分支
- name: Push changes uses: ad-m/github-push-action@master with: github_token: ${{ secrets.MY_GIT_TOKEN }} branch: pr-branch force: "true"
在原先推送的基础上指定一下分支即可
- 创建PR请求
最开始的时候找到的action是peter-evans/create-pull-request@v6
,这个方法确实可以创建PR请求,并且把上一步推送也进行了合并,直接2合1,但是有一个缺点,他是在本地通过Git命令进行分支合并,同样需要签出main分支,那结果还是一样的慢。
# 最开始的版本
- name: Create pull request
id: cpr
uses: peter-evans/create-pull-request@v6
with:
base: main
branch: pr-branch
commit-message: update resources
title: update resources
body: update resources
当我还在想是不是有别的方法的时候,我发现通过Github的界面可以直接创建PR,且速度很快,不需要签出分支等杂七杂八的操作,然后就往这个方面去思考,最后找到了actions/github-script@v6
。这个action其实就是对github的api的一些封装,通过方法并指定函数来请求api。这里还给PR打上了automerge
标签,目的是为了区分action创建的PR和自己创建的PR,避免搞混了
- name: Create Pull Request
id: cpr
uses: actions/github-script@v6
with:
script: |
const { repo, owner } = context.repo;
const result = await github.rest.pulls.create({
title: 'pr-title',
owner,
repo,
head: 'pr-branch',
base: 'main',
body: 'pr-body'
});
github.rest.issues.addLabels({
owner,
repo,
issue_number: result.data.number,
labels: ['automerge']
});
return result.data.number
- 自动合并请求
- id: automerge name: automerge uses: "pascalgn/automerge-action@v0.16.3" env: GITHUB_TOKEN: "${{ secrets.MY_GIT_TOKEN }}" MERGE_DELETE_BRANCH: "true" PULL_REQUEST: ${{ steps.cpr.outputs.result }}
很轻松的找到了这个指令,但是不能确定应该自动合并的是哪一个请求,发现上一步最终可以返回一些自定义的结果信息,且这个接口有返回创建的PR Number。所以又要回到上一步,在返回的地方添加了PR Number,并在这一步指定,直接合并。为了避免分支的异常,还在合并之后删除原分支
