后端

Python获取PDF页数的实现方法与示例

TRAE AI 编程助手

在文档处理、数据分析、自动化办公等场景中,获取PDF文件的总页数是一项基础而重要的操作。无论是批量处理文档、生成目录索引,还是进行文档管理系统的开发,准确快速地获取PDF页数都是不可或缺的技能。

引言:为什么需要获取PDF页数?

在日常开发工作中,我们经常会遇到需要处理PDF文件的场景:

  • 文档管理系统:需要统计每个PDF文档的页数用于展示和分类
  • 批量处理工具:根据页数对PDF进行不同的处理策略
  • 数据分析:分析大量PDF文档的页数分布情况
  • 自动化报告:生成包含页数信息的文档摘要

本文将详细介绍几种主流的Python获取PDF页数的方法,并通过实际代码示例帮助您选择最适合的方案。如果您正在使用TRAE IDE进行Python开发,这些示例代码都可以直接在IDE中运行和调试,TRAE IDE的智能代码补全和实时错误检查功能将大大提升您的开发效率。

方法一:使用PyPDF2库

PyPDF2是最常用的PDF处理库之一,提供了稳定可靠的PDF页数获取功能。

安装PyPDF2

pip install PyPDF2

基础使用示例

import PyPDF2
 
def get_pdf_page_count_pypdf2(file_path):
    """
    使用PyPDF2获取PDF页数
    
    Args:
        file_path (str): PDF文件路径
        
    Returns:
        int: PDF总页数
        
    Raises:
        FileNotFoundError: 文件不存在
        PyPDF2.errors.PdfReadError: PDF文件损坏或加密
    """
    try:
        with open(file_path, 'rb') as file:
            pdf_reader = PyPDF2.PdfReader(file)
            return len(pdf_reader.pages)
    except FileNotFoundError:
        raise FileNotFoundError(f"文件不存在: {file_path}")
    except PyPDF2.errors.PdfReadError as e:
        raise ValueError(f"PDF文件读取错误: {e}")
 
# 使用示例
if __name__ == "__main__":
    try:
        page_count = get_pdf_page_count_pypdf2("example.pdf")
        print(f"PDF文件共有 {page_count} 页")
    except Exception as e:
        print(f"错误: {e}")

处理加密PDF

def get_pdf_page_count_pypdf2_secure(file_path, password=None):
    """
    处理可能加密的PDF文件
    
    Args:
        file_path (str): PDF文件路径
        password (str, optional): PDF密码
        
    Returns:
        int: PDF总页数
    """
    try:
        with open(file_path, 'rb') as file:
            pdf_reader = PyPDF2.PdfReader(file)
            
            # 检查是否加密
            if pdf_reader.is_encrypted:
                if password:
                    if not pdf_reader.decrypt(password):
                        raise ValueError("PDF密码错误")
                else:
                    raise ValueError("PDF文件已加密,需要提供密码")
            
            return len(pdf_reader.pages)
    except Exception as e:
        raise Exception(f"处理PDF时出错: {e}")

方法二:使用pdfplumber库

pdfplumber不仅能够获取页数,还提供了强大的PDF内容提取功能。

安装pdfplumber

pip install pdfplumber

基础使用示例

import pdfplumber
 
def get_pdf_page_count_plumber(file_path):
    """
    使用pdfplumber获取PDF页数
    
    Args:
        file_path (str): PDF文件路径
        
    Returns:
        int: PDF总页数
        
    Raises:
        FileNotFoundError: 文件不存在
        Exception: 其他PDF处理错误
    """
    try:
        with pdfplumber.open(file_path) as pdf:
            return len(pdf.pages)
    except FileNotFoundError:
        raise FileNotFoundError(f"文件不存在: {file_path}")
    except Exception as e:
        raise Exception(f"PDF处理错误: {e}")
 
# 批量处理示例
def batch_count_pages_plumber(file_paths):
    """
    批量获取多个PDF文件的页数
    
    Args:
        file_paths (list): PDF文件路径列表
        
    Returns:
        dict: 文件名与页数的映射
    """
    results = {}
    for file_path in file_paths:
        try:
            page_count = get_pdf_page_count_plumber(file_path)
            results[file_path] = page_count
        except Exception as e:
            results[file_path] = f"错误: {e}"
    
    return results

获取更详细的页面信息

def get_pdf_info_plumber(file_path):
    """
    获取PDF的详细信息
    
    Args:
        file_path (str): PDF文件路径
        
    Returns:
        dict: PDF详细信息
    """
    try:
        with pdfplumber.open(file_path) as pdf:
            info = {
                'page_count': len(pdf.pages),
                'metadata': pdf.metadata,
                'version': pdf.version
            }
            
            # 获取每页的尺寸信息
            page_info = []
            for i, page in enumerate(pdf.pages):
                page_info.append({
                    'page_number': i + 1,
                    'width': page.width,
                    'height': page.height
                })
            
            info['pages'] = page_info
            return info
    except Exception as e:
        raise Exception(f"获取PDF信息失败: {e}")

方法三:使用PyMuPDF库

PyMuPDF(也称为fitz)是功能最强大的PDF处理库之一,性能优异且功能全面。

安装PyMuPDF

pip install PyMuPDF

基础使用示例

import fitz  # PyMuPDF
 
def get_pdf_page_count_mupdf(file_path):
    """
    使用PyMuPDF获取PDF页数
    
    Args:
        file_path (str): PDF文件路径
        
    Returns:
        int: PDF总页数
        
    Raises:
        FileNotFoundError: 文件不存在
        Exception: 其他PDF处理错误
    """
    try:
        doc = fitz.open(file_path)
        page_count = doc.page_count
        doc.close()
        return page_count
    except FileNotFoundError:
        raise FileNotFoundError(f"文件不存在: {file_path}")
    except Exception as e:
        raise Exception(f"PDF处理错误: {e}")
 
# 使用上下文管理器确保安全关闭
def get_pdf_page_count_mupdf_safe(file_path):
    """
    使用上下文管理器安全获取PDF页数
    
    Args:
        file_path (str): PDF文件路径
        
    Returns:
        int: PDF总页数
    """
    try:
        with fitz.open(file_path) as doc:
            return doc.page_count
    except Exception as e:
        raise Exception(f"处理PDF时出错: {e}")

高性能批量处理

def batch_count_pages_mupdf(file_paths, max_workers=4):
    """
    使用多线程批量获取PDF页数(适合大量文件)
    
    Args:
        file_paths (list): PDF文件路径列表
        max_workers (int): 最大工作线程数
        
    Returns:
        dict: 文件名与页数的映射
    """
    import concurrent.futures
    
    def count_single_pdf(file_path):
        try:
            return file_path, get_pdf_page_count_mupdf_safe(file_path)
        except Exception as e:
            return file_path, f"错误: {e}"
    
    results = {}
    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = [executor.submit(count_single_pdf, fp) for fp in file_paths]
        for future in concurrent.futures.as_completed(futures):
            file_path, result = future.result()
            results[file_path] = result
    
    return results

方法对比与选择建议

特性PyPDF2pdfplumberPyMuPDF
安装大小较小中等较大
执行速度中等中等最快
内存占用中等最低
功能丰富度基础丰富丰富
稳定性
加密支持良好良好优秀
依赖数量中等较多
学习成本中等中等

选择建议

  1. 简单项目或只需要页数信息:推荐使用 PyPDF2

    • 安装包小,依赖少
    • API简单直观
    • 稳定性高,社区支持好
  2. 需要提取文本或表格内容:推荐使用 pdfplumber

    • 文本提取能力强
    • 支持表格识别
    • 页面信息丰富
  3. 高性能要求或大量文件处理:推荐使用 PyMuPDF

    • 处理速度最快
    • 内存占用最少
    • 支持多线程处理

错误处理与最佳实践

通用错误处理框架

import logging
from typing import Optional, Union
 
def safe_get_page_count(file_path: str, 
                       method: str = 'auto',
                       password: Optional[str] = None) -> Union[int, str]:
    """
    安全获取PDF页数的通用函数
    
    Args:
        file_path (str): PDF文件路径
        method (str): 使用方法 ('pypdf2', 'plumber', 'mupdf', 'auto')
        password (str, optional): PDF密码
        
    Returns:
        int: 成功时返回页数,失败时返回错误信息
    """
    
    # 配置日志
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger(__name__)
    
    # 验证文件存在
    if not file_path or not file_path.strip():
        return "错误:文件路径不能为空"
    
    import os
    if not os.path.exists(file_path):
        return f"错误:文件不存在 - {file_path}"
    
    # 验证文件扩展名
    if not file_path.lower().endswith('.pdf'):
        logger.warning(f"警告:文件可能不是PDF格式 - {file_path}")
    
    # 自动选择方法
    if method == 'auto':
        methods = ['mupdf', 'pypdf2', 'plumber']
    else:
        methods = [method]
    
    # 尝试不同的方法
    for method_name in methods:
        try:
            if method_name == 'pypdf2':
                import PyPDF2
                with open(file_path, 'rb') as file:
                    reader = PyPDF2.PdfReader(file)
                    if password and reader.is_encrypted:
                        reader.decrypt(password)
                    return len(reader.pages)
                    
            elif method_name == 'plumber':
                import pdfplumber
                with pdfplumber.open(file_path) as pdf:
                    return len(pdf.pages)
                    
            elif method_name == 'mupdf':
                import fitz
                with fitz.open(file_path) as doc:
                    return doc.page_count
                    
        except Exception as e:
            logger.warning(f"方法 {method_name} 失败: {e}")
            continue
    
    return "错误:所有方法都无法处理该PDF文件"
 
# 使用示例
if __name__ == "__main__":
    result = safe_get_page_count("example.pdf", method='auto')
    if isinstance(result, int):
        print(f"PDF页数: {result}")
    else:
        print(result)

性能优化建议

  1. 批量处理时使用多线程:对于大量PDF文件,使用concurrent.futures模块进行并发处理
  2. 缓存结果:对于重复处理的文件,考虑将页数信息缓存到数据库或文件中
  3. 内存管理:使用上下文管理器(with语句)确保文件正确关闭
  4. 异常重试:对于网络文件或临时锁定的文件,可以实现重试机制

在TRAE IDE中开发PDF处理工具

如果您正在使用TRAE IDE进行Python开发,可以充分利用其强大功能:

  1. 智能代码补全:TRAE IDE会根据您导入的库自动补全方法和参数
  2. 实时错误检查:在编写代码时就能发现潜在的错误
  3. 集成终端:可以直接在IDE中安装依赖和运行测试
  4. 调试支持:可以设置断点逐步调试PDF处理逻辑
# TRAE IDE中的完整项目示例
# 文件名:pdf_page_counter.py
 
import os
import sys
from pathlib import Path
from typing import List, Dict
 
class PDFPageCounter:
    """PDF页数统计器"""
    
    def __init__(self, method: str = 'auto'):
        self.method = method
        self.results: Dict[str, int] = {}
    
    def count_pages(self, pdf_path: str) -> int:
        """获取单个PDF的页数"""
        # TRAE IDE会在这里提供代码提示
        result = safe_get_page_count(pdf_path, self.method)
        if isinstance(result, int):
            self.results[pdf_path] = result
            return result
        else:
            raise ValueError(result)
    
    def batch_count(self, folder_path: str) -> Dict[str, int]:
        """批量统计文件夹中的PDF页数"""
        pdf_files = list(Path(folder_path).glob("*.pdf"))
        
        for pdf_file in pdf_files:
            try:
                self.count_pages(str(pdf_file))
            except Exception as e:
                print(f"处理 {pdf_file} 时出错: {e}")
        
        return self.results
    
    def generate_report(self) -> str:
        """生成统计报告"""
        total_files = len(self.results)
        total_pages = sum(self.results.values())
        avg_pages = total_pages / total_files if total_files > 0 else 0
        
        report = f"""
PDF页数统计报告
================
总文件数: {total_files}
总页数: {total_pages}
平均页数: {avg_pages:.1f}
 
详细清单:
"""
        for file_path, pages in self.results.items():
            report += f"- {file_path}: {pages}\n"
        
        return report
 
# 使用示例(可以在TRAE IDE的调试模式中运行)
if __name__ == "__main__":
    counter = PDFPageCounter(method='mupdf')
    
    # 统计单个文件
    try:
        pages = counter.count_pages("document.pdf")
        print(f"文档页数: {pages}")
    except Exception as e:
        print(f"错误: {e}")
    
    # 批量统计
    results = counter.batch_count("./pdf_folder")
    print(counter.generate_report())

总结与建议

获取PDF页数虽然是一个简单的需求,但选择合适的方法可以大大提高开发效率和程序性能。本文介绍了三种主流的Python库:

  • PyPDF2:适合简单场景,轻量级解决方案
  • pdfplumber:适合需要内容提取的复杂场景
  • PyMuPDF:适合高性能要求的专业应用

在实际开发中,建议:

  1. 根据项目需求选择合适的方法,不要盲目追求功能全面
  2. 做好错误处理,PDF文件格式复杂,异常情况较多
  3. 考虑性能优化,特别是批量处理大量文件时
  4. 使用TRAE IDE进行开发,可以显著提高开发效率和代码质量

无论您选择哪种方法,都建议在TRAE IDE中进行开发和测试。TRAE IDE的智能提示、错误检查和调试功能将帮助您更快地开发出稳定可靠的PDF处理工具。记住,好的工具能让开发工作事半功倍!

(此内容由 AI 辅助生成,仅供参考)