1 Star 0 Fork 0

iam002 / PDFDirGenerator2

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

PDF Dir Generator

PDF Dir(ectory) Generator,PDF 目录生成器, 是基于 wxpython 和 PyPDF2 开发的一个简易的 GUI 程序,主要功能是给未添加书签的 PDF 添加目录书签。


安装必要的模块

首先必须保证 Python 运行版本不低于 3.7, 推荐使用的 Python 版本为 3.9.12.

运行本程序需要使用两个模块: PyPDF2wxpython, 我们可以通过 pip 进行安装. 如果你不需要 GUI 界面,可以只安装 PyPDF2.

pip install PyPDF2
pip install wxPython

安装完 PyPDF2 需要对 _writer.pyget_outline_roor() 函数进行修改, 不然运行时可能会如下报错:

File "C:\Users\q2799\.conda\envs\py36\lib\site-packages\PyPDF2\_writer.py", line 1195, in addBookmark
    title, pagenum, parent, color, bold, italic, fit, *args
  File "C:\Users\q2799\.conda\envs\py36\lib\site-packages\PyPDF2\_writer.py", line 1174, in add_bookmark
    parent = self.get_outline_root()
  File "C:\Users\q2799\.conda\envs\py36\lib\site-packages\PyPDF2\_writer.py", line 1008, in get_outline_root
    idnum = self._objects.index(outline) + 1
ValueError: {'/Type': '/Outlines', '/First': IndirectObject(1006, 0, 3019818315728), '/Count': 493, '/Last': IndirectObject(1498, 0, 3019818315728)} is not in list

根据报错信息,找到 _writer.pyget_outline_roor() 的位置(不同版本的 PyPDF2 可能的位置不一样),修改如下:

def get_outline_root(self) -> TreeObject:
    if CO.OUTLINES in self._root_object:
        # TABLE 3.25 Entries in the catalog dictionary
        outline = cast(TreeObject, self._root_object[CO.OUTLINES])
        try:
            idnum = self._objects.index(outline) + 1
        except ValueError:
            if not isinstance(outline, TreeObject):
                def _walk(node):
                    node.__class__  = TreeObject
                    for child in node.children():
                        _walk(child)
                _walk(outline)
            outline_ref = self._add_object(outline)
            self._add_object(outline_ref.get_object())
            self._root_object[NameObject('/Outlines')] = outline_ref       
            idnum = self._objects.index(outline) + 1    
        outline_ref = IndirectObject(idnum, 0, self)
        assert outline_ref.get_object() == outline
    else:
        outline = TreeObject()
        outline.update({})
        outline_ref = self._add_object(outline)
        self._root_object[NameObject(CO.OUTLINES)] = outline_ref

    return outline

运行前的准备

运行之前,推荐先阅读这篇博客, 在运行之前我们需要准备好:

  1. 待添加书签的 PDF
  2. 包含书签目录信息的 txt
  3. 目录页的偏移页数 Offset(一般是目录页的最后一页的页码)

运行命令行

  1. 格式化目录

    python .\dirFormat.py <dir_input_path> [<-option> <params>]
    参数 选项 说明
    DIR_INPUT_PATH 必需参数 目录文件的路径
    DIR_FORMAT_PATH -o 格式化目录的输出文件夹
    DIR_LOG_PATH -l 格式化目录文件的输出日志存放文件夹
    DELIMITER -d 单词分隔符
    PREFIX -p 目录文件每行的前缀
    PRE_LEVEL -pl 预定义级别
    PRE_TITLE -pt 预定义标题, 使用 ; 隔开

    例子

    python .\dirFormator.py test/test_dir.txt -pl 2 -pt 参考文献

    输出结果:

    ---------------------------- Format Dir -----------------------------------
    运行时间: 2022-10-05 15:45:33
    目录源文件路径: test/test_dir.txt
    格式化目录路径:
    日志路径:
    单词分隔符:
    级别标志符: .
    前缀:
    预定义级别: 2
    预定义标题: 参考文献
    ---------------------------------------------------------------------------
    [Line  29] 缩略语对照表 395 ==> 无法判断级别信息
    [Line  30] 符号表       398 ==> 无法判断级别信息
    [Line  31] 参考书目     401 ==> 无法判断级别信息
    [Line  32] 索引 415 ==> 无法判断级别信息
    ---------------------------------------------------------------------------
    Dir-log Path    : test/test_dir.log
    Dir format Path : test/test_dir_format.txt
    ---------------------------------- Done! ----------------------------------
  2. 修改目录

    格式程序的同时会进行简单的检查,并输出日志信息. 可以根据这些信息对格式化后的目录进一步的修改.

  3. 生成目录

    修改完后的目录文件,作为这一步的输入目录文件;同时需要删除待添加书签的 PDF 原先的书签。 然后执行指令:

    python .\pdfDirGenerator.py <dir_input_path> <pdf_input_path> [<-option> <params>]
    参数 选项 说明
    DIR_INPUT_PATH 必需参数 目录文件的路径
    PDF_INPUT_PATH 必须参数 待添加书签的PDF路径
    PDF_OUTPUT_PATH -o PDF输出目录
    DELIMITER -d 单词分隔符
    PREFIX -p 目录文件每行的前缀
    OFFSET -O 页码偏移量

    例子

     python .\pdfDirGenerator.py test\format\pdg_normal_dir.txt test\pdg_test.pdf -O 5

    输出结果:

    --------------------------- Adding the bookmark ---------------------------
    PDF input path: test\pdg_test.pdf
    PDF output path:
    Dir path: test\format\pdg_normal_dir.txt
    Offset: 5
    Prefix:
    Delimiter:
    ---------------------------------------------------------------------------
    [  1/ 23 finished] level: 0, title: 第1章 计算机网络概论, page: 6
    [  2/ 23 finished] level: 1, title: 1.1 计算机网络的形成与发展, page: 6
    [  3/ 23 finished] level: 2, title: 1.1.1 分组交换技术的研究, page: 6
    [  4/ 23 finished] level: 2, title: 1.1.2 互联网的形成, page: 9
    [  5/ 23 finished] level: 2, title: 1.1.3 互联网的高速发展, page: 13
    [  6/ 23 finished] level: 2, title: 1.1.4 移动互联网的发展 , page: 14
    [  7/ 23 finished] level: 1, title: 1.2 计算机网络定义与分类, page: 17
    [  8/ 23 finished] level: 1, title: 1.3 各种类型网络 y 的特点, page: 20
    [  9/ 23 finished] level: 2, title: 1.3.1 广域网, page: 20
    [ 10/ 23 finished] level: 2, title: 1.3.2 城域网, page: 23
    [ 11/ 23 finished] level: 2, title: 1.3.3 局域网, page: 25
    [ 12/ 23 finished] level: 0, title: 小结, page: 26
    [ 13/ 23 finished] level: 1, title: 习题, page: 26
    [ 14/ 23 finished] level: 0, title: 第2章 物理层, page: 27
    [ 18/ 23 finished] level: 1, title: 2.2 数据通信 x 的基本概念 , page: 31
    [ 19/ 23 finished] level: 2, title: 2.2.1 测试, page: 32
    [ 20/ 23 finished] level: 3, title: 2.2.1.1 测试, page: 33
    [ 21/ 23 finished] level: 0, title: 小结, page: 34
    [ 22/ 23 finished] level: 1, title: 习题, page: 34
    [ 23/ 23 finished] level: 0, title: 附录, page: 35
    ---------------------------------------------------------------------------
    Save: test\pdg_test(书签).pdf
    ---------------------------------- Done! ----------------------------------  

运行 GUI 界面

运行 main.py 启动 GUI 界面

python .\main.py

演示

主界面

参数设置

参数说明

  • Offset 页码偏移量,书签对应的页数 = 目录文件的page + offset, 一般这个值等于目录页最后一页所在的页码;
  • Prefix 目录文件每行的前缀, 生成书签时用于判断书签的级别
  • DELIMITER 单词分隔符, 通常是空格, 不建议修改
  • LEVEL_MARKER 级别标志符, 格式化书签时用于判断书签的级别
  • Pre-level 预定义级别
  • Pre-title 预定义标题, 注意使用“;”隔开,不要有多余的空格
  • PDF Output Path PDF输出目录, 留空会根据输入PDF名自动生成
  • Dir-Log Path 格式化目录文件的输出日志存放文件夹目录,留空则与原目录在同一文件夹
  • Dir-format Path 格式化目录的输出文件夹,留空则与原目录在同一文件夹

这里通常需要设置的是 Offset 以及 Pre-title,设置完成后记得点击 Finish

除了这种设置方式外,还支持直接导入配置文件(文件后缀名为 .conf):

配置文件

###########################################################################
#
# 这是一个配置文件, 以行为基本单元, 可以分为注释行, 赋值行和空行.
# 
# 注释行以字符 '#' 开头, 程序会忽略以'#'开头的行; 行首直接回车,则是空行; 注释行
# 和空行可以提高配置文件的可读性.
#
# 赋值行的格式为: 字段名 = 值:
# 1. "值"可以修改, 但不要修改"字段名";
# 2. "="两边的空格可有可无, 数量没有限制;
# 
###########################################################################

# str, 待添加书签的PDF路径
PDF_INPUT_PATH = "C:\Users\q2799\Project\PDFDirGenerator2\test\pdg_test.pdf"

# str, 目录文件的路径
DIR_INPUT_PATH = "C:\Users\q2799\Project\PDFDirGenerator2\test\pdg_normal_dir.txt"

# int, 页码偏移量, 通常是PDF目录页最后一页的页码
OFFSET = 5

# char, 目录文件每行的前缀, 生成书签时用于判断书签的级别
PREFIX = "\t"

# char, 单词分隔符, 通常是空格, 不建议修改
DELIMITER = " "

# char, 级别标志符, 格式化书签时用于判断书签的级别
LEVEL_MARKER = "."

# int, 预定义级别
PRE_LEVEL = 2

# str, 预定义标题, 使用';'隔开
PRE_TITLE = "本章小结;习题"

# str, 格式化目录文件的输出日志存放文件夹,留空则与原目录在同一文件夹
DIR_LOG_PATH = "C:\Users\q2799\Project\PDFDirGenerator2\test\log"

# str, 格式化目录的输出文件夹,留空则与原目录在同一文件夹
DIR_FORMAT_PATH = "C:\Users\q2799\Project\PDFDirGenerator2\test\format"

# PDF输出目录, 留空会根据输入PDF名自动生成
PDF_OUTPUT_PATH = "C:\Users\q2799\Project\PDFDirGenerator2\test\outpdf"

# int, 是否只显示目录日志
IS_PRINT_ACTICE_ONLY = 0

# int, 生成日志前默认先进行格式化
IS_FORMAT_DIR_FIRST = 1

# int, 是否打印生成书签过程中的信息
IS_PRINT_PROCESS = 1

工程目录说明

  • dirFormator.py 格式化目录脚本
  • pdfDirGenerator PDF 目录生成脚本
  • main.py GUI 运行脚本
  • utils.py 存放一些公共函数和全局变量
  • wxb_*.py 通过 wxFormBuilder 自动生成的脚本(用于图像界面的设计)
    • mainFrame.py 主窗口
    • runningDialog.py 运行弹窗
    • settingsDialog.py 设置弹窗
    • aboutDialog 关于弹窗
  • assets\ 存放一些图片等附件
  • design_gui\ 存放 wxFormBuilder 工程文件,可用 wxFormBuilder 打开
  • test\ 存放一些测试数据
    • conf\ 包含一个配置文件 pdg_settings.conf
    • format\ 包含一个格式化目录 pdg_normal_dir.txt
    • log\ 包含格式化目录的日志信息 pdg_normal_dir.log
    • outpdf\ 存放运行结果 pdg_test(书签).pdf
    • pdg_test.pdf 测试 PDF
    • *_dir.txt 测试目录文件
PDFDirGenerator2
├─ aboutDialog.py
├─ assets
├─ blog.md
├─ design_gui
│  ├─ noname.cpp
│  ├─ noname.h
│  └─ pdg2.fbp
├─ dirFormator.py
├─ main.py
├─ mainFrame.py
├─ pdfDirGenerator.py
├─ README.md
├─ runningDialog.py
├─ settingsDialog.py
├─ test
│  ├─ conf
│  │  └─ pdg_settings.conf
│  ├─ format
│  │  └─ pdg_normal_dir.txt
│  ├─ log
│  │  └─ pdg_normal_dir.log
│  ├─ outpdf
│  │  └─ pdg_test(书签).pdf
│  ├─ pdg_invalidnum_dir.txt
│  ├─ pdg_normal_dir.txt
│  ├─ pdg_test.pdf
│  └─ test_dir.txt
├─ utils.py
├─ wxb_mainFrame.py
├─ wxb_runningDialog.py
└─ wxb_settingsDialog.py
 
MIT License Copyright (c) 2022 iam002 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

基于 wxpython 和 PyPDF2 开发的一个简易的 GUI 程序 , 主要功能是给未添加书签的 PDF 添加目录书签。 展开 收起
Python 等 3 种语言
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Python
1
https://gitee.com/iam002/pdfdir-generator2.git
git@gitee.com:iam002/pdfdir-generator2.git
iam002
pdfdir-generator2
PDFDirGenerator2
master

搜索帮助