我算是一个资源收集*者,尤其是特别喜欢收集自己觉得好的电子书,多半都是epub格式,因为觉得这种格式既美观又方便,比pdf之类的好多了。
有些上传到网盘的电子书,为了避免因为侵权被删除,文件名都被上传者做了拼音化处理,这样下载下来后我们自己查看的时候,就不太方便,无法通过文件名直观的看出这本书的名字,为了解决这个问题,就需要对电子书进行重命名。
如果要处理的电子书比较少,只有两三本,那自己手工来改就行,可如果像我一样,手中有三千本电子书,其中的几百本都需要改名,那手工改的效率就太低了,这个时候,就该使用脚本来帮助我们完成了。
思路
关于如何将拼音改成汉字名称这件事,一开始我并没有太好的方法,毕竟我虽然可以通过目测推断出这本书的书名,但是我不想亲自动手啊,这种重复劳动的工作,当然是交给脚本来完成呀。
可是脚本不如我聪明,它怎么能知道这一行拼音,对应的是哪一个汉字书名呢?
我甚至想到过,先去豆瓣将所有能找到的书籍名字都爬取一遍,然后将这些名字转换成拼音,再去跟我的拼音化的电子书名相比较,超过一定相似度的,我们就认为他们是同一本书,再将其改名成相应的名字。
这个方法想想就不是什么简单的事情,简直是杀鸡用牛刀的典范,也因为爬取豆瓣所有的书名实在不是一件简单的事情,我光想想就快放弃了,根本没有行动的打算。
后来恍然间发现,在电子书阅读器上,哪怕是已经拼音化的书名,仍然能显示出正常的书名,这是怎么回事呢?
仔细一想,一定是因为epub这种格式里,包含了一定的书籍信息,比如书名,作者,出版社等信息,那么,只要用从epub中读取的书名,重命名给拼音化的书名,不就能完成我的任务了吗。
这种方法既简单,效果又好,而且想想就知道不会太难,是解决这件事情的最好方法,我又有了行动的动力,那就开始干吧。
行动
最方便的脚本语言当然就是python了,我先搜一搜python中有没有专门处理epub的包,不出所料,果然有,名字叫ebooklib。
网上关于这个库的信息比较少,中文资料也只有寥寥几条,好在这个库足够简单,看一下别人的经验,自己再摸索摸索,足够我们解决问题了。
python真的简单,我正在学,虽然没有系统的学过,但是已经可以实现我的小想法了,下面就开始写代码吧。
import os
from ebooklib import epub
# 电子书所在路径
bookpath = \'c:\\users\\vihv\\books\\\'
renum = norenum = errornum = 0
# 设置为当前路径
os.chdir(bookpath)
# 读取所有电子书名
allbooks = os.listdir(bookpath)
for bookname in allbooks:
# 判断是不是epub格式
nametext, isepub = os.path.splitext(bookpath+bookname)
if isepub == \'.epub\':
try:
print(\'原书名是:\', bookname, \'\n\')
book = epub.read_epub(bookpath+bookname)
newbookname = book.get_metadata(\'DC\', \'title\')[0][0]+\'.epub\'
print(\'新书名是:\', newbookname, \'\n\')
if bookname != newbookname:
os.rename(bookname, newbookname)
print(\'改名成功了O(∩_∩)O哈哈~\')
renum += 1
else:
print(\'这本书不需要改名\')
norenum += 1
except:
print(\'这里出错了,怎么回事我也不知道::>_<::\')
errornum += 1
print(f\'任务成功结束,改名{renum}本,{errornum}本出现错误,{norenum}本不需要改名。\')
运行两遍之后,脚本的运行结果是:
真棒,30行代码就完成了全部的工作,虽然有一些未知原因的错误,使得脚本并非十全十美,这可能是因为电子书在制作期间,就没有完全遵循正确的格式,所以我们的脚本也处理不好。但是已经很棒了,生活嘛,总要允许一点不完美的存在。
接下来我们看一下这短短的30行代码分别做了什么。温故知新,作为总结。
import os
from ebooklib import epub
这两行就是导入包嘛,os包是python和系统交互的包,我们需要这个包来和我们的系统打交道,让系统告诉我们,我们存在电子书的路径下,都有哪些电子书,他们的书名分别是什么。
ebooklib包是我们自己安装的,用来处理epub文件的包,我们从这个包里,导入epub对象。
如果你没有这个包的话,要提前使用pip来安装,安装的方法是:
pip install ebooklib
接下来是设置一些变量,代码是这样的:
# 电子书所在路径
bookpath = \'c:\\users\\vihv\\books\\\'
renum = norenum = errornum = 0
# 设置为当前路径
os.chdir(bookpath)
bookpath是存放电子书的路径,可以看到,我的电子书存放在我的用户目录vihv的books文件夹下,为什么是两条\'\\\'呢,因为在python和很多编程语言下,\都是作为转义字符存在的, 比如\n作为换行等等,这个时候\就不是\了。所以如果要表示\ ,就要用两条\\。
如果你要照抄我的代码的话,就需要将这个路径换成你自己的存放电子书的路径。
然后我设置了三个全局变量,全都是0,我英文不好,这三个变量的名字十分丑陋,将就着看吧O(∩_∩)O~。
renum是rename_num的缩写,表示已经重命名的文件的数量,前边加个no就是norenum,表示不需要改名的文件的数量,errornum自然就是出现未知错误的文件的数量。
然后使用os包里的chdir方法,进入到我的电子书的路径,就相当于命令行里的cd命令。
# 读取所有电子书名
allbooks = os.listdir(bookpath)
然后我们调用os包里的 listdir 方法,这个方法以一条路径作为参数,返回一个列表,列表里是所有的文件的名字。
可以看到,我们将读取到的列表,放入了 allbooks 变量里。
python创建变量不需要提前声明,想什么时候创建都可以,这太方便了,我爱动态语言。
接下来是一个 for ... in ... 的循环,python的的 for 循环和 c 、js 等语言不同,它更加的方便,只需要一个 for ... in ... ,就会自动遍历列表里的所有内容,省去了自己计数的麻烦。
for bookname in allbooks:
# 判断是不是epub格式
nametext, isepub = os.path.splitext(bookpath+bookname)
可以看到,使用 for ... in ... 之后,我们就创建了一个变量 bookname ,其中就已经存放了一个书名,这个书名包含了后缀名,格式是这样的:“自学是一门手艺.epub” 。
然后我们调用os包的路径切割方法os.path.splitext,将书名的名字和后缀名分割开。它会接收一个文件路径作为参数,返回两个值,第一个值是文件名,第二个值是后缀名,其中后缀名是包含了“点”的,比如\'.epub\'。
然后根据这个后缀名,我们就可以做出判断了,如果这个后缀名等于\'.epub\',我们就知道它是一个epub格式,反之,它就不是一个epub格式。
因为我的文件夹里也有很多pdf,mobi之类格式的电子书,并不都是epub,这些文件暂时我不想处理,所以做这样的筛选是有必要的。
接下来的一段,逻辑其实很简单,就是判断这本书是不是epub格式的,如果不是,就不管它。
如果是,就看看它现在是什么名字,然后读取epub里的书名,两相对比,看看他们是不是一样的,如果是一样的,我们就不用改了,不用进行重命名这个操作,这样程序执行比较快,也会比较节省系统资源。
毕竟我们的脚本可能不会只运行一次,以后有新书加进来的时候,我们可能还会执行一次脚本,那时候很多书的名字其实已经改好了,如果再改一次的话,就多此一举了,对吧。
如果两相对比不一样,我们就用epub里的书名对它进行重命名。
if isepub == \'.epub\':
try:
print(\'原书名是:\', bookname, \'\n\')
book = epub.read_epub(bookpath+bookname)
newbookname = book.get_metadata(\'DC\', \'title\')[0][0]+\'.epub\'
print(\'新书名是:\', newbookname, \'\n\')
if bookname != newbookname:
os.rename(bookname, newbookname)
print(\'改名成功了O(∩_∩)O哈哈~\')
renum += 1
else:
print(\'这本书不需要改名\')
norenum += 1
except:
print(\'这里出错了,怎么回事我也不知道::>_<::\')
errornum += 1
可以看到,重命名的时候,使用的是os包的rename方法,这个方法接收两个参数,第一个是原名,第二个是要修改成的名字,也是十分简单啦。
这里要注意的是epub包的方法,我们使用epub包的read_epub方法,从名字上就可以看出来,这个方法就是读取epub嘛,它接收一个文件路径作为参数,返回一个epub对象。
这里我们使用book这个变量,接收了它返回的对象。
’DC‘代表什么意思呢?网上搜到的信息如下:
到这里我们就已经读取到了epub里的书名,要注意的是,get_metadata返回的是一个包含在数组里的元组,元组里包含的才是字符串,所以我在它后面加了两个
别忘了后缀名哦,在后面加上\'.epub\'。
然后再简单的进行比较操作之后,我们的逻辑判断部分就已经完成了,需要注意的是,这里我使用了 try ... except ... 语句,这条语句是专门用来处理异常的。
因为脚本总会因为各种意向不到的原因导致意外退出,比如一本书的格式不对劲,脚本就可能执行不下去,导致我们的任务并不能全部完成,这时候加上这条语句,脚本的健壮性就会提升不少,哪怕有一百多本书格式不对,我们的脚本依然正常运行。
接下来是最后一条语句,就是统计信息啦,有了这条语句,我们对脚本做了什么,经历了多少异常,就了然于胸了。
print(f\'任务成功结束,改名{renum}本,{errornum}本出现错误,{norenum}本不需要改名。\')
结语