场景引入
收到一份 200 页的培训教材,但你只需要第 15-30 页的内容。或者需要把一份合同的每个章节拆分为独立文件,分发给不同负责人。
手动操作需要打开 pdf,选择页面范围,导出——每次只能处理一部分。本节教你用 python 快速拆分和提取。
技术原理
核心操作:源 pdf → 按页拆分 → 按范围提取 → 多个独立 pdf
使用 pypdf 的 pdfreader 读取页面,pdfwriter 写入指定页面。
环境准备
完整代码
import os
from pypdf import pdfreader, pdfwriter
from pathlib import path
# ==================== 方案 1:提取指定页码范围 ====================
def extract_pages(input_pdf, start_page, end_page, output_file):
"""
从 pdf 中提取指定范围的页面
参数:
input_pdf: 源 pdf 文件
start_page: 起始页码(从 1 开始)
end_page: 结束页码(包含)
output_file: 输出文件名
"""
reader = pdfreader(input_pdf)
total = len(reader.pages)
# 验证页码范围
if start_page < 1 or end_page > total:
print(f"错误: 文件共 {total} 页,请求范围 {start_page}-{end_page}")
return
writer = pdfwriter()
for i in range(start_page - 1, end_page): # 转为 0-based 索引
writer.add_page(reader.pages[i])
with open(output_file, 'wb') as f:
writer.write(f)
print(f"已提取第 {start_page}-{end_page} 页 → {output_file}")
# ==================== 方案 2:逐页拆分 ====================
def split_pdf_by_page(input_pdf, output_dir="逐页拆分"):
"""
将 pdf 的每一页拆分为独立文件
"""
reader = pdfreader(input_pdf)
output_path = path(output_dir)
output_path.mkdir(parents=true, exist_ok=true)
base_name = path(input_pdf).stem
for i, page in enumerate(reader.pages):
writer = pdfwriter()
writer.add_page(page)
output_file = output_path / f"{base_name}_第{i+1}页.pdf"
with open(output_file, 'wb') as f:
writer.write(f)
print(f"逐页拆分完成: {len(reader.pages)} 页 → {output_dir}/")
# ==================== 方案 3:按指定块大小拆分 ====================
def split_pdf_by_chunks(input_pdf, chunk_size, output_dir="分块拆分"):
"""
按指定页数拆分(如每 10 页一个文件)
参数:
input_pdf: 源 pdf
chunk_size: 每个文件的页数
output_dir: 输出目录
"""
reader = pdfreader(input_pdf)
output_path = path(output_dir)
output_path.mkdir(parents=true, exist_ok=true)
total = len(reader.pages)
base_name = path(input_pdf).stem
chunk_count = 0
for start in range(0, total, chunk_size):
end = min(start + chunk_size, total)
writer = pdfwriter()
for i in range(start, end):
writer.add_page(reader.pages[i])
output_file = output_path / f"{base_name}_第{start+1}-{end}页.pdf"
with open(output_file, 'wb') as f:
writer.write(f)
chunk_count += 1
print(f"已拆分: 第 {start+1}-{end} 页")
print(f"\n分块拆分完成: {chunk_count} 个文件")
# ==================== 方案 4:按章节/书签拆分 ====================
def split_pdf_by_outline(input_pdf, output_dir="按章节拆分"):
"""
按 pdf 的书签(大纲)拆分为独立章节文件
"""
reader = pdfreader(input_pdf)
output_path = path(output_dir)
output_path.mkdir(parents=true, exist_ok=true)
base_name = path(input_pdf).stem
outline = reader.outline
# 提取书签信息
bookmarks = []
for item in outline:
if isinstance(item, dict) and '/title' in item:
title = item['/title']
page_num = none
if '/dest' in item:
dest = item['/dest']
if isinstance(dest, list) and dest[0]:
page_num = reader.get_destination_page_number(item)
bookmarks.append({'title': title, 'page': page_num})
if not bookmarks:
print("该 pdf 没有书签/大纲")
return
# 按书签拆分
for idx, bm in enumerate(bookmarks):
if bm['page'] is none:
continue
start = bm['page']
# 下一个书签的页码 - 1 作为结束
if idx + 1 < len(bookmarks) and bookmarks[idx + 1]['page'] is not none:
end = bookmarks[idx + 1]['page'] - 1
else:
end = len(reader.pages) - 1
writer = pdfwriter()
for i in range(start, end + 1):
writer.add_page(reader.pages[i])
safe_title = bm['title'].replace('/', '_').replace('\\', '_')
output_file = output_path / f"{safe_title}.pdf"
with open(output_file, 'wb') as f:
writer.write(f)
print(f"已拆分章节: {bm['title']} (第 {start+1}-{end+1} 页)")
print(f"\n按章节拆分完成: {output_dir}/")
# ==================== 使用示例 ====================
if __name__ == "__main__":
pdf_file = "培训教材_200页.pdf"
# 方案 1:提取第 15-30 页
extract_pages(pdf_file, 15, 30, "培训教材_核心章节.pdf")
# 方案 2:逐页拆分
# split_pdf_by_page(pdf_file)
# 方案 3:每 10 页一个文件
# split_pdf_by_chunks(pdf_file, chunk_size=10)
# 方案 4:按书签拆分
# split_pdf_by_outline(pdf_file)
常见问题
q1:提取后页面空白?
pypdf 可能无法正确处理某些特殊 pdf(如扫描件、加密文件)。尝试先解密:
if reader.is_encrypted:
reader.decrypt("")
q2:按书签拆分时没有提取到书签?
有些 pdf 的书签存储在非标准位置。可以使用 pdfplumber 获取更多信息:
import pdfplumber
with pdfplumber.open(pdf_file) as pdf:
toc = pdf.toc
print(toc)
总结
| 拆分方式 | 函数 | 说明 |
|---|---|---|
| 指定范围 | extract_pages() | 提取 start-end 页 |
| 逐页拆分 | split_pdf_by_page() | 每页一个文件 |
| 分块拆分 | split_pdf_by_chunks() | 每 n 页一个文件 |
| 按书签 | split_pdf_by_outline() | 按章节拆分 |
到此这篇关于python实现按页数或指定范围拆分pdf并提取内容的文章就介绍到这了,更多相关python拆分和提取pdf内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论