2025-03-31 09:59:30 +00:00
|
|
|
|
import os
|
2025-04-02 08:36:17 +00:00
|
|
|
|
import asyncio
|
2025-03-31 09:59:30 +00:00
|
|
|
|
import zipfile
|
2025-04-02 08:36:17 +00:00
|
|
|
|
from pathlib import Path
|
2025-03-31 09:59:30 +00:00
|
|
|
|
from PIL import Image
|
|
|
|
|
|
from natsort import natsorted
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def webp_to_pdf(input_folder, output_pdf):
|
|
|
|
|
|
"""
|
|
|
|
|
|
WebP转PDF
|
|
|
|
|
|
"""
|
|
|
|
|
|
webp_files = natsorted(
|
|
|
|
|
|
[os.path.join(input_folder, f) for f in os.listdir(input_folder)
|
|
|
|
|
|
if f.lower().endswith('.webp')],
|
|
|
|
|
|
key=lambda x: os.path.basename(x)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if not webp_files:
|
|
|
|
|
|
print("未找到WebP图片")
|
|
|
|
|
|
|
|
|
|
|
|
images = []
|
|
|
|
|
|
for webp_file in webp_files:
|
|
|
|
|
|
try:
|
|
|
|
|
|
img = Image.open(webp_file)
|
|
|
|
|
|
# 处理透明背景
|
|
|
|
|
|
if img.mode in ('RGBA', 'LA'):
|
|
|
|
|
|
white_bg = Image.new('RGB', img.size, (255, 255, 255))
|
|
|
|
|
|
white_bg.paste(img, mask=img.split()[-1])
|
|
|
|
|
|
images.append(white_bg)
|
|
|
|
|
|
else:
|
|
|
|
|
|
images.append(img.convert('RGB'))
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"处理失败 {webp_file}: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
if not images:
|
|
|
|
|
|
print("无有效图片")
|
|
|
|
|
|
|
|
|
|
|
|
images[0].save(
|
|
|
|
|
|
output_pdf,
|
|
|
|
|
|
save_all=True,
|
|
|
|
|
|
append_images=images[1:],
|
|
|
|
|
|
optimize=True,
|
2025-04-02 08:36:17 +00:00
|
|
|
|
quality=80
|
2025-03-31 09:59:30 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2025-04-02 08:36:17 +00:00
|
|
|
|
async def batch_convert_subfolders(base_dir,output_dir):
|
|
|
|
|
|
"""
|
|
|
|
|
|
批量转换指定目录下所有子文件夹中的WebP图片为独立PDF
|
|
|
|
|
|
:param base_dir: 要扫描的根目录,默认当前目录
|
|
|
|
|
|
:param output_dir: PDF输出目录
|
|
|
|
|
|
"""
|
|
|
|
|
|
subfolders = [
|
|
|
|
|
|
f for f in os.listdir(base_dir)
|
|
|
|
|
|
if os.path.isdir(os.path.join(base_dir, f))
|
|
|
|
|
|
and not f.startswith('.')
|
|
|
|
|
|
and f != os.path.basename(output_dir)
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
if not subfolders:
|
|
|
|
|
|
print("未找到有效子文件夹")
|
|
|
|
|
|
return
|
2025-03-31 09:59:30 +00:00
|
|
|
|
|
2025-04-02 08:36:17 +00:00
|
|
|
|
tasks = []
|
|
|
|
|
|
for folder in subfolders:
|
|
|
|
|
|
input_path = os.path.join(base_dir, folder)
|
|
|
|
|
|
output_pdf = os.path.join(output_dir, f"{folder}.pdf")
|
|
|
|
|
|
tasks.append(
|
|
|
|
|
|
webp_to_pdf(input_path, output_pdf)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
results = await asyncio.gather(*tasks, return_exceptions=True)
|
|
|
|
|
|
success = 0
|
|
|
|
|
|
for folder, result in zip(subfolders, results):
|
|
|
|
|
|
if isinstance(result, Exception):
|
|
|
|
|
|
print(f"转换失败 [{folder}]: {str(result)}")
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f"成功转换: {folder} -> {result}")
|
|
|
|
|
|
success += 1
|
2025-03-31 09:59:30 +00:00
|
|
|
|
|
|
|
|
|
|
async def zip_pdf(pdf_path, zip_path):
|
2025-04-02 08:36:17 +00:00
|
|
|
|
"""
|
|
|
|
|
|
压缩单文件
|
|
|
|
|
|
"""
|
2025-03-31 09:59:30 +00:00
|
|
|
|
try:
|
|
|
|
|
|
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
|
|
|
|
|
arcname = os.path.basename(pdf_path)
|
|
|
|
|
|
zipf.write(pdf_path, arcname=arcname)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"压缩PDF时出错: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def merge_files(jpg_path, zip_path, output_path):
|
2025-04-02 08:36:17 +00:00
|
|
|
|
"""
|
|
|
|
|
|
将PDF伪装成图片
|
|
|
|
|
|
"""
|
2025-03-31 09:59:30 +00:00
|
|
|
|
try:
|
|
|
|
|
|
with open(jpg_path, 'rb') as jpg_file, open(zip_path, 'rb') as zip_file, open(output_path,'wb') as output_file:
|
|
|
|
|
|
output_file.write(jpg_file.read())
|
|
|
|
|
|
output_file.write(zip_file.read())
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"合并文件时出错: {e}")
|
2025-04-02 08:36:17 +00:00
|
|
|
|
|
|
|
|
|
|
async def folder_zip(folder_path, jm_zip_path):
|
|
|
|
|
|
"""
|
|
|
|
|
|
异步压缩整个文件夹到指定路径
|
|
|
|
|
|
:param folder_path: 需要压缩的文件夹路径
|
|
|
|
|
|
:param jm_zip_path: 输出的zip文件路径
|
|
|
|
|
|
:return: 压缩成功返回True,否则返回False
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
Path(jm_zip_path).parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
|
|
|
|
|
|
|
def sync_zip():
|
|
|
|
|
|
with zipfile.ZipFile(jm_zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
|
|
|
|
|
|
|
|
|
|
|
|
for root, dirs, files in os.walk(folder_path):
|
|
|
|
|
|
|
|
|
|
|
|
relative_path = Path(root).relative_to(folder_path)
|
|
|
|
|
|
|
|
|
|
|
|
for dir_name in dirs:
|
|
|
|
|
|
abs_dir = os.path.join(root, dir_name)
|
|
|
|
|
|
zipf.write(abs_dir, arcname=str(relative_path / dir_name))
|
|
|
|
|
|
|
|
|
|
|
|
for file in files:
|
|
|
|
|
|
file_path = os.path.join(root, file)
|
|
|
|
|
|
arcname = str(relative_path / file)
|
|
|
|
|
|
zipf.write(file_path, arcname=arcname)
|
|
|
|
|
|
|
|
|
|
|
|
loop = asyncio.get_running_loop()
|
|
|
|
|
|
await loop.run_in_executor(None, sync_zip)
|
|
|
|
|
|
print(f"成功压缩文件夹到: {jm_zip_path}")
|
|
|
|
|
|
return True
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
print(f"压缩文件夹失败: {str(e)}")
|
|
|
|
|
|
return False
|