前言

刚学会 PHP 的时候写了一个笑话类型的网站,网站的数据是定时从另外一个网站上采集的。但是网站部署在虚拟主机上,所以用不了 crontab 执行定时任务。

解决办法是使用监控宝,定时请求我网站的一个地址,在这个地址里面编写采集数据的逻辑。到了现在已经有很多解决办法,比如 Workerman/Swoole 的定时器组件、GitHub Actions。

本文就是介绍如何用 GitHub Actions 的定时任务将网址推送到百度站长平台,提高文章被收录的速度。

配置 GitHub Actions

首先设置工作流触发条件, push 和 schedule 表示推送代码及定时计划都会触发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
name: 'Push Baidu'

on:
push:
branches:
- gh-pages
schedule:
- cron: '*/5 * * * *'

jobs:
start:
runs-on: ubuntu-latest
steps:
# 检查工作流是否可以访问 actions
- name: Checkout Repository master branch
uses: actions/checkout@v1
# 执行仓库中的脚本文件
- name: Execute script
env:
SITEMAP_URL: ${{ secrets.SITEMAP_URL }}
PUSH_URL: ${{ secrets.PUSH_URL }}
run: php ./.github/push.php -s ${SITEMAP_URL} -p ${PUSH_URL}

*/5 * * * * 表示每五分钟执行一次。

runs-on 的意思是指定工作流运行在什么环境上,ubuntu-latest 表示 Ubuntu 最新版。
steps 中第一个步骤是检查工作流是否可以访问 actions,第二个步骤是执行我们的 PHP 脚本,在执行脚本之前,需要将密钥库中的 SITEMAP_URL 和 PUSH_URL 以环境变量的方式传给脚本。

https://github.com/用户名/仓库名/settings/secrets/actions 中新增两个配置项:

Name Value
SITEMAP_URL 网站的 sitemap 地址,我的是 https://her-cat.com/baidusitemap.xml
PUSH_URL 百度站长平台的推送地址,可以在 百度站长平台 普通收录 => API提交页面中找到,类似于:http://data.zz.baidu.com/urls?site=https://her-cat.com&token=xxxxx

将上面的工作流保存到 .github/workflows 目录下,命名为 push.yml。

编写推送脚本

百度站长平台已经提供了 PHP 推送的例子,我基于这个例子添加了自动获取网址的函数并适配了工作流。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?php

// 获取 sitemap 地址和推送地址
$opt = getopt('s:p:');
if (empty($opt['s']) || empty($opt['p'])) {
throw new \Exception('关键参数不能为空');
}

// 从 sitemap 中解析出网址列表
function get_site_urls($sitemap_url)
{
$content = file_get_contents($sitemap_url);
if (empty($content)) {
return [];
}

$xml = simplexml_load_string($content);
if (!$xml) {
return [];
}

$urls = [];
foreach ($xml->url as $url) {
$urls[] = (string) $url->loc;
}

return $urls;
}

// 将网址列表推送到百度
function push_to_baidu($push_url, $urls)
{
$ch = curl_init();
$options = [
CURLOPT_URL => $push_url,
CURLOPT_POST => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 15,
CURLOPT_POSTFIELDS => implode("\n", $urls),
CURLOPT_HTTPHEADER => ['Content-Type: text/plain'],
];
curl_setopt_array($ch, $options);
return curl_exec($ch);
}

// 获取需要推送的网址列表
$urls = get_site_urls($opt['s']);
if (empty($urls)) {
throw new \Exception('网址列表为空');
}

// 调用推送函数
echo push_to_baidu($opt['p'], $urls).PHP_EOL;

将上面的代码保存到 .github/ 目录下,命名为 push.php。

然后提交代码就可以在 GitHub Actions 中查看工作流的运行状态。

总结

需要注意,如果你的 sitemap 格式和我的不一样,需要修改 get_site_urls 函数解析网址列表的逻辑。

PS:截止到本文发出来,定时计划还是一次都没有运行,我一度以为配置没写对,后来才发现不是到了计划时间就一定会运行!

当定时计划到达执行时间时,会将本次任务放到一个队列里面,每当 GitHub 有可用的机器时才会运行,一般延迟时间约为 3 到 10 分钟。有时可能是更多的时间,甚至几十分钟或一个多小时。但是,如果延迟时间过长,则当天可能不会触发计划的工作流。除了使用外部调度器手动触发工作流之外,没有别的办法。

相关文章: