Hexo使用PythonSDK整站静态发布七牛云

前言

最近因GitLab的国内访问速度问题将本站静态化到了七牛云存储,但是带来的问题也是很明显的。之前在GitLab使用Page来发布工程只需要提交代码即可,会自动静态化并部署项目,于是乎我就想让静态化并同步到七牛对象存储自动化一些,这也是这篇文章的初衷。

其实在用Python做自动同步之前,我使用的官方提供的一个Window上面的同步工具QSunSync,但是使用起来也不是很方便,最主要的原因是不太符合我整站同步的需求,而且速度极慢。

Python SDK

官网为我们提供了基础的对象存储操作SDK, 点击查看

安装Python SDK

1
pip install qiniu

整个同步过程如下:

  1. 拉取七牛云文件列表。
  2. 获取本地文件列表。
  3. 对比远程文件是否有增量(多余的),进行删除。
  4. 对比本地文件是否有增量(新增的)或者有变化(hash不同),进行上传。

同步脚本文件

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
from qiniu import Auth, put_file, etag, urlsafe_base64_encode, BucketManager, CdnManager
from typing import List, Dict
import os

from qiniu import build_batch_delete


class Sync:
"""
同步目录至七牛云
"""

def __init__(
self,
access_key: str,
secret_key: str,
bucket_name: str,
sync_dir: str,
exclude: List,
cover: bool,
remove_redundant: bool,
host: str,
):
self.bucket_name = bucket_name
self.q = Auth(access_key, secret_key)
self.bucket = BucketManager(self.q)
self.sync_dir = sync_dir
self.exclude = exclude
self.cover = cover
self.remove_redundant = remove_redundant
self.host = host
self.sync()

def sync(self):
"""
同步操作
:return:
"""
remote_files = self.list_remote()

local_files = self.list_local()

# 首先删除远端仓库中多余的文件
remove_remote_files = []
for remote_filename in remote_files:
if remote_filename not in local_files:
remove_remote_files.append(remote_filename)
print('delete remote file size = ' + str(len(remove_remote_files)))
self.bucket.batch(build_batch_delete(self.bucket_name, remove_remote_files))

cdnManager = CdnManager(self.q)
refreshUrls = []
refreshDirs = [self.host]
# 上传本地文件到远端(仅上传远端不存在的以及修改过的)
for local_filename in local_files:
if (
local_filename not in remote_files
or local_files[local_filename]["hash"]
!= remote_files[local_filename]["hash"]
):
ret, info = put_file(
self.q.upload_token(self.bucket_name, local_filename, 3600),
local_filename,
local_files[local_filename]["fullpath"],
)
remotepath = self.host + ret["key"]
print('uploaded: ' + remotepath)
#refreshUrls.append(remotepath)

print('uploaded size = ' + len(refreshUrls))
# 刷新节点资源
cdnManager.refresh_dirs(refreshDirs)
print('sycn completed !!!!')

def list_remote(self) -> Dict:
"""
列出远程仓库所有的文件信息
:return: List
"""
result = {}
marker = None
ret = self.bucket.list(self.bucket_name, marker=marker, limit=500)[0]
for file in ret["items"]:
result[file["key"]] = file
if("marker" in ret):
marker = ret["marker"]
while(marker):
print('marker = ' + marker)
ret = self.bucket.list(self.bucket_name, marker=marker, limit=500)[0]
for file in ret["items"]:
result[file["key"]] = file
if("marker" in ret):
marker = ret["marker"]
else:
break
print('pull remote file info success')
return result

def list_local(self) -> Dict:
"""
列出本地仓库所有的文件信息
"""
files = {}

def get_files(path):
for filename in os.listdir(path):
if filename in self.exclude:
continue
fullpath = os.path.join(path, filename)
if os.path.isfile(fullpath):
key = fullpath.split(self.sync_dir)[1]
foldpath = key.replace("\\","/") #实际是相对路径
files[foldpath] = {"fullpath": fullpath, "hash": etag(fullpath)}
else:
get_files(fullpath)
get_files(self.sync_dir)
print('list local file info success')
return files


if __name__ == "__main__":
Sync(
access_key="nzt90pr6nkba0dG1TD2oMul0XHBe6ALuBo3hHc_l", # access_key
secret_key="yoRI0b8J9dDiYwtJeE844tYbrupdjSiVio6sczf1", # secret_key
bucket_name="blog", # bucket_name
#sync_dir="~/blog/public/", # 静态文件目录(后面必须有斜杠/)
sync_dir="D:\\blog\\gitlab\\public\\",
exclude=[".DS_Store"],
cover=True,
remove_redundant=True,
host="https://dp2px.com/",
)

如何使用

如果你也想和我一样将整站的资源同步到七牛云,则只需要第一步使用hexo g来生成静态资源到public目录,然后配置上面Sync类的构造参数,最后执行python blog-qiniu.py即可。

1
2
3
4
5
6
7
Sync(
access_key="xxxxxx", # access_key
secret_key="xxxxxx", # secret_key
bucket_name="blog", # bucket_name
sync_dir="D:\\blog\\gitlab\\public\\", #本地public静态资源目录
host="https://dp2px.com/", #网站host,用于刷新cdn缓存
)

上面值得注意的是代码中的七牛CDN缓存刷新,官方限制了每日100条缓存文件刷新和10条缓存目录刷新,显然这100条是不够用的,所以每次提交完后我会使用refresh_dirs(refreshDirs)主动刷新更目录一次。或者可以换个思路、刷新主页面几个入口界面即可。

1
2
3
4
5
6
7
8
9
10
11
refreshUrls = [
self.host + 'index.html' # 刷新首页

]
refreshDirs = [
self.host + 'tags/', # 刷新标签页
self.host + 'categories/', # 刷新分类页
self.host + 'archives/' # 刷新归档页
]
cdnManager = CdnManager(self.q)
cdnManager.refresh_urls_and_dirs(refreshUrls, refreshDirs)

除了上面使用官方提供的SDK去刷新外,还可以去融合CDN的刷新预取界面手动操作刷新。

有的朋友可能会发现刷新后去浏览器访问并没有发生改变,那是因为在七牛对象存储的设置界面有一个maxAge缓存时间设置,我建议设置成1000,也就是17分钟左右后会重新请求新页面。

七牛对象存储maxAge设置

最后提一下,本站对整站资源进行了压缩处理,以便有更快的访问速度,安装npm install hexo-neat --save插件,在根目录_config.yml文件中配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 文件压缩,设置一些需要跳过的文件 
# hexo-neat
neat_enable: true
# 压缩 html
neat_html:
enable: true
exclude:
# 压缩 css
neat_css:
enable: true
exclude:
- '**/*.min.css'
# 压缩 js
neat_js:
enable: true
mangle: true
output:
compress:
exclude:
- '**/*.min.js'
- '**/jquery.fancybox.pack.js'
- '**/index.js'

在执行hexo g的同时会压缩静态网站资源,如果发生错误不用理会,不会影响实际展示,只是部分页面得不到正确压缩而已。

GitLab CI/CD

GitLab提供持续集成服务。如果添加一个.gitlab-ci.yml文件到项目根目录,并配置GitLab项目使用某个Runner,然后每一次提交或者是推送都会触发CI pipeline.

.gitlab-ci.yml文件会告诉GitLab Runner 做什么。默认情况下,它运行一个pipeline,分为三个阶段:build,test,deploy。你并不需要用到所有的阶段,没有job的阶段会被忽略。

简而言之,CI所需要的步骤可以归结为:

  1. 添加.gitlab-ci.yml到项目的根目录
  2. 配置一个Runner

从此刻开始,在每一次push到Git仓库的过程中,Runner会自动开启pipline,pipline将显示在项目的Pipline页面中。

GitLab CI/CD

接下来我们可以配置.gitlab-ci.yml来自动静态编译压缩和执行python脚本。

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
before_script:
- apt-get update -qq && apt-get install -y -qq pandoc
image: node:10.15.1
pages:
cache:
paths:
- node_modules/
script:
- git config --global user.email "lxq_xsyu@163.com"
- git config --global user.name "lxqxsyu"
- npm install hexo-cli -g
- npm install
- npm uninstall hexo-renderer-marked@0.3.2 --save
- npm install hexo-generator-sitemap@1.2.0 --save
- npm install hexo-generator-baidu-sitemap@0.1.5 --save
- npm install hexo-util@0.6.3 --save
- npm install hexo-generator-search@2.3.0 --save
- npm install image-size@0.6.3 --save
- npm install hexo-asset-image@0.0.3 --save
- npm install hexo-generator-feed@1.2.2 --save
- npm install hexo-neat --save
- npm install hexo-helper-live2d@3.1.1 --save
- hexo g
- python --version
- apt-get -y install python-pip
- pip install qiniu
- pip install typing
- python blog-qiniu.py
artifacts:
paths:
- public
only:
- master

本来这些配置以及可以解决问题,只需要提交代码就可以自动执行,但是在执行过程中发现镜像中的python版本是2.7的,所以我们需要修改之前编写的blog-qiniu.py中的部分代码来适应低版本, 例如asii编码问题需要添加如下代码:

1
2
3
4
5
6
# -*- coding: utf-8 -*-
#!/usr/bin/python
import sys

reload(sys)
sys.setdefaultencoding('utf8')

评论

Ajax Android AndroidStudio Animation Anroid Studio AppBarLayout Banner Buffer Bulma ByteBuffer CDN CMYK COM1 COM2 CSS Camera Raw, 直方图 Chrome ContentProvider CoordinatorLayout C语言 DML DOM Dagger Dagger2 Darktable Demo Document DownloadManage Element Error Exception Extensions File FileProvider Fresco Git GitHub GitLab Gradle Groovy HTML5 Handler HandlerThread Hexo Hybrid IDEA IO ImageMagick IntelliJ Intellij Interpolator JCenter JNI JS Java JavaScript JsBridge Kotlin Lab Lambda Lifecycle Linux Looper MVC MVP Maven MessageQueue Modbus Momentum MySQL NDK NIO NexT Next Nodejs ObjectAnimator Oracle VM Permission PhotoShop Physics Python RGB RS-232 RTU Retrofit Runnable RxAndroid RxJava SE0 Spring SpringBoot Statubar Task Theme Thread Tkinter UI UIKit UML VS Code ValueAnimator ViewPropertyAnimator Web Web前端 Workbench api apk by关键字 compileOnly css databases demo hexo hotfix html iOS icarus implementation init jQuery javascript launchModel logo merge mvp offset photos pug query rxjava2 scss servlet shell svg tkinter tomcat transition unicode utf-8 vector virtual box 七牛 下载 中介者模式 串口 主题 事件 享元模式 仓库 代理模式 位运算 依赖注入 修改,tables 光和色 内核 函数 函数式编程 分支 分析 创建 删除 动画 单例模式 压缩图片 发布 可空性 合并 同向性 后期 启动模式 命令 命令模式 响应式 响应式编程 图层 图床 图片压缩 图片处理 图片轮播 地球 域名 基础 增加 备忘录模式 外观模式 多线程 大爆炸 天气APP 太白山 奇点 字符集 存储引擎 宇宙 实践 属性 属性动画 工具 工厂模式 年终总结 异常 弱引用 恒星 打包 技巧 插件 摄影 操作系统 攻略 故事 数据库 数据类型 文件 新功能 旅行 旋转木马 时序图 时空 时间简史 曲线 杂谈 权限 架构 查询 标签选择器 样式 核心 框架 案例 桥接模式 模块化 模板引擎 模板方法模式 泛型 浅色状态栏 源码 瀑布流 热修复 版本 版本控制 状态栏 状态模式 生活 留言板 相册 相对论 知识点 码云 磁盘 科学 笔记 策略模式 类图 系统,发行版, GNU 索引 组件 组合模式 结构 编码 网易云信 网格布局 网站广播 网站通知 网络 美化 膨胀的宇宙 自定义 自定义View 自定义插件 蒙版 虚拟 补码 表单 装饰模式 西安 观察者模式 规范 视图 视频 解耦器模式 设计 设计原则 设计模式 访问者模式 语法 责任链模式 贪吃蛇 转换 软件工程 软引用 运算符 迭代子模式 适配器模式 选择器 通信 通道 配置 锐化 错误 键盘 闭包 降噪 面向对象 项目构建 黑洞
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×