DevOps文化 & SRE实战分享平台

0%

使用vNote Gitee图床 Hexo Docker打造博客、微信公众号markdown博文编辑神器


文章声明:此文基于木子实操撰写
生产环境:macOS Big Sur 11.1
问题关键字:Gitee Pages图床访问404错误


写在最前面

在博客系统、博客编辑器、微信公众号编辑器等选择上,木子可谓呕心沥血,中间使用过:Typora、MarkdownPad、VSCode,Wordpress、Hexo,Git、FTP、Sync等等,其中还有很多已经忘记了,而且目前的这一套vNote+Gitee图床+自定义Hexo Docker,过程中木子也折腾了很久,也算是比较符合自己的需求了。下面木子简单来聊一聊这一套解决方案。

工具说明

vNote

一款国产开源的Markdown编辑神器,支持Windows、Linux、MacOS,吸引木子最主要的功能是:笔记分类、文章关键字秒级搜索、文章目录树结构等,自带图床功能且支持GitHub、Gitee、微信公众号、腾讯云,但因为其图床是直接将图片上传至对应图床平台,本地不存放副本,这不是木子想要的,万一哪个图床平台挂了,不管是本地文档还是网站、公众号文档都图裂了,而且要将Markdown中的图片一一找回,是一件非常痛苦的事情,所以木子没有使用这个图床功能,而是自己通过导出要发布的文章,然后通过脚本进行图片上传图床,再替换Markdown中图片地址来实现。

Gitee

通过Gitee Pages提供图床,有两个优点,第一国内访问网站的速度更快,第二不需要使用服务器流量加载图片,但有一个问题Gitee上传图片后无法自动更新,需要手动触发更新,木子通过Python selenium模拟点击解决此问题。

Hexo

博客系统,木子基于此创建了Docker镜像,实现了很多附加功能,比如:Let’s encrypt ACME DNS证书自动生成功能(腾讯云)、Markdown自动构建等,详细参考:https://gitee.com/oubayun/Hexo-Blog-Docker

Automated release

Automated-release.py是木子编写的一个自动发布博文的脚本,主要实现以下几个功能:

  • 图片自动等比例缩小50%,目前木子采用的是iShot截图,木子试用了很多截图工具,发现在4K屏上都会出现图片放大的情况,而Hexo又不支持=100px方式缩放功能,所以采用脚本来进行图片缩放。
  • 图片大小自动优化,会自动删除图片中无用的信息,优化后图片大约小30%左右。
  • 自动上传图片至Gitee,将对应的图片上传到Gitee仓库。
  • 自动触发Gitee Pages更新,通过Python selenium模拟点击实现。
  • 上传Markdown至木子的Hexo Blog服务器,通过SFTP方式。

这里木子主要说一下上述功能的Python代码实现,关于Docker镜像的使用,可以参考Gitee仓库使用说明。详细脚本使用说明,木子会在代码块中备注。

自动实现脚本

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
import os
import time
import shutil
import paramiko
import datetime
from PIL import Image
from selenium import webdriver


# 缩小并优化图片大小
def optimize_pictures(filename, targetpath, file):
img = Image.open(filename)
width = img.size[0]
height = img.size[1]
# 等比例缩小50%
img = img.resize((int(width * 0.5), int(height * 0.5)), Image.ANTIALIAS)
img.save(filename)
# 图片优化
os.system("picopt %s" % filename)
shutil.copyfile(filename, "%s/_v_images/%s" % (targetpath, file))


# 上传Markdown至Hexo Blog服务器
def sftp_upload(host, port, username, password, local, remote):
sf = paramiko.Transport((host, port))
sf.connect(username=username, password=password)
sftp = paramiko.SFTPClient.from_transport(sf)
try:
f_list = os.listdir(local)
for i in f_list:
if os.path.splitext(i)[1] == '.md':
remote = remote + '/' + i
sftp.put(i, remote)
except Exception as e:
return ('upload exception:%s' % e)
sf.close()


# 自动更新Gitee Pages
def gitee_pages_action(giteename, giteepasswd, giteeurladdress):
opt = webdriver.ChromeOptions()
driver = webdriver.Chrome(options=opt)
driver.maximize_window()
driver.get('https://gitee.com/login')
input_element = driver.find_element_by_xpath("//*[@id='user_login']")
input_element.send_keys(giteename)
input_element = driver.find_element_by_xpath("//*[@id='user_password']")
input_element.send_keys(giteepasswd)
input_element.submit()
time.sleep(2)
driver.get(giteeurladdress)
time.sleep(3)
driver.find_element_by_xpath("//*[@class='button orange redeploy-button ui update_deploy']").click()
time.sleep(2)
alert = driver.switch_to_alert()
time.sleep(2)
alert.accept()
time.sleep(20)
driver.quit()


if __name__ == "__main__":
# 使用当前日期时间,做为git提交时的描述信息
nowdate = datetime.datetime.now()
# 因为vNote导出markdown会生成对应文件名目录,所以一般木子会将这个脚本复制到对应目录下执行,所以这里使用的是相对路径
filepath = './_v_images/'
# 这里的目标路径即Gitee仓库本地地址
targetpath = '/Users/xxx/Documents/code/blogimage'
ext = ['jpeg', 'jpg', 'png']
files = os.listdir(filepath)

print("1、开始缩小并优化图片大小...")
for file in files:
if file.split('.')[-1] in ext:
filename = '%s%s' % (filepath, file)
optimize_pictures(filename, targetpath, file)

print("2、上传图片到Gitee...")
os.system("cd %s && git add . && git commit -m '%s' && git push" % (targetpath, nowdate))
os.system('''sed -i '.bak' "s#_v_images#https://oubayun.gitee.io/blogimage/_v_images#g" ./*.md''')

print("3、更新Gitee图床...")
giteename = 'xxx'
giteepasswd = 'xxx'
giteeurladdress = 'xxx'
gitee_pages_action(giteename, giteepasswd, giteeurladdress)

print("4、上传Markdown至Hexo Blog系统...")
host = 'xxx'
port = 22
username = 'xxx'
password = 'xxx'
local = './'
remote = '/mdfiles'
sftp_upload(host, port, username, password, local, remote)

关于Gitee Pages自动更新配置

如前面所述,在木子使用Gitee Pages功能做为个人博客图床时,发现有一个问题,就是每一次上传图片以后,需要手动点击Gitee Pages页面的更新才能够正常访问图片,不然会出现404无法访问到的问题,为此了解了相关信息,发现Gitee Pages Action功能,需要Gitee Pages Pro版才能够支持(付费),而且此功能之前支持对个人用户开放,现在只支持对企业开放,换句话说就是给钱也没有办法使用,网上有一个开源项目Gitee Pages Action可以实现此功能,但有一个问题,图片数据量大的时候同步慢,而且配置过于复杂,对于小白用户可能不是很友好,本着不花钱、爱折腾的精神,个人使用Python selenium的模拟点击功能,简单粗暴实现了一下。
首先启用图床功能,创建一个Gitee仓库,然后点击服务Gitee Pages

点击更新以后,就会出现如图所示对应网站地址,这就是你的图床地址,后续木子的自动更新也是模拟点击对应的更新按钮实现的。

代码实现:

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
#! /usr/bin/env python
# coding=utf-8
from selenium import webdriver
import time

def def gitee_pages_action(giteename,giteepasswd,urladdress)
opt = webdriver.ChromeOptions()
driver = webdriver.Chrome(options=opt)
driver.maximize_window()
driver.get('https://gitee.com/login')
input_element = driver.find_element_by_xpath("//*[@id='user_login']")
input_element.send_keys(giteename)
input_element = driver.find_element_by_xpath("//*[@id='user_password']")
input_element.send_keys(giteepasswd)
input_element.submit()
time.sleep(2)
driver.get(urladdress)
time.sleep(3)
driver.find_element_by_xpath("//*[@class='button orange redeploy-button ui update_deploy']").click()
time.sleep(2)
alert = driver.switch_to_alert()
time.sleep(2)
alert.accept()
time.sleep(20)
driver.quit()

if __init__ == __admin__ :
giteename = 'xxx' # Gitee登录账号
giteepasswd = 'xxx' # Gitee登录密码
urladdress = 'xxx' # 个人Gitee Pages地址,如:https://gitee.com/oubayun/blogimage/pages
gitee_pages_action(giteename,giteepasswd,urladdress)

想让上面的代码跑起来,需要安装chromedriverselenium
安装chromedriver
首先查看你Google Chrome浏览器的版本,然后去淘宝镜像站下载对应版本的驱动进行安装。

1
2
3
4
# 安装chromedriver
sudo cp ~/Downloads/chromedriver /usr/local/bin
# 执行chromedriver命令确保成功
chromedriver


安装selenium

1
pip install selenium

写在最后

通过上述的一系列操作,目前此脚本已经实现了木子的基本需求,如果您有疑问,欢迎留言交流。

坚持原创技术分享,您的支持与鼓励,是我持续创作的动力!