使用 GitHub Actions 自动获取 Hostloc 论坛积分

博主其实在 GitHub Actions 还没正式推出时就申请到了测试资格,奈何自己的博客早就配置了 Travis CI 自动构建(现已更换),懒得修改了,又没有什么其他项目,所以根本没有实践过。

最近闲了下来,稍微过了一下 GitHub Actions 的文档,然后折腾了个自动获取 Hostloc 论坛(全球主机交流论坛)积分的小工具,在这里简单介绍一下吧。

2021年5月19日更新

由于 GitHub 的使用政策更新,似乎不再允许该类用途,本仓库在近期的严查中不幸被封禁了,在跟 GitHub 联系后已确认无法解封(他们不接受任何整改意愿,甚至都不能让我将数据备份一下)。

本项目将不再更新,原代码库备份可以从以下链接获取:https://git.inkuang.com/inkuang/hostloc-auto-get-points

快速使用

如果你对那些代码、原理不感兴趣,只是想要用这么个东西的话只要看这一小节就够了,详细讲解放在后面。

首先 Fork 我写好代码的仓库:https://github.com/inkuang/hostloc-auto-get-points

然后在你 Fork 的仓库页面点击右上角的 Settings,找到 Secrets 这一项,添加两个秘密环境变量。

设置秘密环境变量

其中 HOSTLOC_USERNAME 存放你在 Hostloc 的帐户名,HOSTLOC_PASSWORD 存放你的帐户密码。支持同时添加多个帐户,数据之间用半角逗号 , 隔开即可,帐户名和帐户密码需一一对应。

设置好环境变量后点击你的仓库上方的 Actions 选项,会打开一个如下的页面,点击 I understand... 按钮确认在 Fork 的仓库上启用 GitHub Actions 。

在 Fork 的仓库上面启用 GitHub Actions

此时页面上会显示当前仓库所有的 Workflows,点击左侧的 Hostloc Auto Get Points,然后点击页面上黄色提醒框 This scheduled workflow is disabled... 处的 Enable workflow 按钮确认在 Fork 的仓库上启用 GitHub Actions 定时任务。

最后在你这个 Fork 的仓库内随便改点什么(比如给 README 文件删掉或者增加几个字符)提交一下手动触发一次 GitHub Actions 就可以了。

仓库内包含的 GitHub Actions 配置文件会在每天国际标准时间 17 点(北京时间凌晨 1 点)自动执行获取积分的脚本文件,你也可以通过 Push 操作手动触发执行(测试发现定时任务的执行可能有 5 到 10 分钟的延迟,属正常现象,耐心等待即可)。

注意: 为了实现某个链接/帐户访问出错时不中断程序继续尝试下一个,GitHub Actions 的状态将永远是“通过”(显示绿色的✔),请自行检查 GitHub Actions 日志 Get points 项的输出确定程序执行情况。

获取积分原理及代码

在 Hostloc 论坛上,访问他人用户空间每次可以获得 2 积分,每天最多 20 积分。这个小工具就是基于这一原理,使用代码模拟用户登录,然后随机访问用户空间来实现的。

详细代码可以到我的 GitHub 仓库 查看,这里只介绍几个关键点。

观察发现,用户空间的链接都是类似 https://www.hostloc.com/space-uid-{}.html 的格式,大括号内就是用户 id,基于此,我们随机生成一定数量的用户 id,然后构造一系列的用户空间链接:

1
2
3
4
5
6
7
8
def randomly_gen_uspace_url():
url_list = []
# 访问小黑屋用户空间不会获得积分、生成的随机数可能会重复,这里多生成两个链接用作冗余
for i in range(12):
uid = random.randint(10000, 50000)
url = "https://hostloc.com/space-uid-{}.html".format(str(uid))
url_list.append(url)
return url_list

比较关键的,登录,可以打开浏览器开发者工具的 Network 选项,然后在论坛首页使用错误的用户名、密码登录一次(正确的帐户在点击登录后页面会发生跳转,就看不到数据了),会发现我们请求了 member.php 这个文件,在它的 Headers 里可以看到我们使用 post 发送了一组数据。

利用这些获取的数据和 requestsSession 对象,我们可以很轻松的实现登录功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def login(username, password):
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
"origin": "https://www.hostloc.com",
"referer": "https://www.hostloc.com/forum.php",
}
login_url = "https://www.hostloc.com/member.php?mod=logging&action=login&loginsubmit=yes&infloat=yes&lssubmit=yes&inajax=1"
login_data = {
"fastloginfield": "username",
"username": username,
"password": password,
"quickforward": "yes",
"handlekey": "ls",
}
s = requests.Session()
s.headers.update(headers)
res = s.post(url=login_url, data=login_data)
res.raise_for_status()
return s

接下来只要使用登录后的 Session 对象,依次 get 前面生成的用户空间链接即可,这里不再详述。

需要注意的是,为了安全和方便他人使用,我们这里不把用户名和密码写在代码中,而是通过环境变量获取,这样也方便后面与 GitHub Actions 结合使用。

1
2
username = os.environ["HOSTLOC_USERNAME"]
password = os.environ["HOSTLOC_PASSWORD"]

GitHub Actions 配置

代码写好之后我们只需要将它每天运行一遍就行了。你完全可以手动操作,但那样无疑很麻烦,这里我们使用 GitHub Actions 来自动完成这一步骤。完整配置文件请到我的 GitHub 仓库 查看,这里只简单做一下介绍。

注: GitHub Actions 配置文件的格式请到官方文档查看了解,这里不会涉及。

首先要考虑的就是我们什么时候需要运行这个脚本。很明显,从我们的需求来看具体的运行时间并不重要,只要每天运行一次就行了,这里使用 GitHub Actions 的定时任务来实现,在配置文件的 on 字段中指定(为了方便测试,这里将 push 操作触发也加进来):

1
2
3
4
5
6
on:
push:
branches:
- master
schedule:
- cron: '0 17 * * *'

这里指定在每次 push 操作后或者每天国际标准时间 17 点(也就是北京时间凌晨 1 点)执行。

接下来就是考虑运行环境了。首先检出代码,然后设置 python 版本,再接着安装一下依赖(我们的依赖只有 requests 这一个包)。这样我们的 python 脚本所需要的运行环境就配置完成了。

1
2
3
4
5
6
7
8
- name: 'Checkout codes'
uses: actions/checkout@v2
- name: 'Set python'
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: 'Install dependencies'
run: python -m pip install --upgrade requests

最后,也是最关键的一步:运行我们的脚本。前面提到我们的脚本中登录使用的用户名和密码是从环境变量中读取的,所以在这里我们需要设置一下环境变量。为了安全,我们将用户名和密码存在仓库的 Secrets 中,然后从 GitHub Actions 配置文件的 secrets 域中读取出来并设置为对应的环境变量:

1
2
3
4
5
- name: 'Get points'
env:
HOSTLOC_USERNAME: ${{ secrets.HOSTLOC_USERNAME }}
HOSTLOC_PASSWORD: ${{ secrets.HOSTLOC_PASSWORD }}
run: python hostloc_get_points.py

好啦,基本原理之类的东西就这么些了,花了几个小时撸出来的(主要花在看 GitHub Actions 的文档和折腾论坛的登录机制上面),如果你觉得有用的话不要忘了点个 star 哦~~~