再谈 Python自动生成 pdf 文件

pdf 这个东西,不得不说,真的是受人欢迎,任何时候下载个文件或者报告之类的,都想弄个 pdf 版本。当然,这个东西的好处是不管在哪里看,样式基本都是一样的。

然而,缺点也很明显,没有办法直接生成 pdf 文件,当然,通过各种库可以直接将图片转为 pdf。然而,对于复杂格式或者需要使用模板来创建 pdf 的时候,就变得有些麻烦了。

def converImageToPdf(img_list):
    pdf = fitz.open() PyMuPDF
    pdf_document = fitz.open()  Creates a new PDF
    #遍历图片文件夹中的所有图片文件
    for img_url in img_list:
        img_local_file = download_image(img_url, 'confirmd_images')
        img_path = os.path.join(img_folder, img_file)
        img = fitz.open(img_local_file)
        img_rect = img[0].rect  Get the rectangle of the first page of the image
    #Create a new page with the same dimensions as the image
        pdf_page = pdf_document.new_page(width=img_rect.width, height=img_rect.height)
    #Insert the image into the new page
        pdf_page.insert_image(pdf_page.rect, filename=img_local_file)
    #保存PDF文件
        img.close()
    
    file_name = random_file_name('pdf')
    if not os.path.exists('confirmd_receipt'):
        os.mkdir('confirmd_receipt')
    pdf_document.save(os.path.join('confirmd_receipt/') + file_name)
    pdf_document.close()

依赖于fitz

pip install fitz

之前写过基于 oss 的:

Python生成Pdf报告

那么没有 oss 呢?其实此时最简单的办法就是基于 liboffice 了。

# 安装 LibreOffice(Ubuntu/Debian)
sudo apt-get install libreoffice

# 验证安装
libreoffice --version

代码:

import subprocess
import os

def convert_to_pdf(input_docx, output_dir):
    try:
        # 创建输出目录(如果不存在)
        os.makedirs(output_dir, exist_ok=True)
        
        # 执行转换命令
        cmd = [
            'libreoffice', '--headless', '--convert-to', 'pdf',
            '--outdir', output_dir, input_docx
        ]
        result = subprocess.run(cmd, check=True, capture_output=True, text=True)
        
        print(f"转换成功: {input_docx} → {output_dir}")
        return True
    except subprocess.CalledProcessError as e:
        print(f"转换失败: {e.stderr}")
        return False
    except Exception as e:
        print(f"发生错误: {str(e)}")
        return False

# 使用示例
convert_to_pdf(
    input_docx="/path/to/document.docx",
    output_dir="/path/to/output"
)

不多此时大概率得到的 PDF 文件会是乱码:

这一堆框就很专业,应该是没有字体导致的,安装字体文件:

# Ubuntu/Debian
sudo apt-get install fonts-wqy-zenhei fonts-wqy-microhei fonts-noto-cjk

# CentOS/RHEL
sudo yum install wqy-zenhei-fonts wqy-microhei-fonts google-noto-cjk-fonts

# 刷新字体缓存
sudo fc-cache -fv

验证安装:

# 查看已安装的中文字体
fc-list :lang=zh | grep -E "WenQuanYi|Noto"

# 预期输出示例(显示已安装字体路径):
# /usr/share/fonts/truetype/wqy/wqy-zenhei.ttc: WenQuanYi Zen Hei,文泉驛正黑:style=Regular
# /usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc: Noto Sans CJK JP,Noto Sans CJK JP Regular:style=Regular

如果依然有问题,那就修改系统配置:

# 检查当前 locale
locale

# 生成中文环境配置(如未安装)
sudo locale-gen zh_CN.UTF-8

# 临时设置环境变量(测试用)
export LANG=zh_CN.UTF-8

# 永久设置(修改 /etc/default/locale)
sudo nano /etc/default/locale
# 添加内容:
LANG="zh_CN.UTF-8"
LC_ALL="zh_CN.UTF-8"

或者转换的之后指定字体:

def convert_with_font(input_docx, output_dir):
    cmd = [
        'libreoffice', '--headless',
        '--env:UserInstallation=file:///tmp/libreoffice-altprofile', # 使用独立配置
        '--convert-to', 'pdf:writer_pdf_Export:{"Watermark":{"type":"string","value":" "},'
                         '"SelectPdfVersion":{"type":"long","value":"1"},'
                         '"UseTaggedPDF":{"type":"boolean","value":"true"},'
                         '"ExportBookmarks":{"type":"boolean","value":"true"},'
                         '"EmbedStandardFonts":{"type":"boolean","value":"true"}}',
        '--outdir', output_dir,
        input_docx
    ]
    subprocess.run(cmd, check=True)

此时多数就能解决问题了:

☆版权☆

* 网站名称:obaby@mars
* 网址:https://obaby.org.cn/
* 个性:https://oba.by/
* 本文标题: 《再谈 Python自动生成 pdf 文件》
* 本文链接:https://obaby.org.cn/2025/03/19568
* 短链接:https://oba.by/?p=19568
* 转载文章请标明文章来源,原文标题以及原文链接。请遵从 《署名-非商业性使用-相同方式共享 2.5 中国大陆 (CC BY-NC-SA 2.5 CN) 》许可协议。


You may also like

34 comments

  1. Level 4
    Safari 18 Safari 18 iPhone iOS 18.3.1 iPhone iOS 18.3.1 cn中国–香港–新界–荃湾区 Hytron_Network_Services

    跟天书一样,这是直接搞了个 pdf 生成器吗?

    1. 公主 Queen 
      Google Chrome 132 Google Chrome 132 Mac OS X 10.15 Mac OS X 10.15 cn中国–山东–青岛 联通

      还是基于 liboffice,调用现有组件而已

  2.  Level 6
    Firefox 134 Firefox 134 GNU/Linux GNU/Linux cn中国–广东–珠海 电信

    java对pdf生成和word,excel那些都有比较完整的生态支持,还算好了,工作中整天跟这些打交道~

  3. Level 5
    Google Chrome 130 Google Chrome 130 Android 10 Android 10 cn中国–四川–成都 电信

    pdf,不可更改性稍微好一点,我现在偶尔帮领导PS一下pdf的材料,真怕有一点进去了都。🤪

  4. Level 1
    Google Chrome 133 Google Chrome 133 Windows 11 Windows 11 cn中国–江苏–徐州 移动

    PDF真是让人又爱又恨。喜欢它的多环境一致性,但是讨厌它的内容很难被修改。

    1. 公主 Queen 
      Google Chrome 130 Google Chrome 130 Android 10 Android 10 cn中国–山东–青岛 联通

      现在也有很多pdf编辑器了 这才叫魔幻
      最开始就是想不容易被改
      现在一群人变着法的要改pdf

  5.   Level 4
    Google Chrome 133 Google Chrome 133 Windows 11 Windows 11 cn中国–江西 移动/数据上网公共出口

    这个不错 我准备拿去搞点好玩的

  6. Level 4
    Google Chrome 131 Google Chrome 131 Windows 10 Windows 10 cn中国–山东–青岛 联通

    企业用pdf多,还有加密什么的。
    看电子书也有不少pdf格式的。
    还好只是看也不用其他复杂的。

    1. 公主 Queen 
      Google Chrome 132 Google Chrome 132 Mac OS X 10.15 Mac OS X 10.15 cn中国–山东–青岛 联通

      是的,各种 pdf
      主要还是这种格式稳定性真的太好了,尤其是还有各种基于图片的 pdf。

    1. 公主 Queen 
      Google Chrome 132 Google Chrome 132 Mac OS X 10.15 Mac OS X 10.15 cn中国–山东–青岛 联通

      看不懂也没啥的,小玩意儿而已。
      记录一下,怕哪天在别的服务器上部署的时候出问题忘了怎么解决,当备忘录用。

  7. Level 3
    Google Chrome 86 Google Chrome 86 Windows 10 Windows 10 cn中国–上海–上海 联通

    技术文,看不懂,我的PDF都是各种软件转换的…
    封面 100 分~

  8. Level 6
    Google Chrome 109 Google Chrome 109 Windows 10 Windows 10 cn中国–上海–上海 腾讯云

    灵妹妹,还有3天。

  9.  Level 6
    Google Chrome 130 Google Chrome 130 Windows 11 Windows 11 cn中国–河南–漯河 电信

    我不论安装兔子还是deepin,第一件事就是把libreoffice删了。 laugh
    它功能比office和WPS强大,但是我电脑老打开很慢,不知道为啥。

回复 沉沦 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注