最近在学习python,找了一本epub的电子书,但是打开之后发现,是一本扫描版的,一页一张图片的epub,看着很不舒服,扫描版的还是应该做成pdf,所以就研究了一下怎么手动把epub转成pdf。
认识epub
ePub(Electronic Publication的缩写,意为:电子出版),是一个自由的开放标准,属于一种可以“自动重新编排”的内容;也就是文字内容可以根据阅读设备的特性,以最适于阅读的方式显示。EPub档案内部使用了XHTML或DTBook (一种由DAISY Consortium提出的XML标准)来展现文字、并以zip压缩格式来包裹档案内容。(复制自百度百科)
通过上面我们可以知道,通过文件管理器或者解压工具可以打开epub格式的电子书,OEBPS/
目录内就是电子书的内容,我们主要关心的就是text00000.html
以及一堆乱序的图片。
首先打开text00000.html
,打开之后可以在浏览器内看电子书,但是我们的目的不是这个,用文本编辑器打开应该能看见类似这样的代码
1 | ... |
span
标签的作用是作为目录的标记,img
标签是按照顺序排列的图片,如果是常规的epub电子书,p
标签内应该有书里面的文本。
主要流程
如果是我以前,我的流程应该是
- 手动把epub拆包
- 手动用vscode对html正则替换,只保留图片名
- 写个bash脚本把图片按html的顺序批量重命名
- 用imagemagick把图片合并成pdf。
但是现在在学python,而且通过大量的网络查资料,我觉得这些操作全部都可以用python自动化完成(库多就是好),所以我就写了这篇博客来记录,如何用python来将扫描版epub转换成pdf,顺便二值化处理(以前就想弄了,但是用C语言不会读取图片,读取图片我只会手搓bmp)。
需要用到的库有:
- zipfile 用于读取epub文件
- re 用于正则提取图片名
- PIL 用于将图片序列保存为pdf,以及图片二值化,非自带需要通过
pip install pillow
安装
zip操作
这里只介绍需要用到的操作,更多的可以自己去网上查。
首先在开头导入库from zipfile import ZipFile
,注意,我这里是只导入了ZipFile,用来打开zip文件,如果规范一点,在用ZipFile打开文件之前,应该用zipfile.is_zipfile(filename)
来判断是不是zip文件,我这里偷懒了。
打开zip
ZipFile的用法跟打开普通文件的方法类似,使用的时候注意大小写。
1 | #两种写法 |
打开之后可以使用ZipFile的两个方法,namelist
获取压缩包内的文件名列表,infolist
获取文件信息列表。
打开zip内的文件
ZipFile也有一个方法叫做open,用法跟普通的open类似。
1 | with ZipFile(epub_name) as epub_file: |
之后就可以像操作普通文件一样操作zip里的文件了。
正则表达式
正则表达式是一个很好用的东西,简单的很简单,复杂的基本上都不记得要去网上查,python里面使用正则表达式是通过re这个库,使用起来还是很简单的。
通过观察,我们需要提取的就是img
标签内的src
的值,所以我写的正则表达式是<img.*src=\"(.+)\" />
,用来提取img的src的双引号内的文件名。
python内使用正则表达式首先需要编译
1 | import re |
之后就可以通过pattern的findall
方法来提取字符串了。
1 | with ZipFile(epub_name) as epub_file: |
这样就将图片名按顺序保存到file_list
里了。
二值化处理
二值化就是让图片只保留两种颜色,可以让扫描版的图片更加清晰,同时还能缩小图片体积(从32位色彩变成了1位色彩)。
首先,封面我们还是留着颜色,这样好看点,我们就假定第一张图片就是封面,先将第一张图片从列表里拆出来。
1 | file_0,*file_list=file_list |
现在file_list
里的就是我们需要二值化的图片了,二值化的步骤就是把图片转化成灰度图,之后设定一个阈值,小于这个值的就是纯黑,大于这个值的就是纯白,先上代码:
1 | threshold=200 |
convert('L')
是将图片转换成灰度图,也可以转换成其他颜色模式,有需要自行查找。
point
方法就很有意思了,是逐像素映射,感觉可以做很多有意思的事情,第一个参数就是颜色映射,第二个参数是颜色模式,’1’就是只有黑白了。
之后将处理后的图片添加到img_list
里,就是我们pdf的图片序列了。
保存为pdf
不要忘了封面,保存就一行的事,直接上代码了。
1 | with epub_file.open("OEBPS/"+file_0) as file: |
最终完成版
为了使用方便,我还写了个控制台传参,这个看个人喜好,不是重点,不过多说明。注意,因为我这里只有灰度阈值一个参数,所以我只判断了”–”开头,如果有多个参数,建议用字典来保存参数。
1 | from zipfile import ZipFile |
之后可以用pyinstaller把py脚本打包成exe,这样使用就更方便一点,在windows下面直接将epub文件拖到exe文件上就可以使用了。按我自己使用,原本73MB的epub电子书转换之后只有7MB,只有原来的百分之十,而且也清晰了,效果还是很好的。
感想
这次算是我学了python之后的第一次实战,给我的感觉还是很不错的,虽然大多是在调库,但是确实做到了我用C语言很难做到的事情,用C语言我一不会找库,二如果解析zip、jpg、pdf这些我全部学习怎么写,那一定会花很多时间,而且到最后估计也就是在复制代码,所以,人生苦短,我用python。
也挺羡慕现在的小孩,好像听说小学就学python了,如果我小学的时候就学python,现在可能早就实现所有事情自动化了,我是个很懒的人,在学会编程之后,什么都想着能不能让程序做,从解题到用电脑处理文件,虽然很多时候能力受限,都只是停留在想。但是python帮我们解决了很多能力上的问题,我们只要敢想敢做就行了。