You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Img2Pdf时因os.scandir排序问题导致PDF图片顺序错误

修复子文件夹自然排序问题

问题根源

os.scandir()返回的目录条目是无序的,默认按系统底层存储顺序返回,而非自然数字排序,导致数字命名的子文件夹(如1、10、100)出现顺序错乱。

修改后的代码

import os
import img2pdf
import re
from typing import List, Tuple

def convert_images_to_pdf(image_paths: List[str], pdf_path: str) -> None:
    """
    将图片列表转换为单个PDF文件
    参数:
        image_paths: 待转换图片的路径列表
        pdf_path: 输出PDF的路径
    返回:
        None,生成成功或报错时打印信息
    """
    try:
        with open(pdf_path, 'wb') as pdf_file:
            pdf_file.write(img2pdf.convert(image_paths))
        print(f"PDF已成功生成: {pdf_path}")
    except (ValueError, FileNotFoundError) as error:
        print(f"生成PDF时出错: {error}")

def natural_sort_key(s):
    """生成自然排序的键,处理带数字的字符串"""
    return [int(text) if text.isdigit() else text.lower() for text in re.split('([0-9]+)', s)]

def create_folder_pdf(folder_path: str) -> None:
    """
    将指定文件夹下所有子文件夹的JPEG图片转换为对应PDF
    参数:
        folder_path: 包含图片的根文件夹路径
    返回:
        None,无图片或出错时打印信息
    """
    try:
        # 读取子文件夹并按自然顺序排序
        with os.scandir(folder_path) as folder_iterator:
            subfolders = sorted([item for item in folder_iterator if item.is_dir()], 
                               key=lambda x: natural_sort_key(x.name))
            
            for item in subfolders:
                subfolder_name = item.name
                subfolder_path = os.path.join(folder_path, subfolder_name)
                image_paths = []
                
                # 读取子文件夹内的图片并按自然顺序排序
                with os.scandir(subfolder_path) as file_iterator:
                    image_files = sorted([file for file in file_iterator 
                                         if file.name.lower().endswith(('.jpeg', '.jpg'))],
                                        key=lambda x: natural_sort_key(x.name))
                    image_paths = [file.path for file in image_files]
                
                if image_paths:
                    pdf_path = os.path.join(subfolder_path, f'{subfolder_name}.pdf')
                    convert_images_to_pdf(image_paths, pdf_path)
                else:
                    print(f"{subfolder_name}中未找到JPEG文件!")
    except OSError as error:
        print(f"打开文件夹出错: {folder_path}, 错误信息: {error}")
        return

if __name__ == "__main__":
    folder_path = input("请输入包含JPEG图片的文件夹路径: ")
    
    if not os.path.exists(folder_path):
        print(f"路径不存在: {folder_path}")
    else:
        create_folder_pdf(folder_path)

关键修改说明

  • 新增natural_sort_key函数:通过正则拆分字符串中的数字与非数字部分,将数字转为整数后参与排序,实现自然排序逻辑(比如1 < 2 < 10 < 100)
  • 子文件夹排序:从根目录读取子文件夹后,用natural_sort_key作为排序键,确保章节顺序符合预期
  • 图片排序优化:子文件夹内的图片也使用自然排序,避免类似001-10排在001-2前面的问题

补充说明

你提到的PNG转JPEG操作是合理的,截断的PNG在JPEG格式下容错性更强,不会影响后续PDF生成流程。

内容的提问来源于stack exchange,提问作者Matt Bone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 20:04:55