用PDFPatcher为没有书签的PDF制作书签

admin 2026-08-08 06:35:50 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文介绍使用PDFPatcher为无书签PDF制作书签,解决绝对页码与纸版页码不对应问题。核心步骤为导出书签XML、编辑映射关系并重新导入。建议结合Python脚本批量生成页码递增的书签节点,大幅提升制作电子目录效率并实现精准跳转。 综合评分: 75 文章分类: 其他


cover_image

用PDFPatcher为没有书签的PDF制作书签

原创

沈沉舟 沈沉舟

青衣十三楼飞花堂

2026年7月5日 14:27 北京

在小说阅读器读本章

去阅读

创建: 2024-02-27 19:51
更新: 2026-07-02 21:28

有些不是用Pdg2Pic制作的PDF,比如从Z站下载的,只有页面,没有书签,Chrome打开后,左侧只有缩略图,没有电子目录结构(书签)。这种,Chrome显示的页码与纸版页码并不对应,前者是PDF层面的绝对页码,后者是印刷时自定义的页码。比如纸版页码1,对应正文第1页,前面一般还有照片、序言、目录页等,不包含在纸版页码计数器内。

我分享PDF摘录时,用的是Chrome看到的绝对页码,不是纸版页码,因为我主要在PC上看电子版。正经引用书籍内容时,应给纸版页码。

书签的作用,是在纸版页码、绝对页码之间建立映射,书签显示纸版页码,点击后跳至相应的绝对页码。若无书签,就得自己找出纸版页码1所对应的绝对页码,算出差值(delta),对纸版目录中的纸版页码(增加delta)心算出绝对页码,在Chrome中手工跳转。有些人受不了这个麻烦,我倒是无所谓,内容为王,其它不重要。

另一种书签是在章节标题、绝对页码之间建立映射,相比前一种书签,二者各有利弊。

本小节介绍前一种书签的制作过程。有很多方案,只介绍一种自用方案。

用PDFPatcher打开无书签PDF。在右侧PDF页面移动鼠标至左上角,右键”在此插入书签”,”书签文本”处随便输点啥,比如”foo”,”方位”那里显示的数字实际对应刚才鼠标所在点的y坐标,坐标系的原点(0,0)是PDF页面左下角。

菜单上选,文件->换名保存书签文件->some.xml。这个xml长这样

<?xml version="1.0"&nbsp;encoding="gb2312"?>
<PDF信息&nbsp;程序名称="PDFPatcher"&nbsp;程序版本="..."&nbsp;导出时间="..."&nbsp;PDF文件位置="some.pdf">
&nbsp; &nbsp; <文档书签>
&nbsp; &nbsp; &nbsp; &nbsp; <书签&nbsp;文本="foo"&nbsp;页码="1"&nbsp;动作="转到页面"&nbsp;显示方式="坐标缩放"&nbsp;上="800"&nbsp;/>
&nbsp; &nbsp; </文档书签>
</PDF信息>

手工编辑xml,改成(只是个示例)

<?xml version="1.0"&nbsp;encoding="gb2312"?>
<PDF信息&nbsp;程序名称="PDFPatcher"&nbsp;程序版本="..."&nbsp;导出时间="..."&nbsp;PDF文件位置="some.pdf">
&nbsp; &nbsp; <文档书签>
<书签&nbsp;文本="照片"&nbsp;动作="转到页面"&nbsp;页码="4"&nbsp;显示方式="坐标缩放"&nbsp;左="0"&nbsp;上="800"&nbsp;比例="0"&nbsp;/>
<书签&nbsp;文本="自序"&nbsp;动作="转到页面"&nbsp;页码="15"&nbsp;显示方式="坐标缩放"&nbsp;左="0"&nbsp;上="800"&nbsp;比例="0"&nbsp;/>
<书签&nbsp;文本="目录"&nbsp;动作="转到页面"&nbsp;页码="19"&nbsp;显示方式="坐标缩放"&nbsp;左="0"&nbsp;上="800"&nbsp;比例="0"&nbsp;/>
<书签&nbsp;文本="1"&nbsp;动作="转到页面"&nbsp;页码="28"&nbsp;显示方式="坐标缩放"&nbsp;左="0"&nbsp;上="800"&nbsp;比例="0"&nbsp;/>
<书签&nbsp;文本="2"&nbsp;动作="转到页面"&nbsp;页码="29"&nbsp;显示方式="坐标缩放"&nbsp;左="0"&nbsp;上="800"&nbsp;比例="0"&nbsp;/>
...
<书签&nbsp;文本="384"&nbsp;动作="转到页面"&nbsp;页码="411"&nbsp;显示方式="坐标缩放"&nbsp;左="0"&nbsp;上="800"&nbsp;比例="0"&nbsp;/>
&nbsp; &nbsp; </文档书签>
</PDF信息>

解释一下<书签>中的某几个字段

文本 &nbsp;将来显示的电子目录结构(书签)
页码 &nbsp;与"文本"字段关联的绝对页码,即跳转目标的绝对页码
左 &nbsp; &nbsp;跳转目标点的x坐标,一般对应目标页的左上角,可调整至目标页任意位置
上 &nbsp; &nbsp;跳转目标点的y坐标,一般对应目标页的左上角,可调整至目标页任意位置

其他字段保持上例展示的那样。xml决定书签效果,”文本”想写什么都可以;”页码”要与”文本”匹配,否则跳转目标非预期;跳转后展示时自动滚动到(x,y)处,比如想跳至页面中部某处,每个目标页的(x,y)是独立的;有多少条<书签>行都成。

假设已编辑好some.xml,回到PDFPatcher,先删除之前搞的foo书签,菜单上选,文件->导入书签(Ctrl+R),文件->保存PDF文件(Ctrl+S),指定新PDF文件名。

Chrome中打开some_new.pdf,检验书签效果。

一般<书签>行很多,上例纸版页码从1到384递增,每行只有”文本”、”页码”两字段递增,手工编辑不理智,可用程序自动生成。

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

#
# python3 bookmark.py <param0> <param1> <param2> [count]
# python3 bookmark.py 1 28 800 10
# python3 bookmark.py 1 28 800 384 > some.txt
#
# param0 书签中看到的数字,对应纸版页码
# param1 Chrome打开PDF时的绝对页码,不对应纸版页码
# param2 用PDFPatcher获取目标页面左上角y坐标
# count &nbsp;缺省为10
#

import&nbsp;sys

def&nbsp;main&nbsp;( argv ) :
&nbsp; &nbsp; ret =&nbsp;False
&nbsp; &nbsp; while&nbsp;True&nbsp;:
&nbsp; &nbsp; &nbsp; &nbsp; if&nbsp;len( argv ) <&nbsp;4&nbsp;:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(&nbsp;f"Usage: python3&nbsp;{argv[0]}&nbsp;<param0> <param1> <param2> [count]"&nbsp;)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break
&nbsp; &nbsp; &nbsp; &nbsp; try&nbsp;:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; param0 &nbsp;=&nbsp;int( argv[1] )
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; param1 &nbsp;=&nbsp;int( argv[2] )
&nbsp; &nbsp; &nbsp; &nbsp; except&nbsp;ValueError :
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(&nbsp;"param0 and param1 must be integer"&nbsp;)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break
&nbsp; &nbsp; &nbsp; &nbsp; param2 &nbsp;= argv[3]
&nbsp; &nbsp; &nbsp; &nbsp; count &nbsp; =&nbsp;10
&nbsp; &nbsp; &nbsp; &nbsp; if&nbsp;len( argv ) >&nbsp;4&nbsp;:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try&nbsp;:
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; count &nbsp; =&nbsp;int( argv[4] )
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; except&nbsp;ValueError :
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(&nbsp;"count must be integer"&nbsp;)
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break
&nbsp; &nbsp; &nbsp; &nbsp; for&nbsp;_&nbsp;in&nbsp;range( count ) :
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pattern =&nbsp;f'<书签 文本="{param0}" 动作="转到页面" 页码="{param1}" 显示方式="坐标缩放" 左="0" 上="{param2}" 比例="0" />'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print( pattern )
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; param0 +=&nbsp;1
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; param1 +=&nbsp;1
&nbsp; &nbsp; &nbsp; &nbsp; ret &nbsp; &nbsp; =&nbsp;True
&nbsp; &nbsp; &nbsp; &nbsp; break
&nbsp; &nbsp; return&nbsp;ret

if&nbsp;"__main__"&nbsp;== __name__ :
&nbsp; &nbsp; ret &nbsp; &nbsp; = main( sys.argv )
&nbsp; &nbsp; sys.exit(&nbsp;0&nbsp;if&nbsp;ret&nbsp;else&nbsp;-1&nbsp;)

bookmark.py只生成纸版页码到绝对页码的映射行,照片、序言、目录页的映射行需手工组织。

某些书签制作教程,全自动生成some.xml。PDF是文字版时,是一种搞法;PDF是图片扫描版时,动用OCR提取纸版目录的文字说明。我没全自动的需求,略。

若非从零生成书签,只想微调零星几个映射,可不用xml,直接在PDFPatcher中操作,略。

不确认PDFPatcher是否支持Excel下拉操作,选中纸版页码、绝对页码,下拉自动递增。若支持,前面那些都是废话,忘掉即可。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:青衣十三楼飞花堂 沈沉舟 沈沉舟《用PDFPatcher为没有书签的PDF制作书签》

评论:0   参与:  0