当前位置: 代码网 > it编程>前端脚本>Python > Python实现按页数或指定范围拆分PDF并提取内容

Python实现按页数或指定范围拆分PDF并提取内容

2026年08月27日 Python 我要评论
场景引入收到一份 200 页的培训教材,但你只需要第 15-30 页的内容。或者需要把一份合同的每个章节拆分为独立文件,分发给不同负责人。手动操作需要打开 pdf,选择页面范围,导出—&m

场景引入

收到一份 200 页的培训教材,但你只需要第 15-30 页的内容。或者需要把一份合同的每个章节拆分为独立文件,分发给不同负责人。

手动操作需要打开 pdf,选择页面范围,导出——每次只能处理一部分。本节教你用 python 快速拆分和提取。

技术原理

核心操作:源 pdf → 按页拆分 → 按范围提取 → 多个独立 pdf

使用 pypdfpdfreader 读取页面,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内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com