我是程序员,我用这种方式铭记历史
✨War Of Resistance Live: 记录14年抗战的日日夜夜
前言
在目前浮躁的互联网环境下,做一件好事不难,难的是连续8年做一件有意义的事。
在微博上有这样一位博主,从2012年7月7日开始,截至到2020年9月2日, 以图文形式,记录了从1937年7月7日至1945年8月15日中华民族全面抗战的这段历史。2980 天,从未间断,平均每天 12 条,累计 35214 篇。
2020年9月18日7时零7分,沉寂了半个月的 恢复更新,他们将继续以图文的形式记录1931年9月18日至1937年7月7日这六年的抗战历史。
下一个 6 年,他们已经在路上。
历史是不能被遗忘的。
作为程序员的我,在历史面前,我能做点什么?
除了敬佩 这么多年来的坚持,我更想做一点自己力所能及且有意义的事情。
War Of Resistance Live
├── .github/workflows # 工作流配置文件
├── resources # 微博数据
├── site # 博客源码
└── spider # 微博爬虫
是一个主要由 爬虫 + 博客 + 持续集成服务组成的开源项目,开源在 上,并且部署于 。目前包含以下功能:
每日定时自动同步更新数据
查看博主目前所有的微博数据
支持订阅功能
基于的持续集成服务
...
接下来,我将简单的给大家介绍该项目的一些核心逻辑与实现。
Python 爬虫
该项目使用的爬虫是基于 项目的简化及修改实现(仅供研究使用),感谢作者 [dataabc](https://github.com/dataabc)。
实现原理
通过开发者工具查看得知,通过 接口 即可获取微博数据列表:
```python
def get_json(self, params):
"""获取网页中json数据"""
url = 'https://m.weibo.cn/api/container/getIndex?'
r = requests.get(url,
params=params,
headers=self.headers,
verify=False)
return r.json()
```
如何使用
安装依赖:
pip3 install -r requirements.txt
使用:
python weibo.py
注意事项
速度过快容易被系统限制:可通过加入随机等待逻辑,可降低被系统限制的风险;
无法获取全部微博数据:可通过添加 逻辑获取全部数据;
Hexo
经过了一番的抉择,最终选择 + [Next](https://github.com/theme-next/hexo-theme-next) 主题作为本项目的博客框架。
是一款基于 的静态博客框架,依赖少易于安装使用,可以方便的生成静态网页托管在 上,还有丰富的主题可供挑选。关于如何安装使用 可详细查看官方文档:。
那么,如何实现 订阅功能呢?
首先,在博客根目录下安装该插件:
$ npm install hexo-generator-feed --save
接着,在博客根目录下的 文件中添加相关配置:
feed:
enable: true # 是否启用插件
type: atom # Feed的类型,支持 atom 和 rss2,默认 atom
path: atom.xml # 生成文件的路径
limit: 30 # 生成最大文章数,如果为 0 或 false 则生成所有的文章
content: true # 如果为 true 则展示文章所有内容
content_limit: # 文章展示的内容长度,仅当 content 为 false 有效
order_by: -date # 按照日期排序
template: # 自定义模板路径
最后,在主题根目录下的 文件中添加 订阅入口:
menu:
RSS: /atom.xml || fa fa-rss # atom.xml文件路径地址和图标设置
这样,我们就可以为自己的博客添加 订阅功能。 的订阅地址为:
https://kokohuang.github.io/WarOfResistanceLive/atom.xml
Github Actions 持续集成
是由 于 推出的持续集成服务,在此之前,我们可能更多的使用 来实现持续集成服务。以我个人的感觉来看, 功能非常强大,比 的可玩性更高, 拥有丰富的 市场,将这些 组合起来,我们就可以很简单的完成很多很有趣的事情。
我们先来看看 的一些基本概念:
workflow:工作流程。即持续集成一次运行的过程。该文件存放于仓库的 目录中,可包含多个;
job:任务。一个 可包含一个或多个 ,即代表一次集成的运行,可完成一个或多个任务;
step:步骤。一个 由多个 组成,即代表完成一个任务需要哪些步骤;
action:动作。每个 里面可包含一个或多个 ,即代表一个步骤内,可执行多个 动作。
了解了 的这些基本概念后,我们来看看 的持续集成服务是怎样实现的,以下是本项目使用的 完整实现:
# workflow 的名称
name: Spider Bot
# 设置时区
env:
TZ: Asia/Shanghai
# 设置工作流触发方式.
on:
# 定时触发,在 8:00-24:00 间每隔 2 小时更新一次(https://crontab.guru)
# 由于 cron 设定的时间为 UTC 时间,所以 +8 即为北京时间
schedule:
- cron: "0 0-16/2 * * *"
# 允许手动触发 Actions
workflow_dispatch:
jobs:
build:
# 使用 ubuntu-latest 作为运行环境
runs-on: ubuntu-latest
# 将要执行的任务序列
steps:
# 检出仓库
- name: Checkout Repository
uses: actions/checkout@v2
# 设置 Python 环境
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: "3.x"
# 缓存 pip 依赖
- name: Cache Pip Dependencies
id: pip-cache
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('./spider/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
# 安装 pip 依赖
- name: Install Pip Dependencies
working-directory: ./spider
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
# 运行爬虫脚本
- name: Run Spider Bot
working-directory: ./spider # 指定工作目录,仅对 run 命令生效
run: python weibo.py
# 获取系统当前时间
- name: Get Current Date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%d %H:%M')"
# 提交修改
- name: Commit Changes
uses: EndBug/add-and-commit@v5
with:
author_name: Koko Huang
author_email: huangjianke@vip.163.com
message: "已同步最新数据(${{steps.date.outputs.date}})"
add: "./"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# 推送远端
- name: Push Changes
uses: ad-m/github-push-action@master
with:
branch: main
github_token: ${{ secrets.GITHUB_TOKEN }}
# 设置 Node.js 环境
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: "12.x"
# 缓存 NPM 依赖
- name: Cache NPM Dependencies
id: npm-cache
uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('./site/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
# 安装 NPM 依赖
- name: Install NPM Dependencies
working-directory: ./site
run: npm install
# 构建 Hexo
- name: Build Hexo
working-directory: ./site # 指定工作目录,仅对 run 命令生效
run: npm run build
# 发布 Github Pages
- name: Deploy Github Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./site/public # 指定待发布的路径地址
publish_branch: gh-pages # 指定远程分支名称
文件的配置字段非常多,配置文件中也给出了详细的注释。接下来,我们主要看下以下几个比较重要的配置:
工作流的触发方式
# 设置工作流触发方式.
on:
# 定时触发,在 8:00-24:00 间每隔 2 小时更新一次(https://crontab.guru)
# 由于 cron 设定的时间为 UTC 时间,所以 +8 即为北京时间
schedule:
- cron: "0 0-16/2 * * *"
# 允许手动触发工作流程
workflow_dispatch:
我们可以使用 工作流程语法配置工作流程为一个或多个事件运行。支持自动与手动两种方式触发。 事件允许我们在计划的时间触发工作流程,我们可以使用 来安排工作流程在特定的时间运行。
计划任务语法有五个字段,中间用空格分隔,每个字段代表一个时间单位:
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of the month (1 - 31)
│ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
│ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
* * * * *
我们可以使用 来生成计划任务语法,你也可以查看更多的 [crontab guru 示例](https://crontab.guru/examples.html)。
另外,我们还可以通过配置 和 字段来实现手动触发工作流程。
字段也可以配置为 ,即仓库有 操作时则触发工作流的执行,详细的触发工作流配置可以查看 。
步骤序列
从配置文件中我们可以看到,该项目的一次持续集成的运行包含了以下步骤:

检出仓库 --> 设置 环境 --> 缓存 依赖 --> 安装 依赖 --> 运行爬虫脚本 --> 获取当前时间 --> 提交修改 --> 推送远端 --> 设置 环境 --> 缓存 依赖 --> 安装 依赖 --> 构建 --> 发布
本项目的 主要有以下几个要点:
运行环境:整个工作流运行在虚拟环境 。还可以指定其他虚拟环境,如 、 等;
**构建 **:即执行 命令生成静态网页;
工作流程中的身份验证:提交推送及发布步骤需要进行身份验证。 提供一个令牌,可用于代表 进行身份验证。我们所需要做的就是创建一个命名为 的令牌。具体步骤如下: --> --> --> ,命名为 ,并勾选中你所需要的的权限,然后就可以在 中通过使用 进行身份验证。
结语
“我们直播抗战,并非为了鼓动仇恨等负面的情绪,而是想适度唤起遗忘,当我们时刻牢记祖辈们蒙受的苦难、恐惧和屈辱时;当我们体味祖辈们是如何在国家民族危亡之际抛弃前嫌,实现民族和解时,当我们目睹着祖辈们是如何从容慷慨的走向死亡,以身体为这个国家献祭之时,相信我们对于现实将有更加成熟和理性的思考。”
铭记历史,砥砺奋进。
勿忘国耻,吾辈自强。