使用Hexo创建博客并部署Github上

关键字:Mac、Node.js、Hexo、Github

1. 下载安装Node.js

在这里插入图片描述
在mac的命令行输入一下命令查看是否安装好Node.js:

1
2
3
4
5
6
7
8
9
10
################################################
# 进入root
$ sudo su

################################################
# 查看node和npm版本
sh-3.2# node -v
v14.16.1
sh-3.2# npm -v
6.14.12

2. 安装hexo

用npm安装hexo (依然在root下)

1
sh-3.2# npm install -g hexo-cli

查看hexo版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
sh-3.2# hexo -v
hexo-cli: 4.2.0
os: Darwin 20.3.0 darwin x64
node: 14.16.1
v8: 8.4.371.19-node.18
uv: 1.40.0
zlib: 1.2.11
brotli: 1.0.9
ares: 1.16.1
modules: 83
nghttp2: 1.41.0
napi: 7
llhttp: 2.1.3
openssl: 1.1.1k
cldr: 37.0
icu: 67.1
tz: 2020a
unicode: 13.0

3. 配置Hexo

为博客创建新文件夹,这里以/Users/用户名为例,这个用户名是你电脑的用户名。

1
2
3
4
5
sh-3.2# cd /Users/<用户名>
sh-3.2# pwd
/Users/<用户名>
sh-3.2# mkdir myblog
sh-3.2# cd myblog

在新建文件夹下面初始化Hexo

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
################################################
# 查看是否位于正确的文件夹
sh-3.2# pwd
/Users/<用户名>/myblog

################################################
# 以管理员身份初始化Hexo
sh-3.2# sudo hexo init
INFO Cloning hexo-starter https://github.com/hexojs/hexo-starter.git
INFO Install dependencies
added 190 packages from 160 contributors and audited 196 packages in 6.046s

15 packages are looking for funding
run `npm fund` for details

found 0 vulnerabilities

INFO Start blogging with Hexo!

################################################
# 查看生成的目录结构
sh-3.2# ls -l
total 144
drwxr-xr-x 3 root staff 96 May 2 16:27 .github
-rw-r--r-- 1 root staff 65 May 2 16:27 .gitignore
-rw-r--r-- 1 root staff 0 May 2 16:27 _config.landscape.yml
-rw-r--r-- 1 root staff 2441 May 2 16:27 _config.yml
drwxr-xr-x 165 root staff 5280 May 2 16:27 node_modules
-rw-r--r-- 1 root staff 57414 May 2 16:27 package-lock.json
-rw-r--r-- 1 root staff 615 May 2 16:27 package.json
drwxr-xr-x 5 root staff 160 May 2 16:27 scaffolds
drwxr-xr-x 3 root staff 96 May 2 16:27 source
drwxr-xr-x 3 root staff 96 May 2 16:27 themes

4. 生成第一篇博客

初始化Hexo以后其实就可以生成博客了。

1
2
3
4
5
6
7
8
9
################################################
# 启动本地博客页面 hexo s或者hexo server
sh-3.2# hexo s
INFO Validating config
INFO Start processing
Deprecated as of 10.7.0. highlight(lang, code, ...args) has been deprecated.
Deprecated as of 10.7.0. Please use highlight(code, options) instead.
https://github.com/highlightjs/highlight.js/issues/2277
INFO Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.

这时我们用浏览器打开http://localhost:4000就能看到Hexo为我们准备的默认博客页面了。

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
################################################
# 创建新博客 hexo n或者hexo new
sh-3.2# hexo n "我的第一篇博客"
INFO Validating config
INFO Created: /Users/kangyangwu/myblog/source/_posts/我的第一篇博客.md

################################################
# 为新的博客生成静态文件 hexo g或者hexo generate
sh-3.2# hexo g
INFO Validating config
INFO Start processing
INFO Files loaded in 88 ms
INFO Generated: 2021/05/02/hello-world/index.html
INFO Generated: 2021/05/02/我的第一篇博客/index.html
INFO Generated: archives/2021/05/index.html
INFO Generated: archives/2021/index.html
INFO Generated: index.html
INFO Generated: archives/index.html
INFO 6 files generated in 27 ms

################################################
# 启动本地博客页面
sh-3.2# hexo s
INFO Validating config
INFO Start processing
INFO Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.

5. 部署Github Pages

首先进入github主页,选择创建新的仓库 (New repository)。
在这里插入图片描述
仓库名(repository name) 一定要填写<github用户名>.github.io。**
在这里插入图片描述
在这里插入图片描述
下面开始配置博客,将之与刚创建好的github网站连接起来。

1
2
3
################################################
# 安装hexo-deployer-git
sh-3.2# npm install hexo-deployer-git --save

修改配置文件_config.yml最后一项,记得改成你自己的github个人网站

1
2
3
4
5
6
# Deployment
## Docs: https://hexo.io/docs/one-command-deployment
deploy:
type: git
repo: https://github.com/wukangyang/wukangyang.github.io.git
branch: master
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
################################################
# 部署网页 hexo d或者hexo deploy
sh-3.2# hexo d
INFO Validating config
INFO Deploying: git
INFO Clearing .deploy_git folder...
INFO Copying files from public folder...
INFO Copying files from extend dirs...
[master d553892] Site updated: 2021-05-02 17:47:15
Committer: System Administrator <root@Kangyangs-Mac.local>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly. Run the
following command and follow the instructions in your editor to edit
your configuration file:

git config --global --edit

After doing this, you may fix the identity used for this commit with:

git commit --amend --reset-author

9 files changed, 900 insertions(+), 6 deletions(-)
create mode 100644 2021/04/29/kruskalMST/index.html
create mode 100644 2021/05/02/使用ffmpeg合并多个mp4文件/index.html
create mode 100644 archives/2021/04/index.html
Username for 'https://github.com': yangzaiky
Password for 'https://yangzaiky@github.com':
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 13.77 KiB | 2.29 MiB/s, done.
Total 24 (delta 8), reused 0 (delta 0)
remote: Resolving deltas: 100% (8/8), completed with 3 local objects.
To https://github.com/YangzaiKY/yangzaiky.github.io.git
6fe509f..d553892 HEAD -> master
Branch 'master' set up to track remote branch 'master' from 'https://github.com/YangzaiKY/yangzaiky.github.io.git'.
INFO Deploy done: git

在浏览器打开https://wukangyang.github.io(https://<你的github用户名>.github.io)来查看是否部署成功。

使用ffmpeg合并多个mp4文件

关键词:ffmpeg、Mac、Python、bash

安装ffmpeg

打开浏览器,进入ffmpeg官方下载页面,选择操作系统对应的可执行文件下载选项,直接下载压缩包并且解压即可。
在这里插入图片描述
在这里插入图片描述
解压完”ffmpeg-4.4.7z”会得到一个”ffmpeg”的可执行文件,此时我们在命令行是无法使用ffmpeg命令的,因为我们并没有安装ffmpeg到系统,只是下载了可执行文件,下一步我们打开Terminal,把ffmpeg的可执行文件移动到”/usr/local/bin”文件夹下面,这样我们就可以在命名行正常使用ffmpeg相关命令了。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ mv ffmpeg /usr/local/bin
$ ffmpeg -version
ffmpeg version 4.4-tessus https://evermeet.cx/ffmpeg/ Copyright (c) 2000-2021 the FFmpeg developers
built with Apple clang version 11.0.0 (clang-1100.0.33.17)
configuration: --cc=/usr/bin/clang --prefix=/opt/ffmpeg --extra-version=tessus --enable-avisynth --enable-fontconfig --enable-gpl --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libmysofa --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvmaf --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-version3 --pkg-config-flags=--static --disable-ffplay
libavutil 56. 70.100 / 56. 70.100
libavcodec 58.134.100 / 58.134.100
libavformat 58. 76.100 / 58. 76.100
libavdevice 58. 13.100 / 58. 13.100
libavfilter 7.110.100 / 7.110.100
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100

使用Python生成合并mp4的bash脚本

ffmpeg官网的wiki提供了合并多媒体文件的方法:
在这里插入图片描述
由于mp4文件较多,一行一行敲太麻烦,所以就用python直接生成bash文件,由于python自带的sort的结果可能不是我们想要的,比如会变成0.mp4, 1.mp4, 10.mp4, 2.mp4…,所以安装netsort(pip install natsort)来帮助完成排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import os
from natsort import natsorted

# 存储当前文件夹下的所有mp4文件路径
L = []
for root, dirs, files in os.walk('.'):
files = natsorted(files)
for file in files:
# 只处理mp4文件
if os.path.splitext(file)[1] == '.mp4':
file_path = os.path.join(root, file)
L.append(new_path)

# 生成bash文件
with open('concat_mp4.sh', 'w') as f:
f.write("#! /bin/bash\n\n")
for l in L:
f.write(f"ffmpeg -i {l} -vcodec copy -acodec copy -vbsf h264_mp4toannexb {l.replace('.mp4', '.ts')}\n")

f.write(f'\nffmpeg -i "concat:{"|".join([i.replace(".mp4", ".ts") for i in L])}" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4\n')
f.write('rm *.ts')

运行该python脚本即可得到下面的bash文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#! /bin/bash

ffmpeg -i ./0.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./0.ts
ffmpeg -i ./1.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./1.ts
ffmpeg -i ./2.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./2.ts
ffmpeg -i ./3.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./3.ts
ffmpeg -i ./4.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./4.ts
ffmpeg -i ./5.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./5.ts
ffmpeg -i ./6.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./6.ts
ffmpeg -i ./7.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./7.ts
ffmpeg -i ./8.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./8.ts
ffmpeg -i ./9.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./9.ts
ffmpeg -i ./10.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./10.ts
ffmpeg -i ./11.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./11.ts
ffmpeg -i ./12.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./12.ts
ffmpeg -i ./13.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb ./13.ts

ffmpeg -i "concat:./0.ts|./1.ts|./2.ts|./3.ts|./4.ts|./5.ts|./6.ts|./7.ts|./8.ts|./9.ts|./10.ts|./11.ts|./12.ts|./13.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4
rm *.ts

下面只要在Terminal里运行即可完成当前文件夹下的mp4合并,输出文件为output.mp4。

1
$ bash concat_mp4.sh

最小生成树MST Kruskal算法

代码参考来源

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
//
// main.cpp
// KruskalMST
//
// Created by YangZai on 22.04.21.
//

#include <iostream>
#include <map>
using namespace std;

/* 并查集(Disjoint-Set)节点(node)的定义 */
typedef struct _dsetNode
{
// 节点的值/名字
char data;
// 当前节点作为代表节点时集合的大小(包含节点的数量),仅当为代表节点时有意义
int rank;
// 节点的父母节点
_dsetNode *parent;
}dsetNode;

/* 记录某一时刻集合的数目 */
int count = 0;

/* map用节点值/名字来获取节点的地址 */
map<char, dsetNode*> mymap;

/* MakeSet函数根据节点值构建节点,并将其存进mymap中 */
void MakeSet(char data)
{
dsetNode* node = new dsetNode;
node->data = data;
mymap[data] = node;
// 初始rank为1,代表集合包含1个节点即节点本身
node->rank = 1;
// 初始节点的父母节点为节点本身
node->parent = node;
// ::(作用域运算符)用来指定访问全局变量里的count
::count++;
}

/*
函数FindSetRoot输入是一个节点的指针,返回该节点所在集合的代表节点的指针,这里用了路径压缩,
也就是说在查找过程中经过的节点都会直接连在代表节点的后面,以后这些节点的查找时间复杂度就是O(1)。
*/
dsetNode *FindSetRoot(dsetNode *node)
{
if (node != node->parent)
{
node->parent = FindSetRoot(node->parent);
}
return node->parent;
}

/* FindSet函数根据节点值来获取该节点所在集合的代表节点值 */
char FindSet(char x)
{
dsetNode *node = mymap[x];
node = FindSetRoot(node);
return node->data;
}

/* isconnected函数检查两个节点所在集合是否相连即是否属于同一集合 */
bool isconnected(char x, char y)
{
return (FindSet(x) == FindSet(y));
}

/* LinkSet函数用来合并两个集合,rank值小的要合并到rank值大的集合里 */
void LinkSet(char x, char y)
{
if (isconnected(x, y))
{
return;
}
dsetNode *node1 = mymap[x];
dsetNode *node2 = mymap[y];
if (node1->rank > node2->rank)
{
node2->parent = node1;
// 合并完以后更新rank值
node1->rank += node2->rank;
}
else
{
node1->parent = node2;
node2->rank += node1->rank;
}
// 每合并两个集合则总集合数量减1
::count--;
}

/* UnionSet函数用来调用LinkSet来合并两个集合 */
void UnionSet(char x, char y)
{
LinkSet(FindSet(x), FindSet(y));
}

/* freeset用来释放程序运行过程中动态申请的内存,防止内存泄漏 */
void freeset(char arr[], int n)
{
for (int i = 0; i < n; ++i)
{
dsetNode *node = mymap[arr[i]];
delete node;
}
}

/* QuickSort原地快速排序 */
void QuickSort(int array[], int low, int high, char edgein[], char edgeout[])
{
int i = low, j = high;
// 使用中间位置的值为中轴
int pivot = array[(low + high)/2];

while (i <= j)
{
while (array[i] < pivot)
{
++i;
}
while (array[j] > pivot)

{
--j;
}

if (i <= j)
{
// 交换i和j位置的数
int i_tmp = array[i];
array[i] = array[j];
array[j] = i_tmp;

char c_tmp = edgein[i];
edgein[i] = edgein[j];
edgein[j] = c_tmp;

c_tmp = edgeout[i];
edgeout[i] = edgeout[j];
edgeout[j] = c_tmp;

++i;
--j;
}
}

// 递归对子序列进行排序
if (i < high)
{
QuickSort(array, i, high, edgein, edgeout);
}
if (j > low)
{
QuickSort(array, low, j, edgein, edgeout);
}
}

/* MSTKruskal函数用来得到最小生成树 */
void MSTKruskal(char vertices[], char edgein[], char edgeout[], int weight[], int n, int m)
{
// 创建初始化节点
for (int i = 0; i < n; ++i)
{
MakeSet(vertices[i]);
}

// 根据权重对边界进行非降序排序
QuickSort(weight, 0, m-1, edgein, edgeout);

int A = 0;
cout << "最小生成树包含的边界:" << endl;
/*
i用来遍历所有边界,count代表目前集合的数目,如果只剩一个集合了,
就说明已经得到最小生成树了,可以提前结束循环。
*/
for (int i = 0; i < m && ::count > 1; ++i)
{
// 如果当前边界会造成环则忽略,即边界两端节点属于同一集合
if (isconnected(edgein[i], edgeout[i]))
{
continue;
}

// 将边界添加到最小生成树中,即合并边界两端节点所在的集合
UnionSet(edgein[i], edgeout[i]);
A += weight[i];
cout << "\t" << edgein[i] << "--" << edgeout[i] << endl;
}
cout << "最小生成树总共的权重为: " << A << endl;

// 释放用new动态申请的内存,防止内存泄漏
freeset(vertices, n);
}


int main(int argc, const char * argv[]) {
char vertices[] = {'A', 'B', 'C', 'D', 'E', 'F'};

char edgein[] = {'A', 'A', 'A', 'B', 'B', 'C', 'C', 'D', 'D'};
char edgeout[] = {'B', 'D', 'C', 'D', 'E', 'D', 'F', 'E', 'F'};
int weight[] = {6, 5, 3, 8, 2, 2, 6, 5, 3};

// 节点数目n和边界数目m
int n = sizeof(vertices) / sizeof(vertices[0]);
int m = sizeof(weight) / sizeof(weight[0]);
MSTKruskal(vertices, edgein, edgeout, weight, n, m);

return 0;
}

/*
输出:
最小生成树包含的边界:
B--E
C--D
D--F
A--C
D--E
最小生成树总共的权重为: 15
*/