解决Hexo博客批量上传的小问题:利用 Python 脚本提取 HTML 文件

2018-12-12 by Liuqingwen | Tags: Hexo Python | Hits

一、前言

每次写完一篇文章后,我都要手动上传到我的博客空间服务器,虽然算不上麻烦,不过还是非常羡慕那些直接使用 git deploy 命令的朋友们,一键发布,方便快捷啊!

因为 Hexo 博客框架所生成页面都是静态 HTML 文件,所以当我更新博客的某一个功能或者添加一个小插件的时候,所有的页面都会更新,包括图片等文件的修改时间!所谓:“牵一发而动全身”,这个时候我就非常痛苦了,需要重新上传本月的所有文章、今年的所有文章、去年的所有文字……

所以,基于这个痛点,我早已在心里下定了决心,在某一天要亲手“解决它”!嗯,时机来了,最近有空闲时间的时候在自学 Python ,刚好可以尝试练习一下,利用 Python 脚本来提取需要更新的文件,然后复制到一个与源文件路径对应的临时文件夹中,最后批量上传到服务器覆盖即可,不得不说这句话是对的:

人生苦短,我(需要)用 Python !

另外,如果你还没有创建博客,推荐使用 Hexo 搭建;如果刚创建博客,还在搜寻可用插件的话,那么可以参考我之前的几篇文章:

二、正文

注意:本文仅适用于那些使用 Hexo 搭建博客,平时写的文章有大量图片,还需要自己手动上传服务器的朋友。其他同学就请随意啦! laughing

问题所在

问题已经描述过了,比如之前我在自己的博客页面添加了一个日历云小插件,然后高兴地使用 hexo g 命令重新生成所有文章,接下来一顿崩溃:

  1. 我的文章比较多,网络不给力,上传所有文件到服务器非常耗时
  2. 直接覆盖全部文件会遇到断线重连的情况,导致服务器上某些文件“半途而废”
  3. 图片多而且不会发生变化,不需要把图片上传覆盖到服务器
  4. 如果选择手动提取 HTML 文件则非常耗时,因为文件夹“很有深度”

文件夹深度

有点啰嗦,虽然我使用的 WinSCP 有选择覆盖“最新的文件”的功能,但是并没有什么卵用,我也没有在 Hexo 插件中找到相关解决方案的插件,所以只能自己动手了。

文件覆盖方式

解决思路

思路非常简单:只要把需要更新的类型的文件提取出来到一个临时文件夹,同时保持和源文件的文件夹结构相同,那么上传的时候只需要一次性覆盖最顶层文件夹就可以了!

一般来说,需要重新上传覆盖的文件都很小,是一些数据文件,比如: hmtl/json/xml/js 等。

所有代码

代码就不用说明了,非常简单,完全新手作品,主要使用 Python 的 shutil 模块就可以轻松解决文件提取和复制等问题。

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
import os
import shutil

def searchFile(src_dir, ext_filters, result_list):
if not os.path.exists(src_dir) or not os.path.isdir(src_dir):
print('None exits folder or not a directory at all, for:', src_dir, 'and will be ignored!')
return
for file in os.listdir(src_dir):
file = os.path.join(src_dir, file)
if os.path.isfile(file) and os.path.splitext(file)[1] in ext_filters:
result_list.append(file)
elif os.path.isdir(file):
searchFile(file, ext_filters, result_list)

def getSearchedFiles(src_dir, ext_filters):
results = []
searchFile(src_dir, ext_filters, results)
print('Find %d files in %s directory!' % (len(results), src_dir))
return results

def copySingleFile(src_file, dst_dir):
if not os.path.exists(src_file):
print('No such source file')
return
src_dir = os.path.split(src_file)[0] if os.path.isfile(src_file) else src_file
src_dir = os.path.relpath(src_dir)
dst_dir = os.path.join(dst_dir, src_dir)
dst_dir = dst_dir.replace('..\\', '') # for test!
if not os.path.exists(dst_dir):
os.makedirs(dst_dir)
shutil.copy2(src_file, dst_dir)

def createGeneratedFolder():
current_path = os.path.abspath('.')
# 临时文件夹,自行修改吧
generate_path = os.path.join(current_path, 'temp')
generate_path = os.path.join(generate_path, 'generated')
if os.path.exists(generate_path):
os.removedirs(generate_path)
os.makedirs(generate_path)
return generate_path

# 修改这里为你的文件夹路径
def getInputWorkDirectories():
dirs = [] # 你的文件夹路径,绝对路径,可以不写
use_default = input('Use default directories?(y/n):')
if use_default not in ['n', 'no', 'NO', 'N']:
return dirs
path = input('Input the work directory(0 char to stop):')
dirs = [path]
while len(path) > 1:
path = input('Input the work directory(0 char to stop):')
dirs.append(path)
return dirs

def startWork():
gene = createGeneratedFolder()
dirs = getInputWorkDirectories()
if len(dirs) == 0:
return
extensions = getInputExtensions() # 方法已省略,返回扩展名数组
for d in dirs:
files = getSearchedFiles(d, extensions)
for f in files:
copySingleFile(f, gene)

if __name__ == '__main__':
print('Start working......')
startWork()
print('Done!')

注:省略了一点点代码,可以直接到这里下载我写好的文件: copy_html.py ,最后代码中修改您的博客文件路径即可!

在绝对路径和相对路径上,我写的还有点问题,还请大家多多包涵与指正,谢谢! grin

三、总结

代码太简单了,不过还算解决了我的一个小小烦恼。当然,你完全可以使用其他语言实现,比如 Kotlin/C#/JavaScript 等等,在这里我再次感受到了 Python 的简洁与方便。嘿嘿。

如果有大神看到了这篇文章,希望能打造一个 Hexo 内部功能或者插件,类似用于重新生成指定文件类型的命令,就像: hexo rebuild -html,json,xml 。(嗯,这个命令是我乱写的,别被忽悠!)

谢谢大家的观赏,欢迎留言交流! laughing

我的博客地址: http://liuqingwen.me ,欢迎关注我的微信公众号:
IT自学不成才


Comments: