使用 Python 给 PDF 添加目录书签

0、库的选择------pypdf

原因:Python Version Support

Python 3.11 3.10 3.9 3.8 3.7 3.6 2.7
pypdf>=3.0 YES YES YES YES YES YES
PyPDF2>=2.0 YES YES YES YES YES YES
PyPDF2 1.20.0 - 1.28.4 YES YES YES YES YES YES
PyPDF2 1.15.0 - 1.20.0 YES

我的版本

Python=3.6.13

pypdf=3.16.2

1、添加书签------方法add_outline_item的使用

python 复制代码
# https://zhuanlan.zhihu.com/p/603340639
import pypdf  #
import sys

wk_in_file_name = 'PythonTutorial.pdf'
input1 = open(wk_in_file_name, "rb")  # 打开需要添加书签的PDF
writer = pypdf.PdfWriter()  # 创建一个PdfWriter类
writer.append(input1)  # 将PDF读入writer中,然后进行书签的编辑

writer.add_outline_item(title='10', page_number=10, parent=None)  # 添加第一个书签
writer.add_outline_item(title='11', page_number=11, parent=None)  # 添加第二个书签

# Write to an output PDF document
output = open('01_' + wk_in_file_name, "wb")  # 如果wk_out_file_name不存在,则创建一个
writer.write(output)  # 将添加书签后的PDF保存

# Close File Descriptors
writer.close()
output.close()

print('pypdf.__version__=', pypdf.__version__)
print('sys.version=', sys.version)

pass

运行结果

2、添加子书签------参数parent的使用

python 复制代码
# https://zhuanlan.zhihu.com/p/603340639
import pypdf

wk_in_file_name = 'PythonTutorial.pdf'
writer = pypdf.PdfWriter()
input1 = open(wk_in_file_name, "rb")
writer.append(input1)

parent_bookmark_0 = writer.add_outline_item(title='10', page_number=10, parent=None)  # 添加第一个书签
writer.add_outline_item(title='10_1', page_number=11, parent=parent_bookmark_0)  # 添加第一个书签的子书签
parent_bookmark_1 = writer.add_outline_item(title='11', page_number=20, parent=None)  # 添加第二个书签
writer.add_outline_item(title='11_1', page_number=21, parent=parent_bookmark_1)  # 添加第二个书签的子书签

# Write to an output PDF document
output = open('02_'+wk_in_file_name, "wb")
writer.write(output)

# Close File Descriptors
writer.close()
output.close()

pass

运行结果

3、读取txt文件

python 复制代码
# https://blog.csdn.net/kobeyu652453/article/details/106876829

f = open('dir.txt', 'r', encoding='utf8')
# f = open('dir.txt', encoding='gbk', errors='ignore'), errors='ignore'
# f = open('dir.txt', encoding='gb18030', errors='ignore')
line1 = f.readline()  # 读取第一行,大文件readline

# https://blog.csdn.net/andyleo0111/article/details/87878784
lines = f.readlines()  # 读取所有行,小文件readlines
num_lines = len(lines)  # 标题的总个数

txt = []
for line in lines:
    txt.append(line.strip())
    print(line.strip())

    line.strip()  # 去掉末尾的'\n'
    line.split(' ')  # 根据line中' '进行分割
    line.count('.')  # 有n个'.'就是n+1级标题

print(txt)
f.close()  # 关闭文件
print('f.closed=', f.closed)

运行结果

python 复制代码
D:\SoftProgram\JetBrains\anaconda3_202303\envs\py3_6_for_TimeSeries\python.exe E:\program\python\gitTemp\pdf\test\03_read_txt.py 
1 课前甜点 3
2 使用Python解释器 5
2.1 调用解释器 5
2.1.1 传入参数 6
2.1.2 交互模式 6
2.2 解释器的运行环境 6
2.2.1 源文件的字符编码 6
3 Python的非正式介绍 9
3.1 Python作为计算器使用 9
3.1.1 数字 9
3.1.2 字符串 11
3.1.3 列表 14
3.2 走向编程的第一步 15
4 其他流程控制工具 17
4.1 if语句 17
4.2 for语句 17
4.3 range()函数 18
4.4 break和continue语句,以及循环中的else子句 19
4.5 pass 语句 20
4.6 定义函数 20
4.7 函数定义的更多形式 22
4.8 小插曲:编码风格 29
['1 课前甜点 3', '2 使用Python解释器 5', '2.1 调用解释器 5', '2.1.1 传入参数 6', '2.1.2 交互模式 6', '2.2 解释器的运行环境 6', '2.2.1 源文件的字符编码 6', '3 Python的非正式介绍 9', '3.1 Python作为计算器使用 9', '3.1.1 数字 9', '3.1.2 字符串 11', '3.1.3 列表 14', '3.2 走向编程的第一步 15', '4 其他流程控制工具 17', '4.1 if语句 17', '4.2 for语句 17', '4.3 range()函数 18', '4.4 break和continue语句,以及循环中的else子句 19', '4.5 pass 语句 20', '4.6 定义函数 20', '4.7 函数定义的更多形式 22', '4.8 小插曲:编码风格 29']
f.closed= True

进程已结束,退出代码0

4、从txt中读取目录与页码并写入PDF的书签

python 复制代码
# https://blog.csdn.net/kobeyu652453/article/details/106876829
import pypdf

wk_in_file_name = 'PythonTutorial.pdf'
writer = pypdf.PdfWriter()
input1 = open(wk_in_file_name, "rb")
writer.append(input1)

f = open('dir.txt', 'r', encoding='utf8')
lines = f.readlines()  # 读取所有行
num_lines = len(lines)  # 标题的总个数

txt = []
for line in lines:
    line = line.strip()  # 去掉末尾的'\n'
    pline = line.split(' ')  # 根据line中' '进行分割
    level = line.count('.')  # 有n个'.'就是n+1级标题

    if level == 0:
        bookmark_parent_0 = writer.add_outline_item(title=pline[0] + pline[1], page_number=int(pline[-1]), parent=None)
    elif level == 1:
        bookmark_parent_1 = writer.add_outline_item(title=pline[0] + pline[1], page_number=int(pline[-1]),
                                                    parent=bookmark_parent_0)
    else:
        writer.add_outline_item(title=pline[0] + pline[1], page_number=int(pline[-1]), parent=bookmark_parent_1)


# Write to an output PDF document
output = open('04_'+wk_in_file_name, "wb")
writer.write(output)

# Close File Descriptors
writer.close()
output.close()

f.close()  # 关闭文件
print('f.closed=', f.closed)

运行结果

5、添加偏置

python 复制代码
# https://blog.csdn.net/kobeyu652453/article/details/106876829
import pypdf

wk_in_file_name = 'PythonTutorial.pdf'
writer = pypdf.PdfWriter()
input1 = open(wk_in_file_name, "rb")
writer.append(input1)

f = open('dir.txt', 'r', encoding='utf8')
lines = f.readlines()  # 读取所有行
num_lines = len(lines)  # 标题的总个数
offset = 5  # 添加偏置

txt = []
bookmark_parent_0 = None
bookmark_parent_1 = None

for line in lines:
    line = line.strip()  # 去掉末尾的'\n'
    pline = line.split(' ')  # 根据line中' '进行分割
    level = line.count('.')  # 有n个'.'就是n+1级标题

    page_title = pline[0] + ' ' + pline[1]
    page_num = int(pline[-1]) + offset

    if level == 0:
        bookmark_parent_0 = writer.add_outline_item(title=page_title, page_number=page_num, parent=None)
    elif level == 1:
        bookmark_parent_1 = writer.add_outline_item(title=page_title, page_number=page_num, parent=bookmark_parent_0)
    else:
        writer.add_outline_item(title=page_title, page_number=page_num, parent=bookmark_parent_1)

    print(line.strip())

print(txt)

# Write to an output PDF document
output = open('05_' + wk_in_file_name, "wb")
writer.write(output)

# Close File Descriptors
writer.close()
output.close()

f.close()  # 关闭文件
print('f.closed=', f.closed)

运行结果:

6、dir中没有页码的情况

python 复制代码
# https://blog.csdn.net/kobeyu652453/article/details/106876829
import pypdf

wk_in_file_name = 'PythonTutorial.pdf'
writer = pypdf.PdfWriter()
input1 = open(wk_in_file_name, "rb")
writer.append(input1)

f = open('dir.txt', 'r', encoding='utf8')
lines = f.readlines()  # 读取所有行
num_lines = len(lines)  # 标题的总个数
offset = 5  # 添加偏置

txt = []
bookmark_parent_0 = None
bookmark_parent_1 = None

for line in lines:
    line = line.strip()  # 去掉末尾的'\n'
    pline = line.split(' ')  # 根据line中' '进行分割
    level = line.count('.')  # 有n个'.'就是n+1级标题

    page_title = pline[0] + ' ' + pline[1]
    page_num = offset

    if level == 0:
        bookmark_parent_0 = writer.add_outline_item(title=page_title, page_number=page_num, parent=None)
    elif level == 1:
        bookmark_parent_1 = writer.add_outline_item(title=page_title, page_number=page_num, parent=bookmark_parent_0)
    else:
        writer.add_outline_item(title=page_title, page_number=page_num, parent=bookmark_parent_1)

    print(line.strip())

print(txt)

# Write to an output PDF document
output = open('06_' + wk_in_file_name, "wb")
writer.write(output)

# Close File Descriptors
writer.close()
output.close()

f.close()  # 关闭文件
print('f.closed=', f.closed)

运行结果

参考

使用 python 给 PDF 添加目录书签_pypdf2.errors.deprecationerror: pdffilereader is d_Wreng我是002的博客-CSDN博客

python 操作合并pdf 文件并建立书签目录 - 知乎

相关推荐
不想有bug的小菜鸟24 分钟前
vue3使用iframe全屏展示pdf效果
前端·pdf
紫雾凌寒1 小时前
计算机视觉 |解锁视频理解三剑客——TimeSformer
python·深度学习·神经网络·计算机视觉·transformer·timesformer
程序员杰哥2 小时前
测试用例详解
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例
go54631584657 小时前
本地部署 GitHub 上的 Python 人脸识别项目
开发语言·python·github
FreakStudio8 小时前
手把手教你用 MicroPython 玩转幻尔串口舵机,代码+教程全公开
python·嵌入式·大学生·面向对象·技术栈·电子diy·电子计算机
tekin8 小时前
基于 Python 开发在线多人游戏服务器案例解析
服务器·python·游戏·在线多人游戏服务器
让学习成为一种生活方式10 小时前
libGL.so.1: cannot open shared object file: No such file or directory-linux022
linux·开发语言·python
java1234_小锋11 小时前
一周学会Flask3 Python Web开发-Jinja2模板继承和include标签使用
python·flask·flask3
图书馆钉子户11 小时前
from flask_session import Session 为什么是Session(app)这么用?
python·flask·mybatis
一只蜗牛儿11 小时前
Sherpa-ONNX:说话人识别与语音识别自动开启(VAD)+ Python API 完整指南
人工智能·python·语音识别