python 如何获取书签的页码

omhiaaxx  于 12个月前  发布在  Python
关注(0)|答案(4)|浏览(134)
from typing import List
from PyPDF2 import PdfFileReader
from PyPDF2.generic import Destination

def get_outlines(pdf_filepath: str) -> List[Destination]:
    """Get the bookmarks of a PDF file."""
    with open(pdf_filepath, "rb") as fp:
        pdf_file_reader = PdfFileReader(fp)
        outlines = pdf_file_reader.getOutlines()
    return outlines

print(get_outlines("PDF-export-example.pdf"))

字符串
pyPdf.pdf.Destination有很多属性,但我找不到该书签的引用页码。我如何获得书签的页码?
例如,outlines[1].page.idnum返回的数字大约是PDF文档中引用的页码的3倍,我假设引用的对象比页面小,因为在整个PDF文档大纲上运行.page.idnum返回的数字数组甚至与PDF文档中的“真实的”页码目标不线性相关,并且大约是3倍
更新:这个问题和这个一样:split a pdf based on outline虽然我不明白作者在他的自我回答中做了什么。对我来说似乎太复杂了,无法使用

7fyelxc5

7fyelxc51#

正如@theta指出的,“split a pdf based on outline“有提取页码所需的代码。如果你觉得这很复杂,我复制了部分将页面idMap到页码的代码,并将其变成一个函数。下面是一个打印书签o[0]页码的工作示例:

from PyPDF2 import PdfFileReader

def _setup_page_id_to_num(pdf, pages=None, _result=None, _num_pages=None):
    if _result is None:
        _result = {}
    if pages is None:
        _num_pages = []
        pages = pdf.trailer["/Root"].getObject()["/Pages"].getObject()
    t = pages["/Type"]
    if t == "/Pages":
        for page in pages["/Kids"]:
            _result[page.idnum] = len(_num_pages)
            _setup_page_id_to_num(pdf, page.getObject(), _result, _num_pages)
    elif t == "/Page":
        _num_pages.append(1)
    return _result
# main
f = open('document.pdf','rb')
p = PdfFileReader(f)
# map page ids to page numbers
pg_id_num_map = _setup_page_id_to_num(p)
o = p.getOutlines()
pg_num = pg_id_num_map[o[0].page.idnum] + 1
print(pg_num)

字符串
可能太晚了@theta,但可能会帮助别人:)顺便说一句,我的第一个职位上stackoverflow,所以请原谅我,如果我没有遵循通常的格式

**为了进一步扩展:**如果您正在寻找书签在页面上的确切位置,这将使您的工作更容易:

from PyPDF2 import PdfFileReader
import PyPDF2 as pyPdf

def _setup_page_id_to_num(pdf, pages=None, _result=None, _num_pages=None):
    if _result is None:
        _result = {}
    if pages is None:
        _num_pages = []
        pages = pdf.trailer["/Root"].getObject()["/Pages"].getObject()
    t = pages["/Type"]
    if t == "/Pages":
        for page in pages["/Kids"]:
            _result[page.idnum] = len(_num_pages)
            _setup_page_id_to_num(pdf, page.getObject(), _result, _num_pages)
    elif t == "/Page":
        _num_pages.append(1)
    return _result
def outlines_pg_zoom_info(outlines, pg_id_num_map, result=None):
    if result is None:
        result = dict()
    if type(outlines) == list:
        for outline in outlines:
            result = outlines_pg_zoom_info(outline, pg_id_num_map, result)
    elif type(outlines) == pyPdf.pdf.Destination:
        title = outlines['/Title']
        result[title.split()[0]] = dict(title=outlines['/Title'], top=outlines['/Top'], \
        left=outlines['/Left'], page=(pg_id_num_map[outlines.page.idnum]+1))
    return result

# main
pdf_name = 'document.pdf'
f = open(pdf_name,'rb')
pdf = PdfFileReader(f)
# map page ids to page numbers
pg_id_num_map = _setup_page_id_to_num(pdf)
outlines = pdf.getOutlines()
bookmarks_info = outlines_pg_zoom_info(outlines, pg_id_num_map)
print(bookmarks_info)

注:我的书签是章节号(例如:1.1简介),我将书签信息Map到章节号。如果您的书签不同,请修改这部分代码:

elif type(outlines) == pyPdf.pdf.Destination:
        title = outlines['/Title']
        result[title.split()[0]] = dict(title=outlines['/Title'], top=outlines['/Top'], \
        left=outlines['/Left'], page=(pg_id_num_map[outlines.page.idnum]+1))

vjrehmav

vjrehmav2#

使用vjayky和Giulio D建议递归管理书签。
PyPDF2 >= v1.25

from PyPDF2 import PdfFileReader

def printBookmarksPageNumbers(pdf):
    def reviewAndPrintBookmarks(bookmarks, indent=0):
        for b in bookmarks:
            if type(b) == list:
                reviewAndPrintBookmarks(b, indent + 4)
                continue
            pg_num = pdf.getDestinationPageNumber(b) + 1  # page count starts from 0
            print("%s%s: Page %s" % (" " * indent, b.title, pg_num))

    reviewAndPrintBookmarks(pdf.getOutlines())

with open('document.pdf', "rb") as f:
    pdf = PdfFileReader(f)
    printBookmarksPageNumbers(pdf)

字符串
PyPDF2 < v1.25

from PyPDF2 import PdfFileReader

def printBookmarksPageNumbers(pdf):
    # Map page ids to page numbers
    pg_id_to_num = {}
    for pg_num in range(0, pdf.getNumPages()):
        pg_id_to_num[pdf.getPage(pg_num).indirectRef.idnum] = pg_num

    def reviewAndPrintBookmarks(bookmarks, indent=0):
        for b in bookmarks:
            if type(b) == list:
                reviewAndPrintBookmarks(b, indent + 4)
                continue
            pg_num = pg_id_to_num[b.page.idnum] + 1  # page count starts from 0
            print("%s%s: Page %s" % (" " * indent, b.title, pg_num))

    reviewAndPrintBookmarks(pdf.getOutlines())

with open('document.pdf', "rb") as f:
    pdf = PdfFileReader(f)
    printBookmarksPageNumbers(pdf)


示例输出(两种方法):

Bookmark 1: Page 1
    Bookmark 1.1: Page 2
    Bookmark 1.2: Page 3
Bookmark 2: Page 4
Bookmark 3: Page 5
    Bookmark 3.1: Page 6

iaqfqrcu

iaqfqrcu3#

在2019年,对于那些对更快的方式感兴趣的人来说,可以用途:

from PyPDF2 import PdfFileReader

def printPageNumberFrom(filename):
    with open(filename, "rb") as f:
       pdf = PdfFileReader(f)
       bookmarks = pdf.getOutlines()
       for b in bookmarks:
           print(pdf.getDestinationPageNumber(b) + 1) #page count starts from 0

字符串

ulmd4ohb

ulmd4ohb4#

我不确定,但根据pypdf.Destination的文档,书签的页码只是Destination.page。

相关问题