【Python】PyPandoc:批量文件格式转换

Pandoc 是一个强大的文档转换工具,它可以将各种标记语言(如 Markdown、HTML、LaTeX)转换为不同的格式(如 PDF、DOCX、EPUB 等)。Pandoc 支持多种输入和输出格式,并允许用户添加自定义样式、模板和过滤器。

Pandoc 的主要功能

  • 格式转换:将不同的标记语言转换为多种输出格式。最常见的格式包括 Markdown、HTML、LaTeX、PDF、DOCX、EPUB 等。
  • 样式和模板支持:Pandoc 允许使用自定义的 CSS 样式或 LaTeX 模板来控制输出的外观。
  • 自动生成目录:可以根据文档结构自动生成目录。
  • 代码高亮:支持将代码块转换为带有高亮显示的格式,适用于技术文档。

Pandoc下载与使用

Pandoc 的安装

  • Windows
    可以通过 Pandoc 官方网站 下载 Windows 安装包,安装后会自动将 Pandoc 添加到系统路径中。

  • Linux
    在大多数 Linux 发行版中,可以通过包管理器安装 Pandoc:

    sudo apt install pandoc  # 对于基于 Debian/Ubuntu 的系统
    sudo dnf install pandoc  # 对于基于 Fedora 的系统
    
  • macOS
    使用 Homebrew 安装:

    brew install pandoc
    

Pandoc 的基本用法

Pandoc 的使用非常灵活,主要通过命令行进行操作。其基本命令如下:

pandoc [输入文件] -o [输出文件] [选项]
  • -o [filename]:指定输出文件。
  • --toc:生成目录(table of contents)。
  • --highlight-style [style]:指定代码块的高亮风格,style 可以是 pygmentskate 等。
  • --standalone-s:生成独立文件,比如在 HTML 中,包含完整的 标签。

目标文件为PDF

使用 Pandoc 将文件转换为 PDF 时,特别是涉及中文支持和复杂排版的情况,需要进行一些特殊的准备工作。以下是具体步骤:

  • Pandoc 本身不能直接输出 PDF,它依赖 LaTeX 来生成 PDF 文件。因此,需要安装 Pandoc 和 LaTeX。
  • 推荐安装一个完整的 LaTeX 发行版,例如:TeX Live
  • 【操作与配置】基于Tex Live的VS Code编写LaTex-CSDN博客

使用自定义模板

Pandoc 允许用户通过模板定义生成文件的格式和样式。以 LaTeX PDF 为例,用户可以自定义 LaTeX 模板来控制输出 PDF 的样式。

使用 LaTeX 模板
  1. 创建自定义模板 template.tex,并在其中定义格式。
  2. 使用 Pandoc 时指定模板:
    pandoc example.md -o example.pdf --template=template.tex
    

Pandoc 过滤器

Pandoc 提供了扩展功能,通过过滤器可以对文档进行进一步处理,比如添加水印或修改特定格式。

使用 Python 过滤器

可以编写 Pandoc 过滤器来修改 AST(抽象语法树)。比如你想过滤掉所有二级标题,可以用 Python 来实现过滤器。

pandoc example.md --filter ./filter.py -o example.pdf

Pandoc 的输入输出格式

Pandoc 支持的输入和输出格式非常多,其中包括:

  • 输入格式:Markdown (.md)、DOCX (.docx)、LaTeX (.tex)、HTML (.html)、reStructuredText (.rst)、EPUB (.epub)、ODT (.odt)、MediaWiki (.wiki)、Org-mode (.org)、Textile (.textile)等
  • 输出格式:PDF (.pdf)、DOCX (.docx)、HTML (.html)、LaTeX (.tex)、EPUB (.epub)、Markdown (.md)、ODT (.odt)、RTF (.rtf)、PowerPoint (.pptx)、Plain text (.txt)等

扩展 Markdown

Pandoc 增强了 Markdown,支持表格、脚注、目录生成等。使用时可以指定不同的 Markdown 扩展:

pandoc example.md -o example.html --from markdown+footnotes+table_captions

Pypandoc的使用

Pypandoc 是 Pandoc 的 Python 接口,允许在 Python 程序中直接调用 Pandoc 进行文档格式转换。Pypandoc 提供了一个简化的 API,使得用户可以在 Python 中方便地使用 Pandoc 的所有功能,而不必通过系统命令行进行调用。

安装 Pypandoc

Pypandoc 可以通过 pip 安装:

pip install pypandoc

Pypandoc 只是 Pandoc 的 Python 封装,因此你仍然需要安装 Pandoc。你可以按照 Pandoc 官方网站 提供的说明进行安装。

自动下载 Pandoc

如果 Pandoc 未安装,Pypandoc 提供了一个函数 pypandoc.download_pandoc(),可以自动下载并安装 Pandoc。这在没有管理员权限或者需要快速部署的场景下特别有用。

import pypandoc

# 自动下载 Pandoc 并安装
pypandoc.download_pandoc()

此方法会下载适用于当前操作系统的 Pandoc 二进制文件,并将其存放在 Pypandoc 可以访问的目录中。

  • pypandoc.download_pandoc() 默认下载的 Pandoc 二进制文件是从网络上获取的。因此,在离线环境下无法使用此功能。
  • 自动安装的 Pandoc 仅限于 Pypandoc 使用,并不会影响系统的其他程序。

检查 Pandoc 安装

在使用 Pypandoc 时,可以先检查 Pandoc 是否已安装:

import pypandoc

try:
    # 检查 Pandoc 是否可用
    pypandoc.get_pandoc_version()
except OSError:
    # 如果未安装,则自动下载 Pandoc
    pypandoc.download_pandoc()

Pypandoc 的基本用法与详细参数

Pypandoc 是 Pandoc 的 Python 接口,提供了两种主要的转换方式:

  • pypandoc.convert_text():用于转换字符串内容。

  • pypandoc.convert_file():用于转换文件。

pypandoc.convert_text()

用于将一个字符串的文本从一种格式转换为另一种格式。

语法:

pypandoc.convert_text(source_text, to, format=None, extra_args=None, encoding='utf-8')

参数:

  • source_text:要转换的文本内容(字符串)。
  • to:目标格式,例如 'html''pdf''docx' 等。
  • format:源文本格式。例如 'md'(Markdown)、'rst'(reStructuredText)、'latex'(LaTeX)等。如果不指定,默认会尝试根据内容自动检测。
  • extra_args:可以传递给 Pandoc 的额外命令行参数。例如,['--toc'] 可以生成目录,['--highlight-style=pygments'] 可以设置代码高亮风格。
  • encoding:文本编码,默认为 'utf-8'

示例:

import pypandoc

# 将 Markdown 字符串转换为 HTML
output = pypandoc.convert_text('# Hello World', 'html', format='md')
print(output)
pypandoc.convert_file()

用于将一个文件从一种格式转换为另一种格式。

语法:

pypandoc.convert_file(source_file, to, format=None, outputfile=None, extra_args=None, filters=None)

参数:

  • source_file:要转换的源文件路径,可以是字符串或文件路径列表。
  • to:目标格式,例如 'pdf''html''docx' 等。
  • format:源文件格式。例如 'md'(Markdown)、'rst'(reStructuredText)、'latex'(LaTeX)等。如果不指定,默认根据文件扩展名检测。
  • outputfile:输出文件的路径。如果指定该参数,转换结果会直接写入文件,而不是返回字符串。若未指定,将返回转换结果的字符串内容。
  • extra_args:传递给 Pandoc 的额外命令行参数(列表形式)。
  • filters:Pandoc 过滤器的路径或名称,用于对文档进一步处理。可选参数。

示例:

# 将 Markdown 文件转换为 DOCX
output = pypandoc.convert_file('example.md', 'docx', outputfile='example.docx')

# 将 LaTeX 文件转换为 PDF,使用特定的 LaTeX 引擎
output = pypandoc.convert_file('example.tex', 'pdf', extra_args=['--pdf-engine=xelatex'])

错误处理

Pypandoc 会抛出 RuntimeError,如果 Pandoc 命令执行失败,用户可以捕获并处理错误:

try:
    output = pypandoc.convert_file('nonexistent.md', 'pdf')
except RuntimeError as e:
    print(f"转换失败:{e}")

批量文档转换源码剖析

这段代码的主要目的是将指定目录中的特定类型文件(例如 .md 文件)批量转换为另一种格式(例如 pdfdocx),并且保留原有的目录结构。下面是逐段讲解:

导入必要的库

import os
import pypandoc
  • os: 用于处理文件和目录的操作,比如遍历文件夹,检查目录是否存在,创建目录等。
  • pypandoc: 这是 Pandoc 的 Python 包装器,用于将各种格式的文件进行转换。

获取指定扩展名的文件列表

def get_files(source_dir, source_ext):
    """
    遍历源目录,获取符合指定扩展名的文件列表,并返回源文件路径。

    参数:
    source_dir (str): 源文件目录路径。
    source_ext (str): 要查找的源文件扩展名(如 '.md')。

    返回:
    list: 一个包含源文件路径的列表。
    """
    file_pairs = []

    # 遍历源目录及其子目录中的所有文件
    for src_root, _, files in os.walk(source_dir):
        for filename in files:
            # 检查文件扩展名是否符合源文件要求
            if filename.endswith(source_ext):
                # 构建源文件路径
                src_path = os.path.join(src_root, filename)
                file_pairs.append(src_path)
    
    return file_pairs
  • get_files 函数用于遍历指定的 source_dir 目录,寻找符合特定扩展名(source_ext)的文件,并返回一个包含这些文件路径的列表。
  • 使用了 os.walk() 遍历目录及其子目录,查找特定扩展名的文件。

转换单个文件

def convert_file(src_path, dst_path, target_format):
    """
    将单个源文件转换为指定格式的目标文件。
    """
    try:
        if target_format == "pdf":
            extra_args = [
                "--pdf-engine=xelatex",
                "--variable",
                'mainfont="SimSun"',  # 使用 SimSun 字体,或其他已安装字体
                "--variable",
                'CJKmainfont="SimSun"',  # 设置 CJK 字体
                "--variable",
                'fontenc="T1"',  # 字体编码
                "--variable",
                "geometry:margin=1in",  # 设置边距
            ]

            pypandoc.convert_file(
                src_path, target_format, outputfile=dst_path, extra_args=extra_args
            )
        else:
            pypandoc.convert_file(src_path, target_format, outputfile=dst_path)

        print(f"已成功转换 {src_path}{dst_path}.")
    except Exception as e:
        print(f"无法转换 {src_path}: {e}")

  • 该函数用于将单个文件从 src_path 转换为目标格式 target_format,并将输出保存到 dst_path
  • 如果目标格式是 pdf,使用 xelatex 引擎,并添加支持中文字体和适当的 LaTeX 参数。
  • 对于其他格式,直接使用 pypandoc 进行转换。
  • 使用 try-except 块捕获异常,避免程序崩溃并输出错误信息。

批量转换文件

def convert_files(source_dir, output_dir, source_ext, target_format):
    """
    将源目录中的指定类型文件批量转换为目标格式,并保持原目录结构。

    参数:
    source_dir (str): 源文件目录路径。
    output_dir (str): 转换后文件的输出目录路径。
    source_ext (str): 要转换的源文件的扩展名(例如 '.md')。
    target_format (str): 目标文件格式(例如 'pdf', 'docx' 等)。
    """
    # 确保输出目录存在
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # 获取源文件及其目标路径的列表
    files_to_convert = get_files(source_dir, source_ext)
    
    for src_path in files_to_convert:
        # 构建目标文件名和路径
        rel_path = os.path.relpath(src_path, source_dir)
        target_name = rel_path.rsplit('.', 1)[0] + '.' + target_format
        dst_path = os.path.join(output_dir, target_name)

        # 确保目标目录结构存在
        dst_root = os.path.dirname(dst_path)
        if not os.path.exists(dst_root):
            os.makedirs(dst_root)
        
        # 转换单个文件
        convert_file(src_path, dst_path, target_format)
  • 该函数批量将 source_dir 目录中的指定类型文件转换为目标格式 target_format
  • 它确保目标输出目录存在,并保持原始文件目录结构。
  • 调用 convert_file 函数来处理每个文件的转换。

程序主入口

if __name__ == "__main__":
    # 自动下载并安装 Pandoc,避免手动安装
    try:
        pypandoc.get_pandoc_version()
    except OSError:
        pypandoc.download_pandoc()

    # 示例路径,用户需根据实际情况修改
    source_dir = 'path/to/your/source/files'  # 源文件目录
    output_dir = 'path/to/your/output/files'  # 输出文件目录
    source_ext = '.md'  # 源文件扩展名
    target_format = 'pdf'  # 目标格式(例如 'pdf', 'docx')

    # 调用文件转换函数
    convert_files(source_dir, output_dir, source_ext, target_format)
  • 这是程序的主入口,用于自动下载 Pandoc(如果还没有安装)并调用 convert_files 函数进行批量文件转换。
  • 需要用户根据实际路径修改 source_diroutput_dir,以及指定源文件扩展名和目标文件格式。

你可能感兴趣的:(#,Python全栈开发,python,开发语言)