交互式菜单选择版: 运行脚本后,它会自动列出当前目录下的所有 PDF 文件并标上序号,如果只有 1 个就直接选中;如果有多个,你只需敲对应的数字编号即可,省去手打文件名的麻烦,且不会误处理无关文件。
交互选择版脚本:auto_unimpose.py
import copy
import glob
import os
import sys
from pypdf import PdfReader, PdfWriter
def select_pdf_file():
"""扫描当前目录下的 PDF,列出菜单供用户选择"""
# 查找所有 pdf,排除之前生成的成果文件
pdf_files = [
f
for f in glob.glob("*.pdf")
if not f.endswith("_A4_顺序版.pdf") and not f.startswith("output_")
]
if not pdf_files:
print("[!] 错误:当前目录下没有找到任何待处理的 PDF 文件!")
sys.exit(1)
# 如果恰好只有 1 个文件,直接默认选中
if len(pdf_files) == 1:
print(f"[*] 发现唯一待处理文件: {pdf_files[0]}")
return pdf_files[0]
# 存在多个文件时,按修改时间降序排序并展示列表
pdf_files.sort(key=lambda x: os.path.getmtime(x), reverse=True)
print("=" * 45)
print("请选择要处理的试卷 PDF 文件(输入序号):")
for idx, fname in enumerate(pdf_files, 1):
print(f" [{idx}] {fname}")
print("=" * 45)
while True:
choice = input(f"请输入数字序号 (1-{len(pdf_files)}),或按 'q' 退出: ").strip()
if choice.lower() == "q":
print("已取消操作。")
sys.exit(0)
if choice.isdigit():
val = int(choice)
if 1 <= val <= len(pdf_files):
selected = pdf_files[val - 1]
print(f"[*] 已选择: {selected}")
return selected
print("[!] 输入无效,请重新输入正确的数字。")
def run_unimpose():
input_pdf_path = select_pdf_file()
base_name = os.path.splitext(input_pdf_path)[0]
output_pdf_path = f"{base_name}_A4_顺序版.pdf"
reader = PdfReader(input_pdf_path)
writer = PdfWriter()
total_sheets = len(reader.pages)
if total_sheets == 0:
print("[!] 错误:该 PDF 没有任何页面!")
return
N = total_sheets * 2 # 自动推导总单页容量
print(
f"[*] 页面统计:共 {total_sheets} 个 B4 大面,切分后对应 {N} 页"
" A4。"
)
pages_dict = {}
for idx, page in enumerate(reader.pages):
rect = page.mediabox
width = float(rect.width)
height = float(rect.height)
mid_x = width / 2
# 1. 裁剪左半页
left_page = copy.copy(page)
left_page.mediabox = copy.copy(rect)
left_page.mediabox.upper_right = (mid_x, height)
# 2. 裁剪右半页
right_page = copy.copy(page)
right_page.mediabox = copy.copy(rect)
right_page.mediabox.lower_left = (mid_x, 0)
# 3. 骑马钉解拼数学映射
# idx 从 0 开始:
# 偶数面 (正面): 左 = N - idx, 右 = 1 + idx
# 奇数面 (反面): 左 = 1 + idx, 右 = N - idx
if idx % 2 == 0:
p_left = N - idx
p_right = 1 + idx
else:
p_left = 1 + idx
p_right = N - idx
pages_dict[p_left] = left_page
pages_dict[p_right] = right_page
# 4. 按 1 ~ N 顺序写入新文件
print("[*] 正在按页码重新装订排序...")
for p_num in sorted(pages_dict.keys()):
writer.add_page(pages_dict[p_num])
with open(output_pdf_path, "wb") as f:
writer.write(f)
print(f"[✓] 全部完成!生成文件已保存在同目录:\n -> {output_pdf_path}")
if __name__ == "__main__":
run_unimpose()
终端运行效果演示
如果有多个 PDF,运行 python auto_unimpose.py 时终端会弹出:
=============================================
请选择要处理的试卷 PDF 文件(输入序号):
[1] 2024届模拟考试试卷_数学.pdf
[2] 语文期末测试B4扫描.pdf
[3] 英语强化试题.pdf
=============================================
请输入数字序号 (1-3),或按 'q' 退出: 1
[*] 已选择: 2024届模拟考试试卷_数学.pdf
[*] 页面统计:共 32 个 B4 大面,切分后对应 64 页 A4。
[*] 正在按页码重新装订排序...
[✓] 全部完成!生成文件已保存在同目录:
-> 2024届模拟考试试卷_数学_A4_顺序版.pdf
如果目录下正好只有一个待处理的 PDF,它会自动直接执行,不再多问一步。
