一、动机
针对网上下载到的pdf书籍,很多都是没有书签目录的,给读者看起来很不方便,下面就有了这个半自动生成书签目录的方法。
本文的主要思路来源于Ghoset 博主的《批量给pdf添加目录(最完整详细方法)》,主要是把其中对目录手动格式化的一步进行了自动化,写成了代码,打包成了工具,算是一个补充。
二、利用正则将目录格式化简析
2.1 参考正则表达式模式
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾 |
a| b | 匹配a或b |
(re) | 匹配括号内的表达式,也表示一个组 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f]. |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9]. |
\D | 匹配任意非数字 |
\1...\9 | 匹配第n个分组的内容。 |
2.2 目录正则替换简析
2.2.1 待格式化目录(上)、格式化后目录(中)、格式效果实现(下)
格式化前:
"第一部分标 题 9"
" 第1章标题10"
"1.1标题 11"
"1.1.1标 题 12"
格式化后:
"第一部分 标 题 9"
" 第1章 标题 10"
" 1.1 标题 11"
" 1.1.1 标 题 12"
格式效果:
#1.一级目录实现:
# '第一部分'与'标题'之间一个空格;
# (行头匹配):匹配模式:^(第(\d|\D)+部分)' --> 替换模式:'\1 '
# 注:'\1'的使用需要匹配模式中用()分组,否则无效
# '\1 '后有一个空格
#2.二级目录实现:
# '第1章'之前一个制表符'\t';'第1章'与'标题'之间一个空格;
# 首先得去除'第一章'前空格;
# 后(行头匹配):匹配模式:'^(第(\d|\D)+章)' --> 替换模式:'\t\1 '
#3.三级目录实现:
# '1.1'之前两个制表符'\t\t';'1.1'与'标题'之间一个空格;
# (行头匹配):匹配模式:'^(\d+\.\d+)' --> 替换模式:'\t\t\1 '
#4.四级目录实现:
# '1.1.1'之前三个制表符'\t\t\t';'1.1.1'与'标题'之间一个空格;
# (行头匹配):匹配模式:'^(\d+\.\d+\.\d+)' --> 替换模式:'\t\t\t\1 '
#5.页码实现:
# '标题'与页码'10'之间一个制表符'\t';
# (行尾匹配):匹配模式:'(\d+)$' --> 替换模式:'\t\1'
注:1.标题中的空格保留不动,不可随空格去除操作一起去除;
2.标题中最后一个字符若为数字,会被程序当成是页码,这个暂时没有解决,需手动修改。
三、代码实现
3.1 代码目录结构
其中,主函数在“CatalogFormat.py”文件中;
“catalog.txt”文件为存放的待格式化目录;
“catalog_result.txt”文件为存放的格式化后的结果文件。
3.2 代码实现语言:Python2.7
代码程序支持到三级目录,可包含章节之上的'部分'分类目录,用0|1区别
若hasModule == 1 则将“第一部分 标题 9”作为一级目录;
若hasModule == 0 则将“第一部分 标题 9”与“第一章 标题 10”同时作为一级目录
# -*- coding:UTF-8 -*-
# 此文件名:CatalogFormat.py
import re
#正则替换关联类
class Pattern_Replace_Link:
regPattern = ''
regReplace = ''
def __init__(self, regPattern, regReplace):
self.regPattern = regPattern
self.regReplace = regReplace
#目录格式化Pdf
def CatalogFormat4Pdf(hasModule=0):
# hasModule 表示是否包含‘第...部分’的目录层级,默认 0:不包含 | 1:包含
#正则操作字典
regex_opt_dicts = {
# 将空白字符'\s',或者网络文本空白' ',转成单个空格' '
'repSpace' : Pattern_Replace_Link(r'(\s+| +)', r' '),
# 将可能存在的多个空格,转成单个空格' '
'oneSpace' : Pattern_Replace_Link(r'( +)', r' '),
# 模块目录序号前顶格,后加一个空格' '
'moduleSeq' : Pattern_Replace_Link(r'^(第(\d|\D)+部分)',r'\1 '),
# 一级目录序号前一个制表符'\t',后加一个空格' '
'firstSeq' : Pattern_Replace_Link(r'^(第(\d|\D)+章)', r'\t\1 ' if(hasModule == 1) else r'\1 '),
# 二级目录序号前两个制表符'\t',后加一个空格' '
'secondSeq' : Pattern_Replace_Link(r'^(\d+\.\d+)', r'\t\t\1 ' if(hasModule == 1) else r'\t\1 '),
# 三级目录序号前三个制表符'\t',后加一个空格' '
'thirdSeq' : Pattern_Replace_Link(r'^(\d+\.\d+\.\d+)', r'\t\t\t\1 ' if(hasModule == 1) else r'\t\t\1 '),
# 页码前一个制表符'\t'
'pageSeq' : Pattern_Replace_Link(r'(\d+)$', r'\t\1')
}
obj_file = open('catalog.txt', mode='r')
result_file = open('catalog_result.txt', mode='w')
for line in obj_file.readlines():
# 将网络空白文本及普通空白'\s',替换为单个空格' '
link = regex_opt_dicts['repSpace']
line = re.sub(link.regPattern, link.regReplace, line)
# 去除左右(前后)空格
#注:strip()去除不了网络空格文本' '
line = line.strip()
# 模块中文目录匹配
link = regex_opt_dicts['moduleSeq']
line = re.sub(link.regPattern, link.regReplace, line)
# 第一级中文目录匹配
link = regex_opt_dicts['firstSeq']
line = re.sub(link.regPattern, link.regReplace, line)
# 二、三级数字目录匹配
# 数字序号由最下层开始匹配
# 如:1.2 和 1.2.1 中,先从头匹配 1.2.1
# 因匹配是从头开始往后匹配的,所以匹配完一次,第二次将匹配不成功(开头多了'\t')
link = regex_opt_dicts['thirdSeq']
line = re.sub(link.regPattern, link.regReplace, line)
link = regex_opt_dicts['secondSeq']
line = re.sub(link.regPattern, link.regReplace, line)
# 每层目录页号匹配
link = regex_opt_dicts['pageSeq']
line = re.sub(link.regPattern, link.regReplace, line)
# 将可能存在的多个空格,转成单个空格' '
link = regex_opt_dicts['oneSpace']
line = re.sub(link.regPattern, link.regReplace, line)
#追加换行符
line += '\n'
#写入结果文件
result_file.write(line)
#关闭文件
obj_file.close()
result_file.close()
# 函数入口
if __name__ == '__main__':
print("*******************--******--*************************\n"\
"*************--********--*******--********************\n"
"Ensure the file catalog.txt under the current directory.")
print("Then enter 0 or 1 to choose if it has Module (like \' " + unicode('章节之上还分 第一部分','utf-8') + "\')\n"\
+ "1:yes; 0:no\n")
hasModule = input()
while hasModule != 0 and hasModule != 1:
print("Please enter 0 or 1:\n")
hasModule = input()
print("You choose " + str(hasModule) + "\n")
print("Catalog Format Begin.....")
CatalogFormat4Pdf(hasModule)
print("Catalog Format Over.....")
四、生成CatalogFormat.exe可执行文件
生成如下目录结构:(不需要Python环境,可在Windows下直接运行)
--CatalogFormat4PDF
----build
------CatalogFormat
--------Analysis-00.toc
--------CatalogFormat.exe.manifest
--------EXE-00.toc
--------PKG-00.pkg
--------PKG-00.toc
--------PYZ-00.pyz
--------PYZ-00.toc
--------warn-CatalogFormat.txt
--------xref-CatalogFormat.html
----dist
------catalog.txt --> 待格式化目录
------catalog_result.txt --> 目录格式化结果
------CatalogFormat.exe --> 可执行程序(Windows下)
----CatalogFormat.spec
程序窗口:
首先需保证 CatalogFormat.exe同目录下的catalog.txt文件中已经放入了你的目录
(注:目录可从网上查找,最好是带页码的,如果没有只能手动添加)
(目录可从“百科”、“当当”、“天猫”等书籍资料处搜索)
然后按控制台提示,如下操作:
1.如果是这种目录结构,输入"1",回车:
"第一部分 标 题 9"
" 第1章 标题 10"
" 1.1 标题 11"
" 1.1.1 标 题 12"
2.如果是这种目录结构,输入"0",回车:
"第1章 标题 10"
" 1.1 标题 11"
" 1.1.1 标 题 12"
格式化结果在catalog_result.txt文件中。
可执行程序下载地址
链接:https://pan.baidu.com/s/14fFRL0siT7YMs1qAOTgBaw
提取码:6ojk