我尝试使用 Python 和 PyPDF2 包来阅读 PDF 文档。目标是读取pdf中的所有书签,并构建一个以书签页码为键、书签标题为值的字典。
除了这篇文章之外,互联网上没有太多关于如何实现它的支持。其中发布的代码不起作用,我不是 python 专家来纠正它。PyPDF2的阅读器对象有一个名为outlines的属性,它为您提供所有书签对象的列表,但书签没有页码,并且遍历该列表并不困难,因为书签之间没有父/子关系。
我在下面分享我的代码来阅读 pdf 文档并检查轮廓属性。
import PyPDF2
reader = PyPDF2.PdfFileReader('SomeDocument.pdf')
print(reader.numPages)
print(reader.outlines[1][1])
Run Code Online (Sandbox Code Playgroud)
通过使列表彼此嵌套来保留父/子关系。此示例代码将以缩进的目录形式递归显示书签:
import PyPDF2
def show_tree(bookmark_list, indent=0):
for item in bookmark_list:
if isinstance(item, list):
# recursive call with increased indentation
show_tree(item, indent + 4)
else:
print(" " * indent + item.title)
reader = PyPDF2.PdfFileReader("[your filename]")
show_tree(reader.getOutlines())
Run Code Online (Sandbox Code Playgroud)
我不知道如何检索页码。我尝试了几个文件,对象page的属性Destination始终是 的实例IndirectObject,它似乎不包含有关页码的任何信息。
更新:
有一个getDestinationPageNumber方法可以从对象中获取页码Destination。修改代码以创建您想要的字典:
import PyPDF2
def bookmark_dict(bookmark_list):
result = {}
for item in bookmark_list:
if isinstance(item, list):
# recursive call
result.update(bookmark_dict(item))
else:
result[reader.getDestinationPageNumber(item)] = item.title
return result
reader = PyPDF2.PdfFileReader("[your filename]")
print(bookmark_dict(reader.getOutlines()))
Run Code Online (Sandbox Code Playgroud)
但是,请注意,如果同一页面上有多个书签(字典键必须是唯一的),您将覆盖并丢失一些值。
编辑:PyPDF2 还没有死!我是新的维护者。
\n编辑:PyPDF2 移至 pypdf我现在也是该项目的维护者
\n这是mportes 答案的更新/改进版本:
\nfrom typing import Dict, Union\n\nfrom pypdf import PdfReader\n\n\ndef bookmark_dict(\n bookmark_list, reader: PdfReader, use_labels: bool = False,\n) -> Dict[Union[str, int], str]:\n """\n Extract all bookmarks as a flat dictionary.\n\n Args:\n bookmark_list: The reader.outline or a recursive call\n use_labels: If true, use page labels. If False, use page indices.\n\n Returns:\n A dictionary mapping page labels (or page indices) to their title\n\n Examples:\n Download the PDF from https://zenodo.org/record/50395 to give it a try\n """\n result = {}\n for item in bookmark_list:\n if isinstance(item, list):\n # recursive call\n result.update(bookmark_dict(item, reader))\n else:\n page_index = reader.get_destination_page_number(item)\n page_label = reader.page_labels[page_index]\n if use_labels:\n result[page_label] = item.title\n else:\n result[page_index] = item.title\n return result\n\n\nif __name__ == "__main__":\n reader = PdfReader("GeoTopo-A5.pdf")\n bms = bookmark_dict(reader.outline, reader, use_labels=True)\n\n for page_nb, title in sorted(bms.items(), key=lambda n: f"{str(n[0]):>5}"):\n print(f"{page_nb:>3}: {title}")\nRun Code Online (Sandbox Code Playgroud)\n以下是使用 PyMupdf 和类型注释的方法:
\nfrom typing import Dict\n\nimport fitz # pip install pymupdf\n\n\ndef get_bookmarks(filepath: str) -> Dict[int, str]:\n # WARNING! One page can have multiple bookmarks!\n bookmarks = {}\n with fitz.open(filepath) as doc:\n toc = doc.getToC() # [[lvl, title, page, \xe2\x80\xa6], \xe2\x80\xa6]\n for level, title, page in toc:\n bookmarks[page] = title\n return bookmarks\n\n\nprint(get_bookmarks("my.pdf"))\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
10436 次 |
| 最近记录: |