如何用pikepdf将PDF1的大纲复制到重排后的PDF2中?
问题描述
我用pikepdf模块编写了代码,将PDF1的页面重排后保存为PDF2,代码如下:
import pikepdf def Main(): with pikepdf.open("pdf1.pdf") as sourcePDF: sourcePages = sourcePDF.pages targetPDF = pikepdf.Pdf.new() targetPages = targetPDF.pages # 根据指定列表重排页面 for idx in [1, 7, 2, 3, 4, 5, 6, 0]: targetPages.append(sourcePages[idx]) targetPDF.save("pdf2.pdf") if __name__ == "__main__": Main()
请问能否将PDF1的大纲(书签等)也复制到PDF2中,并关联到对应的重排后页面?我尝试了以下代码,但无法正确使用copy_foreign方法:
with sourcePDF.open_outline() as sourceOutline: with targetPDF.open_outline() as targetOutline: for outline in sourceOutline.root: targetOutline.root.append(sourcePDF.copy_foreign(outline))
解决方案
可以实现,但不能直接复制书签——原书签关联的是原PDF的页面,重排后新PDF的页面顺序已改变,必须先建立原页面索引到新页面的映射,再复制书签并更新其目标页面。
修改后的完整代码
import pikepdf def copy_outline_with_updated_pages(source_pdf, target_pdf, page_order): # 建立原页面索引到新PDF页面对象的映射 page_map = {} for new_idx, old_idx in enumerate(page_order): # 记录原索引对应的新页面对象 page_map[old_idx] = target_pdf.pages[new_idx] with source_pdf.open_outline() as source_outline, target_pdf.open_outline() as target_outline: def process_outline_item(item, parent=None): # 复制书签条目到目标PDF copied_item = source_pdf.copy_foreign(item) # 更新书签的目标页面 if hasattr(copied_item, 'Dest'): # 处理直接指向页面的Dest if isinstance(copied_item.Dest, pikepdf.Page): old_page_idx = source_pdf.pages.index(copied_item.Dest) copied_item.Dest = page_map[old_page_idx] # 处理数组形式的Dest(PDF标准格式,第一个元素为页面) elif isinstance(copied_item.Dest, list) and isinstance(copied_item.Dest[0], pikepdf.Page): old_page_idx = source_pdf.pages.index(copied_item.Dest[0]) copied_item.Dest[0] = page_map[old_page_idx] # 添加到目标大纲的对应位置 if parent is None: target_outline.root.append(copied_item) else: parent.append(copied_item) # 递归处理子书签 if hasattr(item, 'Kids'): for child in item.Kids: process_outline_item(child, parent=copied_item) # 遍历原大纲的所有根条目 for root_item in source_outline.root: process_outline_item(root_item) def Main(): # 页面重排顺序 page_order = [1, 7, 2, 3, 4, 5, 6, 0] with pikepdf.open("pdf1.pdf") as sourcePDF: targetPDF = pikepdf.Pdf.new() targetPages = targetPDF.pages # 执行页面重排 for idx in page_order: targetPages.append(sourcePDF.pages[idx]) # 复制并更新大纲书签 copy_outline_with_updated_pages(sourcePDF, targetPDF, page_order) targetPDF.save("pdf2.pdf") if __name__ == "__main__": Main()
关键要点
- 页面映射:通过
page_map字典记录原PDF页面索引与新PDF页面对象的对应关系,确保书签指向重排后的正确页面。 - 递归处理子书签:遍历书签的
Kids属性,保证所有层级的子书签都能被正确复制和更新。 - 兼容多种Dest格式:针对PDF书签常见的两种目标格式(直接页面引用、数组形式)做了适配,覆盖大多数场景。
内容的提问来源于stack exchange,提问作者nidias57
相关产品推荐
相关产品推荐

