Python 实战指南:一键批量旋转 PDF 页面方向

在日常办公、文档处理或自动化流程中,我们经常会遇到 PDF 页面方向错误的问题------比如扫描件横置、部分页面倒置,或者从不同来源合并的 PDF 页向不统一。手动用 Adobe Acrobat 或其他工具逐页调整既耗时又低效。

幸运的是,借助 Python 和开源库 PyPDF2 (或其继任者 pypdf ),我们可以几行代码轻松实现 PDF 页面的自动旋转,甚至支持批量处理!本文将带你从零开始,完成一个实用的 PDF 页面方向调整脚本。


一、准备工作:安装依赖

推荐使用 pypdf(PyPDF2 的现代维护版本,性能更好、API 更清晰):

复制代码
pip install pypdf

💡 注意:如果你仍在使用旧版 PyPDF2,大部分代码也兼容,但建议迁移到 pypdf


二、核心原理:PDF 页面的旋转机制

在 PDF 中,每个页面都有一个 /Rotate 属性,表示顺时针旋转角度,必须是 90 的整数倍(如 0、90、180、270)。

  • 0:正常方向
  • 90:向右旋转 90°(横屏)
  • 180:倒置
  • 270:向左旋转 90°

通过修改该属性,即可无损调整页面显示方向,无需重新渲染图像或内容


三、基础示例:旋转指定页面

以下代码将 PDF 的第 1 页(索引 0)顺时针旋转 90°:

python 复制代码
from pypdf import PdfReader, PdfWriter

def rotate_page(input_pdf, output_pdf, page_number, rotation=90):
    reader = PdfReader(input_pdf)
    writer = PdfWriter()

    for i, page in enumerate(reader.pages):
        if i == page_number:
            page.rotate(rotation)  # 旋转角度(90, 180, 270)
        writer.add_page(page)

    with open(output_pdf, "wb") as f:
        writer.write(f)

# 使用示例:旋转第1页(索引0)90度
rotate_page("input.pdf", "output_rotated.pdf", page_number=0, rotation=90)

page.rotate() 会累加旋转角度。若页面原本是 90°,再调用 rotate(90) 将变为 180°。

如需强制设为某个方向 ,可先重置为 0:page.rotate(-page.get("/Rotate", 0)),再设置新值。


四、进阶实战:批量处理所有页面

场景 1:将整个 PDF 所有页面统一旋转 180°(如全部倒置的扫描件)

scss 复制代码
def rotate_all_pages(input_pdf, output_pdf, rotation=180):
    reader = PdfReader(input_pdf)
    writer = PdfWriter()

    for page in reader.pages:
        page.rotate(rotation)
        writer.add_page(page)

    with open(output_pdf, "wb") as f:
        writer.write(f)

rotate_all_pages("scanned.pdf", "corrected.pdf", rotation=180)

场景 2:智能检测并修正"横置"页面(假设奇数页应为纵向,偶数页为横向)

ini 复制代码
def smart_rotate_by_index(input_pdf, output_pdf):
    reader = PdfReader(input_pdf)
    writer = PdfWriter()

    for i, page in enumerate(reader.pages):
        if i % 2 == 1:  # 偶数页(索引从0开始)
            # 如果当前未旋转,则设为90度
            current_rot = page.get("/Rotate", 0)
            if current_rot == 0:
                page.rotate(90)
        writer.add_page(page)

    with open(output_pdf, "wb") as f:
        writer.write(f)

五、实用工具函数:命令行调用

将脚本封装为命令行工具,方便日常使用:

python 复制代码
# pdf_rotate.py
import argparse
from pypdf import PdfReader, PdfWriter

def main():
    parser = argparse.ArgumentParser(description="旋转 PDF 页面方向")
    parser.add_argument("input", help="输入 PDF 文件路径")
    parser.add_argument("output", help="输出 PDF 文件路径")
    parser.add_argument("--angle", type=int, default=90, choices=[90, 180, 270], help="旋转角度")
    parser.add_argument("--page", type=int, help="指定页码(从1开始),不填则旋转所有页")

    args = parser.parse_args()

    reader = PdfReader(args.input)
    writer = PdfWriter()

    for i, page in enumerate(reader.pages):
        if args.page is None or i == args.page - 1:
            page.rotate(args.angle)
        writer.add_page(page)

    with open(args.output, "wb") as f:
        writer.write(f)

    print(f"✅ 已保存至: {args.output}")

if __name__ == "__main__":
    main()

使用方式:

lua 复制代码
# 旋转第3页 270度
python pdf_rotate.py input.pdf output.pdf --page 3 --angle 270

# 全部页面旋转180度
python pdf_rotate.py input.pdf output.pdf --angle 180

六、注意事项与局限

  1. 仅修改元数据,不重绘内容:旋转是"视图级"操作,不影响原始文本或图像数据。
  2. 角度必须是 90 的倍数 :否则 rotate() 会报错。
  3. 加密 PDF 需先解密pypdf 支持读取带密码的 PDF(reader.decrypt("password")),但无法修改加密文件。
  4. 保留书签与注释 :上述方法默认会丢失书签(outlines)。如需保留,需额外处理(writer.add_outline_item())。

结语

通过 Python + pypdf,我们不仅解决了 PDF 页面方向问题,还构建了一个可复用、可扩展的文档处理工具。无论是个人整理资料,还是集成到企业自动化流程中,这类脚本都能显著提升效率。

🌟 小提示 :结合 watchdog 库,你甚至可以实现"监控文件夹,自动修正新放入的 PDF 方向"!

从此,再也不用手动一页页拖拽旋转------让代码为你打工!

相关推荐
喜欢流萤吖~1 小时前
微服务架构解析:从单体到分布式
spring boot·后端
小江的记录本1 小时前
【分布式】分布式核心组件——分布式锁:Redis/ZooKeeper/etcd 实现方案(附全方位对比表)、优缺点、Redlock、时钟回拨问题
java·网络·redis·分布式·后端·zookeeper·架构
小江的记录本1 小时前
【分布式】分布式核心组件——分布式ID生成:雪花算法、号段模式、美团Leaf、百度UidGenerator、时钟回拨解决方案
分布式·后端·算法·缓存·性能优化·架构·系统架构
GetcharZp8 小时前
拒绝低效!这款神器,让你的终端效率起飞 | 深度解析 fzf 终极指南
后端
自珍JAVA8 小时前
高效处理Long列表与集合运算:基于RoaringBitmap的工具类解析与应用场景
后端
小码哥_常9 小时前
Spring Boot项目上线秘籍:日志、监控、异常处理全攻略
后端
GreenTea9 小时前
AI 时代,工程师的不可替代性在哪里
前端·人工智能·后端
朦胧之9 小时前
AI 编程开发思维
前端·后端·ai编程
希望永不加班11 小时前
Spring AOP 代理模式:CGLIB 与 JDK 动态代理区别
java·开发语言·后端·spring·代理模式
浮游本尊12 小时前
一次合同同步背后的多阶段流水线:从外部主数据到本地歧义消解
后端