Python之PDF小工具

Python之PDF小工具

【穷鬼套餐(买不起WPS会员)】这是一个多功能工具,既可以将EPUB电子书转换为PDF格式,也可以对现有的PDF文件进行拆分。代码仓库:https://gitee.com/enzoism/python_epub_to_pdf.git

1-epub_to_pdf

python 复制代码
#!/usr/bin/env python3
"""
epub_to_pdf.py
ebooklib>=0.20、weasyprint>=66.0 实测通过
"""

import os
import sys
import ebooklib
from ebooklib import epub
from weasyprint import HTML
from weasyprint.text.fonts import FontConfiguration


def convert_epub_to_pdf(src_epub: str, dst_pdf: str | None = None) -> str | None:
    """把单个 epub 转 pdf,返回输出文件路径;失败返回 None"""
    try:
        book = epub.read_epub(src_epub)
        html_parts = []

        for item in book.get_items():
            if item.get_type() == ebooklib.ITEM_DOCUMENT:
                html_parts.append(item.get_content().decode('utf-8', errors='ignore'))

        if not html_parts:
            raise ValueError('文档不包含可解析章节')

        # 拼成完整 HTML
        full_html = f"""
        <!DOCTYPE html>
        <html>
        <head>
        <meta charset="utf-8">
        <style>
          body {{
            font-family: "PingFang SC", "Helvetica Neue", "Arial", sans-serif;
            line-height: 1.6;
          }}
        </style>
        </head>
        <body>{''.join(html_parts)}</body>
        </html>
        """

        if dst_pdf is None:
            out_dir = os.path.join('.', 'pdf')
            os.makedirs(out_dir, exist_ok=True)
            title = os.path.splitext(os.path.basename(src_epub))[0]
            dst_pdf = os.path.join(out_dir, f"{title}.pdf")

        HTML(string=full_html).write_pdf(dst_pdf, font_config=FontConfiguration())
        print(f"✅ 成功:{dst_pdf}")
        return dst_pdf
    except Exception as e:
        print(f"❌ 失败:{src_epub}\n原因:{e}")
        return None


def main(target):
    if os.path.isfile(target) and target.lower().endswith('.epub'):
        convert_epub_to_pdf(target)
    elif os.path.isdir(target):
        epub_files = [f for f in os.listdir(target) if f.lower().endswith('.epub')]
        if not epub_files:
            print('📂 该目录下没有 epub 文件')
            return
        for f in epub_files:
            convert_epub_to_pdf(os.path.join(target, f))

# ----------------------------
# 脚本入口
# ----------------------------
if __name__ == '__main__':
    # if len(sys.argv) != 2:
    #     print('用法:python epub_to_pdf.py <epub文件或文件夹路径>')
    #     sys.exit(1)
    #
    # target = sys.argv[1]
    main("/Users/rong/Documents/09-深度学习/epub_book")

2-epub_to_pdf

python 复制代码
#!/usr/bin/env python3
"""
epub_to_pdf.py
ebooklib>=0.20、weasyprint>=66.0 实测通过
"""

import sys
import os

# 添加PyPDF2库用于PDF操作
try:
    import PyPDF2

    PDF_LIBRARY_AVAILABLE = True
except ImportError:
    PyPDF2 = None
    PDF_LIBRARY_AVAILABLE = False


def split_pdf(input_pdf_path: str, output_pdf_path: str, pdf_file_name: str, start_page: int, end_page: int) -> bool:
    """按指定页码范围拆分PDF文件"""
    if not PDF_LIBRARY_AVAILABLE:
        print("❌ 错误:缺少PyPDF2库,请安装PyPDF2")
        return False

    try:
        with open(input_pdf_path + pdf_file_name, 'rb') as infile:
            reader = PyPDF2.PdfReader(infile)
            writer = PyPDF2.PdfWriter()

            # 检查页码范围是否有效
            total_pages = len(reader.pages)
            if start_page < 1 or end_page > total_pages or start_page > end_page:
                print(f"❌ 错误:页码范围无效。总页数: {total_pages},请求范围: {start_page}-{end_page}")
                return False

            # 提取指定页面
            for i in range(start_page - 1, end_page):  # 页码从0开始索引
                writer.add_page(reader.pages[i])

            # 确保输出目录存在
            os.makedirs(output_pdf_path, exist_ok=True)

            # 写入新文件
            output_file_name = output_pdf_path + str(start_page) + "_" + str(end_page) + "_" + pdf_file_name
            with open(output_file_name, 'wb') as outfile:
                writer.write(outfile)

            print(f"✅ 成功拆分PDF: {input_pdf_path} 的第 {start_page}-{end_page} 页已保存到 {output_file_name}")
            return True
    except Exception as e:
        print(f"❌ 拆分PDF失败:{e}")
        return False


def main(pdf_file):
    split_pdf(pdf_file, "output.pdf", 1, 10)


# ----------------------------
# 脚本入口
# ----------------------------
if __name__ == '__main__':
    input_pdf_path = "./pdf/"
    output_pdf_path = "./pdf_split/"
    input_pdf_name = "曾国藩传_张宏杰.pdf"
    success = split_pdf(input_pdf_path, output_pdf_path, input_pdf_name, 1, 115)
    success = split_pdf(input_pdf_path, output_pdf_path, input_pdf_name, 115, 206)
    success = split_pdf(input_pdf_path, output_pdf_path, input_pdf_name, 206, 338)
    sys.exit(0 if success else 1)

3-项目说明

功能特性

  1. EPUB转PDF转换器
  2. PDF文件按页码范围拆分

安装依赖

bash 复制代码
pip install -r requirements.txt

或者使用uv:

bash 复制代码
uv pip install -r .

使用方法

EPUB转PDF

bash 复制代码
python main.py <epub文件或文件夹路径>

示例:

bash 复制代码
# 转换单个EPUB文件
python main.py books/example.epub

# 转换目录下的所有EPUB文件
python main.py books/

拆分PDF文件

bash 复制代码
python main.py split <输入PDF文件> <输出PDF文件> <起始页码> <结束页码>

示例:

bash 复制代码
# 拆分PDF的第5页到第10页
python main.py split input.pdf output.pdf 5 10

依赖库

  • ebooklib: 处理EPUB文件
  • weasyprint: 将HTML转换为PDF
  • PyPDF2: 操作PDF文件
相关推荐
代码栈上的思考2 小时前
MyBatis——动态SQL讲解
java·开发语言·数据库
achi0102 小时前
从 0 到 1 掌握 Gunicorn:让 Python Web 应用飞起来的 WSGI 服务器
python·flask·性能调优·容器化·gunicorn·wsgi·并发模型
王柏龙2 小时前
c# aggregate使用
开发语言·c#
小鸡吃米…2 小时前
Python - 构造函数
开发语言·python
moonquakeTT2 小时前
C++:智能指针
开发语言·c++
hoiii1872 小时前
基于MATLAB实现无监督数据建模
开发语言·matlab
Lenyiin2 小时前
第 97 场周赛:公平的糖果交换、查找和替换模式、根据前序和后序遍历构造二叉树、子序列宽度之和
java·c++·python·leetcode·周赛·lenyiin
znhy_232 小时前
day42打卡
python
SCBAiotAigc2 小时前
在Ubuntu上使用docker compose安装普通(不支持GPU)的Ollama服务
人工智能·python·ubuntu·ollama