首页
/ Python PDF处理实战指南:从入门到精通的PyPDF完全掌握

Python PDF处理实战指南:从入门到精通的PyPDF完全掌握

2026-05-03 11:31:45作者:申梦珏Efrain

在数字化时代,PDF文档处理已成为开发者日常工作中不可或缺的技能。Python凭借其丰富的库生态,为PDF处理提供了强大支持,其中PyPDF作为轻量级yet功能全面的库,能够满足从简单文本提取到复杂文档操作的各种需求。本文将通过实战案例,全面讲解如何利用PyPDF进行高效PDF处理,帮助开发者快速掌握这一必备技能。

环境搭建与基础准备

PyPDF安装与验证

问题:如何快速搭建Python PDF处理环境?
解决方案:使用pip安装PyPDF库并验证版本。

# 安装PyPDF库
pip install pypdf

# 创建虚拟环境(可选但推荐)
python -m venv pdf-env
source pdf-env/bin/activate  # Linux/Mac
pdf-env\Scripts\activate     # Windows

验证安装是否成功:

import pypdf
print(f"PyPDF版本: {pypdf.__version__}")
# 输出示例: PyPDF版本: 3.17.1

进阶技巧:指定安装特定版本以确保兼容性:

pip install pypdf==3.17.1

PDF文档基础操作

文档信息提取

问题:如何获取PDF文档的元数据和基本信息?
解决方案:使用PdfReader类读取文档属性。

from pypdf import PdfReader

def extract_pdf_info(pdf_path):
    """提取PDF文档基本信息"""
    try:
        # 创建PdfReader对象
        reader = PdfReader(pdf_path)
        
        # 获取文档基本信息
        info = {
            "页数": len(reader.pages),
            "标题": reader.metadata.title,
            "作者": reader.metadata.author,
            "创建日期": reader.metadata.creation_date,
            "修改日期": reader.metadata.modification_date,
            "主题": reader.metadata.subject,
            "关键词": reader.metadata.keywords
        }
        
        return info
        
    except FileNotFoundError:
        print(f"错误: 文件 '{pdf_path}' 不存在")
        return None
    except Exception as e:
        print(f"处理PDF时出错: {str(e)}")
        return None

# 使用示例
if __name__ == "__main__":
    pdf_info = extract_pdf_info("example.pdf")
    if pdf_info:
        for key, value in pdf_info.items():
            print(f"{key}: {value}")

进阶技巧:处理加密PDF文件时,需要提供密码:

reader = PdfReader("encrypted.pdf")
if reader.is_encrypted:
    reader.decrypt("password")

文本内容提取

问题:如何从PDF中提取文本内容进行分析?
解决方案:使用PageObject的extract_text()方法。

from pypdf import PdfReader

def extract_pdf_text(pdf_path, start_page=0, end_page=None):
    """
    提取PDF文档中的文本内容
    
    参数:
        pdf_path: PDF文件路径
        start_page: 开始提取的页码(从0开始)
        end_page: 结束提取的页码(None表示提取到最后一页)
    
    返回:
        提取的文本内容
    """
    text = []
    
    try:
        reader = PdfReader(pdf_path)
        total_pages = len(reader.pages)
        
        # 确定结束页码
        end_page = end_page or total_pages - 1
        if end_page >= total_pages:
            end_page = total_pages - 1
            
        # 提取指定范围的页面文本
        for page_num in range(start_page, end_page + 1):
            page = reader.pages[page_num]
            page_text = page.extract_text()
            if page_text:
                text.append(f"=== 第 {page_num + 1} 页 ===")
                text.append(page_text)
        
        return "\n".join(text)
        
    except Exception as e:
        print(f"提取文本时出错: {str(e)}")
        return None

# 使用示例
if __name__ == "__main__":
    pdf_text = extract_pdf_text("example.pdf", start_page=0, end_page=2)
    if pdf_text:
        print(pdf_text)
        # 保存到文件
        with open("extracted_text.txt", "w", encoding="utf-8") as f:
            f.write(pdf_text)

常见问题解决

  1. 文本乱码或提取不完整:尝试调整页面布局分析模式

    page = reader.pages[page_num]
    text = page.extract_text(extraction_mode="layout")  # 尝试不同的提取模式
    
  2. 加密文档无法提取:先解密再提取

    if reader.is_encrypted:
        reader.decrypt("password")  # 提供密码
    

PDF页面管理高级操作

PDF合并实战

问题:如何将多个PDF文件合并为一个文档?
解决方案:使用PdfMerger类实现高效合并。

from pypdf import PdfMerger
import os

def merge_pdfs(input_paths, output_path, bookmarks=True):
    """
    合并多个PDF文件
    
    参数:
        input_paths: PDF文件路径列表
        output_path: 输出文件路径
        bookmarks: 是否保留原文档书签
    """
    merger = PdfMerger()
    
    try:
        for path in input_paths:
            # 验证文件是否存在
            if not os.path.exists(path):
                print(f"警告: 文件 '{path}' 不存在,已跳过")
                continue
                
            # 添加PDF文件,可以指定书签名称
            bookmark_name = os.path.splitext(os.path.basename(path))[0]
            merger.append(path, bookmark=bookmark_name if bookmarks else None)
        
        # 写入合并结果
        merger.write(output_path)
        print(f"成功合并 {len(input_paths)} 个PDF文件到 {output_path}")
        
    except Exception as e:
        print(f"合并PDF时出错: {str(e)}")
        return False
    finally:
        # 确保资源被释放
        merger.close()
        
    return True

# 使用示例
if __name__ == "__main__":
    # 要合并的PDF文件列表
    pdf_files = ["document1.pdf", "document2.pdf", "document3.pdf"]
    
    # 执行合并
    merge_pdfs(pdf_files, "merged_result.pdf")

PDF合并示例 使用PyPDF合并多个PDF文档的效果展示,保留了原始页面布局和内容

进阶技巧:合并特定页面范围

# 只合并每个PDF的第一页到第三页
merger.append("document.pdf", pages=(0, 3))

页面旋转与调整

问题:如何旋转PDF页面并调整布局?
解决方案:使用页面旋转方法和Transformation类。

from pypdf import PdfReader, PdfWriter
from pypdf.transformations import Transformation

def rotate_and_transform_pdf(input_path, output_path, rotation_angle=0, scale_factor=1.0):
    """
    旋转PDF页面并应用缩放变换
    
    参数:
        input_path: 输入PDF路径
        output_path: 输出PDF路径
        rotation_angle: 旋转角度(度),支持0, 90, 180, 270
        scale_factor: 缩放因子,1.0为原始大小
    """
    reader = PdfReader(input_path)
    writer = PdfWriter()
    
    for page in reader.pages:
        # 旋转页面
        if rotation_angle != 0:
            page.rotate(rotation_angle)
            
        # 应用缩放变换
        if scale_factor != 1.0:
            transform = Transformation().scale(scale_factor, scale_factor)
            page.add_transformation(transform)
            
        writer.add_page(page)
    
    # 保存结果
    with open(output_path, "wb") as f:
        writer.write(f)
        
    print(f"已将PDF旋转 {rotation_angle} 度并缩放到 {scale_factor} 倍")

# 使用示例
if __name__ == "__main__":
    # 旋转45度并缩放到80%
    rotate_and_transform_pdf("source.pdf", "transformed.pdf", 45, 0.8)

页面旋转效果 PDF页面旋转45度后的效果展示,保持内容完整性

常见问题解决

  1. 旋转后内容被截断:先缩放再旋转

    # 先缩小再旋转,避免内容被截断
    transform = Transformation().scale(0.8, 0.8)
    page.add_transformation(transform)
    page.rotate(90)
    
  2. 页面方向错误:检查旋转角度是否为90的倍数

    # 确保旋转角度是90的倍数
    rotation_angle = (rotation_angle % 360)
    if rotation_angle not in [0, 90, 180, 270]:
        raise ValueError("旋转角度必须是0, 90, 180或270度")
    

PDF内容增强与安全保护

水印添加技术

问题:如何为PDF文档添加水印保护知识产权?
解决方案:创建透明文本水印并添加到每一页。

from pypdf import PdfReader, PdfWriter
from pypdf.generic import Annotation, TextStringObject, NameObject
from pypdf.annotations import FreeText

def add_watermark(input_pdf, output_pdf, watermark_text, opacity=0.3):
    """
    为PDF添加文本水印
    
    参数:
        input_pdf: 输入PDF路径
        output_pdf: 输出PDF路径
        watermark_text: 水印文本
        opacity: 水印透明度 (0.0-1.0)
    """
    reader = PdfReader(input_pdf)
    writer = PdfWriter()
    
    # 水印外观设置
    watermark = {
        "text": watermark_text,
        "font_size": 48,
        "color": (0.5, 0.5, 0.5),  # 灰色
        "opacity": opacity,
        "rotation": 45,  # 旋转45度
        "x": 300,  # X坐标
        "y": 400   # Y坐标
    }
    
    for page in reader.pages:
        # 添加水印作为注释
        annotation = FreeText(
            text=TextStringObject(watermark["text"]),
            rect=(watermark["x"], watermark["y"], watermark["x"]+200, watermark["y"]+50),
            font="Helvetica",
            bold=True,
            italic=False,
            font_size=watermark["font_size"],
            color=watermark["color"],
            opacity=watermark["opacity"],
            rotation=watermark["rotation"],
        )
        
        # 将注释添加到页面
        if "/Annots" not in page:
            page[NameObject("/Annots")] = []
        page["/Annots"].append(annotation)
        
        writer.add_page(page)
    
    # 保存结果
    with open(output_pdf, "wb") as f:
        writer.write(f)
        
    print(f"已为PDF添加水印: {watermark_text}")

# 使用示例
if __name__ == "__main__":
    add_watermark("original.pdf", "watermarked.pdf", "CONFIDENTIAL", opacity=0.2)

PDF水印效果 为PDF文档添加半透明"CONFIDENTIAL"水印的效果展示

进阶技巧:添加图片水印

from pypdf import PdfReader, PdfWriter
from pypdf._page import PageObject

def add_image_watermark(input_pdf, output_pdf, watermark_image_path, opacity=0.3):
    """添加图片水印"""
    reader = PdfReader(input_pdf)
    writer = PdfWriter()
    watermark_reader = PdfReader(watermark_image_path)
    watermark_page = watermark_reader.pages[0]
    
    for page in reader.pages:
        # 创建新页面作为结果
        new_page = PageObject.create_blank_page(width=page.mediabox.width, height=page.mediabox.height)
        
        # 添加原始页面内容
        new_page.merge_page(page)
        
        # 添加水印图片
        new_page.merge_translated_page(watermark_page, page.mediabox.width/2, page.mediabox.height/2, overlay=True)
        
        writer.add_page(new_page)
    
    with open(output_pdf, "wb") as f:
        writer.write(f)

文本高亮与注释

问题:如何在PDF中高亮重要文本并添加注释?
解决方案:使用PyPDF的注释功能实现文本高亮。

from pypdf import PdfReader, PdfWriter
from pypdf.generic import RectangleObject, NameObject, TextStringObject
from pypdf.annotations import Highlight

def highlight_text_in_pdf(input_pdf, output_pdf, page_num, text_positions):
    """
    在PDF中高亮指定文本位置
    
    参数:
        input_pdf: 输入PDF路径
        output_pdf: 输出PDF路径
        page_num: 页码(从0开始)
        text_positions: 要高亮的文本位置列表,每个位置是一个包含坐标的元组 (x0, y0, x1, y1)
    """
    reader = PdfReader(input_pdf)
    writer = PdfWriter()
    
    for i, page in enumerate(reader.pages):
        # 复制原始页面内容
        writer.add_page(page)
        
        # 只处理指定页面
        if i == page_num:
            # 获取当前页面对象
            current_page = writer.pages[i]
            
            # 如果没有注释列表,创建一个
            if "/Annots" not in current_page:
                current_page[NameObject("/Annots")] = []
            
            # 添加高亮注释
            for pos in text_positions:
                x0, y0, x1, y1 = pos
                
                # 创建高亮注释
                highlight = Highlight(
                    rect=RectangleObject([x0, y0, x1, y1]),
                    quad_points=[x0, y1, x1, y1, x0, y0, x1, y0],
                    color=(1, 1, 0)  # 黄色
                )
                
                # 添加注释到页面
                current_page["/Annots"].append(highlight)
    
    # 保存结果
    with open(output_pdf, "wb") as f:
        writer.write(f)
        
    print(f"已在第 {page_num+1} 页添加 {len(text_positions)} 处高亮")

# 使用示例
if __name__ == "__main__":
    # 假设我们已经通过某种方式获取了文本位置
    # 这些坐标需要根据实际PDF内容进行调整
    text_positions = [
        (100, 700, 200, 720),  # (x0, y0, x1, y1)
        (300, 650, 450, 670)
    ]
    
    highlight_text_in_pdf("document.pdf", "highlighted.pdf", 0, text_positions)

文本高亮效果 使用PyPDF高亮PDF文档中重要文本的效果展示

常见问题解决

  1. 无法确定文本坐标:使用PDF解析工具获取文本位置

    # 获取文本内容及其位置信息
    from pypdf import PdfReader
    
    reader = PdfReader("document.pdf")
    page = reader.pages[0]
    text_content = page.extract_text(extraction_mode="layout")
    # 分析text_content获取文本位置
    
  2. 高亮显示异常:确保坐标系统正确

    # PDF坐标系统原点在左下角,需要注意y轴方向
    # 可以先获取页面尺寸进行调整
    page_width = page.mediabox.width
    page_height = page.mediabox.height
    

页面视觉优化与布局调整

页面缩放与裁剪

问题:如何调整PDF页面大小和内容缩放比例?
解决方案:使用Transformation类实现内容缩放和页面调整。

from pypdf import PdfReader, PdfWriter
from pypdf.transformations import Transformation

def scale_pdf_content(input_path, output_path, scale_factor=0.8, new_page_size=None):
    """
    缩放PDF内容并可选调整页面大小
    
    参数:
        input_path: 输入PDF路径
        output_path: 输出PDF路径
        scale_factor: 内容缩放因子 (默认0.8)
        new_page_size: 新页面大小,格式为 (width, height),None表示保持原尺寸
    """
    reader = PdfReader(input_path)
    writer = PdfWriter()
    
    for page in reader.pages:
        # 创建缩放变换
        transform = Transformation().scale(scale_factor, scale_factor)
        page.add_transformation(transform)
        
        # 如果指定了新页面大小,调整页面
        if new_page_size:
            page.mediabox.upper_right = new_page_size
        
        writer.add_page(page)
    
    # 保存结果
    with open(output_path, "wb") as f:
        writer.write(f)
        
    print(f"PDF内容已缩放到 {scale_factor*100}%")
    if new_page_size:
        print(f"页面大小已调整为 {new_page_size}")

# 使用示例
if __name__ == "__main__":
    # 缩放到80%并调整页面大小
    scale_pdf_content("original.pdf", "scaled.pdf", 0.8, (595, 842))  # A4尺寸

页面缩放对比 PDF页面缩放效果对比,从左到右分别为原始大小、内容缩放和页面缩放

进阶技巧:精确控制内容位置

# 缩放并居中内容
transform = (
    Transformation()
    .scale(scale_factor, scale_factor)
    .translate(
        (page.mediabox.width * (1 - scale_factor)) / 2,
        (page.mediabox.height * (1 - scale_factor)) / 2
    )
)
page.add_transformation(transform)

PDF安全与权限管理

PDF加密与权限控制

问题:如何为PDF文档添加密码保护和权限控制?
解决方案:使用PdfWriter的encrypt方法设置密码和权限。

from pypdf import PdfReader, PdfWriter

def encrypt_pdf(input_path, output_path, user_password, owner_password=None, permissions=None):
    """
    为PDF添加密码保护和权限控制
    
    参数:
        input_path: 输入PDF路径
        output_path: 输出PDF路径
        user_password: 用户密码(打开文档)
        owner_password: 所有者密码(完全权限,默认为随机生成)
        permissions: 权限设置字典
    """
    # 默认权限设置
    default_permissions = {
        "print": True,
        "modify": False,
        "copy": False,
        "annotate": True
    }
    
    # 合并用户权限设置
    if permissions:
        default_permissions.update(permissions)
    
    reader = PdfReader(input_path)
    writer = PdfWriter()
    
    # 添加所有页面
    for page in reader.pages:
        writer.add_page(page)
    
    # 设置加密和权限
    writer.encrypt(
        user_password=user_password,
        owner_password=owner_password,
        use_128bit=True,  # 使用128位加密
        permissions_flags={
            "/Print": default_permissions["print"],
            "/ModifyContents": default_permissions["modify"],
            "/CopyContents": default_permissions["copy"],
            "/Annotate": default_permissions["annotate"]
        }
    )
    
    # 保存加密后的PDF
    with open(output_path, "wb") as f:
        writer.write(f)
        
    print(f"PDF已加密并保存到 {output_path}")

# 使用示例
if __name__ == "__main__":
    # 设置权限:允许打印和注释,但禁止修改和复制
    permissions = {
        "print": True,
        "modify": False,
        "copy": False,
        "annotate": True
    }
    
    encrypt_pdf(
        "sensitive.pdf", 
        "encrypted_sensitive.pdf", 
        user_password="reader123",
        owner_password="admin456",
        permissions=permissions
    )

常见问题解决

  1. 加密后文件损坏:确保使用正确的加密参数

    # 使用兼容模式加密,确保在所有PDF查看器中可打开
    writer.encrypt(user_password, use_128bit=True, compress=False)
    
  2. 忘记密码:无法恢复加密PDF的密码,建议使用密码管理工具妥善保存

性能优化与批量处理

批量PDF处理自动化

问题:如何高效处理大量PDF文件?
解决方案:创建批量处理脚本,结合多线程提高效率。

import os
import glob
import concurrent.futures
from pypdf import PdfReader, PdfWriter

def process_single_pdf(input_path, output_dir, watermark_text=None):
    """处理单个PDF文件"""
    try:
        # 创建输出目录(如果不存在)
        os.makedirs(output_dir, exist_ok=True)
        
        # 获取输出文件名
        filename = os.path.basename(input_path)
        output_path = os.path.join(output_dir, filename)
        
        # 读取PDF
        reader = PdfReader(input_path)
        writer = PdfWriter()
        
        # 添加所有页面
        for page in reader.pages:
            # 如果需要添加水印
            if watermark_text:
                # 添加水印逻辑(此处省略,参考前面的水印添加函数)
                pass
            writer.add_page(page)
        
        # 保存处理后的PDF
        with open(output_path, "wb") as f:
            writer.write(f)
            
        return f"成功处理: {filename}"
        
    except Exception as e:
        return f"处理失败 {input_path}: {str(e)}"

def batch_process_pdfs(input_dir, output_dir, watermark_text=None, max_workers=4):
    """
    批量处理PDF文件
    
    参数:
        input_dir: 输入目录
        output_dir: 输出目录
        watermark_text: 水印文本(可选)
        max_workers: 最大工作线程数
    """
    # 获取所有PDF文件
    pdf_files = glob.glob(os.path.join(input_dir, "*.pdf"))
    
    if not pdf_files:
        print("未找到PDF文件")
        return
    
    print(f"找到 {len(pdf_files)} 个PDF文件,开始处理...")
    
    # 使用多线程处理
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 提交所有任务
        futures = [
            executor.submit(
                process_single_pdf, 
                pdf_file, 
                output_dir, 
                watermark_text
            ) for pdf_file in pdf_files
        ]
        
        # 获取结果
        for future in concurrent.futures.as_completed(futures):
            print(future.result())
    
    print("批量处理完成")

# 使用示例
if __name__ == "__main__":
    batch_process_pdfs(
        input_dir="input_pdfs",
        output_dir="processed_pdfs",
        watermark_text="PROCESSED",
        max_workers=4
    )

内存优化策略

问题:处理大型PDF时如何减少内存占用?
解决方案:使用流式处理和分块操作。

from pypdf import PdfReader, PdfWriter

def memory_efficient_pdf_processing(input_path, output_path, page_range=None):
    """
    内存高效的PDF处理
    
    参数:
        input_path: 输入PDF路径
        output_path: 输出PDF路径
        page_range: 要处理的页面范围,格式为 (start, end)
    """
    # 使用上下文管理器打开文件
    with open(input_path, "rb") as infile, open(output_path, "wb") as outfile:
        reader = PdfReader(infile)
        writer = PdfWriter()
        
        # 确定页面范围
        start, end = page_range if page_range else (0, len(reader.pages))
        
        # 逐个处理页面
        for page_num in range(start, end):
            # 只在需要时加载页面
            page = reader.pages[page_num]
            
            # 处理页面(示例:旋转页面)
            page.rotate(90)
            
            # 添加到writer并立即刷新
            writer.add_page(page)
            
            # 定期清理内存(每处理10页)
            if page_num % 10 == 0:
                writer.write(outfile)
                writer = PdfWriter()  # 重置writer,释放内存
        
        # 处理剩余页面
        if writer.pages:
            writer.write(outfile)
    
    print(f"已处理 {end - start} 页,内存使用优化完成")

# 使用示例
if __name__ == "__main__":
    # 处理大型PDF的1-100页
    memory_efficient_pdf_processing("large_document.pdf", "processed_large.pdf", (0, 100))

性能优化技巧

  1. 避免一次性加载所有页面:使用迭代方式逐个处理
  2. 定期刷新输出:每处理一定数量页面就写入磁盘并重置writer
  3. 使用低内存模式:设置strict=False处理非标准PDF
    reader = PdfReader(input_path, strict=False)
    
  4. 释放资源:处理完页面后显式删除引用
    del page  # 帮助垃圾回收
    

综合实战项目:PDF文档自动化处理系统

项目概述

本项目实现一个功能全面的PDF自动化处理系统,能够批量完成PDF合并、水印添加、文本提取、页面旋转和加密保护等操作。系统支持命令行界面和配置文件两种使用方式,适合处理大量PDF文档。

项目结构

pdf_processor/
├── main.py              # 主程序入口
├── pdf_processor.py     # PDF处理核心类
├── config.yaml          # 配置文件
├── input/               # 输入PDF目录
├── output/              # 输出目录
└── logs/                # 日志目录

核心代码实现

import os
import yaml
import logging
import argparse
from datetime import datetime
from pypdf import PdfReader, PdfWriter, PdfMerger

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('logs/pdf_processor.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

class PDFProcessor:
    """PDF文档自动化处理类"""
    
    def __init__(self, config):
        """初始化处理器
        
        参数:
            config: 配置字典
        """
        self.config = config
        self.input_dir = config.get('input_dir', 'input')
        self.output_dir = config.get('output_dir', 'output')
        
        # 创建必要的目录
        os.makedirs(self.input_dir, exist_ok=True)
        os.makedirs(self.output_dir, exist_ok=True)
        os.makedirs('logs', exist_ok=True)
        
    def get_pdf_files(self, directory=None, recursive=False):
        """获取目录中的所有PDF文件
        
        参数:
            directory: 目录路径,默认为输入目录
            recursive: 是否递归查找
            
        返回:
            PDF文件路径列表
        """
        directory = directory or self.input_dir
        pdf_files = []
        
        if recursive:
            for root, _, files in os.walk(directory):
                for file in files:
                    if file.lower().endswith('.pdf'):
                        pdf_files.append(os.path.join(root, file))
        else:
            for file in os.listdir(directory):
                if file.lower().endswith('.pdf'):
                    pdf_files.append(os.path.join(directory, file))
                    
        logger.info(f"找到 {len(pdf_files)} 个PDF文件")
        return pdf_files
    
    def merge_pdfs(self, output_filename, pdf_files=None, **kwargs):
        """合并PDF文件
        
        参数:
            output_filename: 输出文件名
            pdf_files: 要合并的PDF文件列表,None则合并输入目录所有PDF
            **kwargs: 其他参数
        """
        try:
            merger = PdfMerger()
            pdf_files = pdf_files or self.get_pdf_files()
            
            if not pdf_files:
                logger.warning("没有要合并的PDF文件")
                return False
                
            # 添加PDF文件
            for pdf_file in pdf_files:
                merger.append(pdf_file)
                logger.info(f"添加文件: {os.path.basename(pdf_file)}")
            
            # 输出路径
            output_path = os.path.join(self.output_dir, output_filename)
            
            # 写入合并结果
            merger.write(output_path)
            merger.close()
            
            logger.info(f"成功合并 {len(pdf_files)} 个PDF到 {output_path}")
            return output_path
            
        except Exception as e:
            logger.error(f"合并PDF失败: {str(e)}", exc_info=True)
            return False
    
    def add_watermark(self, input_path, output_path, watermark_text, **kwargs):
        """添加水印到PDF
        
        参数:
            input_path: 输入PDF路径
            output_path: 输出PDF路径
            watermark_text: 水印文本
            **kwargs: 水印参数(opacity, rotation等)
        """
        try:
            reader = PdfReader(input_path)
            writer = PdfWriter()
            
            # 水印配置
            opacity = kwargs.get('opacity', 0.3)
            rotation = kwargs.get('rotation', 45)
            font_size = kwargs.get('font_size', 48)
            
            for page in reader.pages:
                # 添加水印逻辑(参考前面的水印实现)
                # ...
                
                writer.add_page(page)
            
            # 保存结果
            with open(output_path, "wb") as f:
                writer.write(f)
                
            logger.info(f"已为 {os.path.basename(input_path)} 添加水印")
            return True
            
        except Exception as e:
            logger.error(f"添加水印失败: {str(e)}", exc_info=True)
            return False
    
    def process_batch(self):
        """执行批量处理任务"""
        tasks = self.config.get('tasks', [])
        
        if not tasks:
            logger.warning("配置文件中没有定义任务")
            return
            
        logger.info(f"开始执行 {len(tasks)} 个处理任务")
        
        for task in tasks:
            task_name = task.get('name', f"task_{datetime.now().strftime('%Y%m%d%H%M%S')}")
            task_type = task.get('type')
            
            logger.info(f"执行任务: {task_name} ({task_type})")
            
            try:
                if task_type == 'merge':
                    output_filename = task.get('output', f"merged_{datetime.now().strftime('%Y%m%d%H%M%S')}.pdf")
                    self.merge_pdfs(output_filename, **task.get('params', {}))
                    
                elif task_type == 'watermark':
                    pdf_files = self.get_pdf_files(task.get('input_dir'))
                    output_dir = os.path.join(self.output_dir, task.get('output_dir', 'watermarked'))
                    os.makedirs(output_dir, exist_ok=True)
                    
                    for pdf_file in pdf_files:
                        filename = os.path.basename(pdf_file)
                        output_path = os.path.join(output_dir, filename)
                        self.add_watermark(pdf_file, output_path, **task.get('params', {}))
                        
                elif task_type == 'encrypt':
                    # 加密任务实现
                    pass
                    
                else:
                    logger.warning(f"未知任务类型: {task_type}")
                    
            except Exception as e:
                logger.error(f"任务 {task_name} 执行失败: {str(e)}", exc_info=True)
                
        logger.info("批量处理任务完成")

def main():
    """主函数"""
    # 解析命令行参数
    parser = argparse.ArgumentParser(description='PDF自动化处理系统')
    parser.add_argument('-c', '--config', default='config.yaml', help='配置文件路径')
    args = parser.parse_args()
    
    # 加载配置文件
    try:
        with open(args.config, 'r') as f:
            config = yaml.safe_load(f)
            logger.info(f"成功加载配置文件: {args.config}")
    except Exception as e:
        logger.error(f"加载配置文件失败: {str(e)}", exc_info=True)
        return
    
    # 创建处理器并执行任务
    processor = PDFProcessor(config)
    processor.process_batch()

if __name__ == "__main__":
    main()

配置文件示例 (config.yaml)

input_dir: input
output_dir: output

tasks:
  - name: merge_monthly_reports
    type: merge
    params:
      output: monthly_report_2023.pdf
      
  - name: add_confidential_watermark
    type: watermark
    input_dir: output
    output_dir: watermarked
    params:
      watermark_text: "CONFIDENTIAL"
      opacity: 0.2
      rotation: 45

使用说明

  1. 准备工作

    • 创建input目录并放入待处理的PDF文件
    • 安装依赖:pip install pypdf pyyaml
  2. 运行程序

    python main.py -c config.yaml
    
  3. 查看结果

    • 处理后的文件保存在output目录
    • 日志文件保存在logs目录

拓展学习资源

  1. 官方文档PyPDF官方文档 - 详细了解PyPDF的所有功能和API
  2. 测试案例测试套件 - 通过实际测试用例学习最佳实践
  3. 高级教程开发者文档 - 深入了解PDF格式和PyPDF内部实现

通过本指南的学习,您已经掌握了使用PyPDF进行Python PDF处理的核心技术和最佳实践。无论是日常文档处理还是复杂的PDF自动化任务,PyPDF都能提供高效可靠的解决方案。继续探索和实践,您将能够构建更加强大的PDF处理应用。

登录后查看全文
热门项目推荐
相关项目推荐