Word 转 PDF,且需要能够在 Linux 上部署

1.docx (0118)

实现方案 优点 缺点 软件占用空间
win32com 效果最好 不支持 Linux 1 GB 以上
comtypes 效果最好 不支持 Linux 1 GB 以上
docx2pdf 效果最好 不支持 Linux 1 GB 以上
AbiWord 占用空间小,安装方便 不支持 Windows,导出可能不完整 69.4 MB
LibreOffice 支持 Windows 和 Linux 效果一般,安装麻烦 585 MB
wvPDF 效果很差,兼容很差 247 MB
aspose-words 速度快 收费,有水印 50.6 MB
unoconv 效果较差,且有坑 306 MB
阿里云市场易源数据API 速度快 效果较差,收费 0
九云图API 效果好 文档需先上传为url,字体貌似需要不可多样化,收费 0
WPS+pywpsrpc 效果好 首次运行需要界面,安装麻烦 350 MB 以上

Linux 环境下建议使用 WPS+pywpsrpc

win32com

from pathlib import Path
from win32com.client import Dispatch, constants, gencache
docx_path = str(Path('1.docx').absolute())
pdf_path = str(Path('1.pdf').absolute())
gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 4)
wd = Dispatch('Word.Application')
doc = wd.Documents.Open(docx_path, ReadOnly=1)
doc.ExportAsFixedFormat(pdf_path, constants.wdExportFormatPDF, Item=constants.wdExportDocumentWithMarkup,
                        CreateBookmarks=constants.wdExportCreateHeadingBookmarks)
wd.Quit(constants.wdDoNotSaveChanges)
第一页第二页

优点:代码简洁,效果好

缺点:需要安装Microsoft Word,不支持 Linux

comtypes

pip install comtypes
from pathlib import Path
import comtypes.client
word = comtypes.client.CreateObject('Word.Application')
doc = word.Documents.Open(str(Path('1.docx').absolute()))
wdFormatPDF = 17
doc.SaveAs(str(Path('1.pdf').absolute()), FileFormat=wdFormatPDF)
doc.Close()
word.Quit()
第一页第二页

优点:代码简洁,效果好

缺点:需要安装Microsoft Word,不支持 Linux

wdFormatPDF 的值为 17 查阅 WdSaveFormat enumeration

docx2pdf

原理是调用 Microsoft Word,所以必须安装

pip install docx2pdf
docx2pdf 1.docx
from docx2pdf import convert
convert('1.docx')
print('转换完成')
第一页第二页

优点:速度快,效果好

缺点:需要安装Microsoft Word,不支持 Linux

AbiWord

Linux 安装

sudo apt-get install abiword
abiword -t pdf 1.docx
from subprocess import Popen
file = '1.docx'
Popen(['abiword', '-t', 'pdf', file]).communicate()
print('转换完成')

命令行参数详细阅读:Command line options

第一页第二页第三页

优点:占用空间小,安装方便

缺点:不支持 Windows,导出可能不完整

LibreOffice

Windows

安装 LibreOffice

添加环境变量 PATH:C:\Program Files\LibreOffice\program

soffice.exe --convert-to pdf 1.docx
from subprocess import Popen
file = '1.docx'
Popen(['soffice.exe', '--convert-to', 'pdf', file]).communicate()
print('转换完成')

Linux

Index of libreoffice 找到合适的文件(x.x.x 指具体的版本,如 7.1.8)

LibreOffice_x.x.x_Linux_x86-64_deb.tar.gz
LibreOffice_x.x.x_Linux_x86-64_deb_sdk.tar.gz
LibreOffice_x.x.x_Linux_x86-64_deb_langpack_zh-CN
mkdir -p ~/download/libreoffice/deb
cd ~/download/libreoffice
wget http://mirrors.ustc.edu.cn/tdf/libreoffice/stable/7.1.8/deb/x86_64/LibreOffice_7.1.8_Linux_x86-64_deb.tar.gz
wget http://mirrors.ustc.edu.cn/tdf/libreoffice/stable/7.1.8/deb/x86_64/LibreOffice_7.1.8_Linux_x86-64_deb_sdk.tar.gz
wget http://mirrors.ustc.edu.cn/tdf/libreoffice/stable/7.1.8/deb/x86_64/LibreOffice_7.1.8_Linux_x86-64_deb_langpack_zh-CN.tar.gz
tar -zxvf LibreOffice_7.1.8_Linux_x86-64_deb.tar.gz -C deb
tar -zxvf LibreOffice_7.1.8_Linux_x86-64_deb_sdk.tar.gz -C deb
tar -zxvf LibreOffice_7.1.8_Linux_x86-64_deb_langpack_zh-CN.tar.gz -C deb
sudo dpkg -i LibreOffice_7.1.8.1_Linux_x86-64_deb/DEBS/*.deb
sudo dpkg -i LibreOffice_7.1.8.1_Linux_x86-64_deb_sdk/DEBS/*.deb
sudo dpkg -i LibreOffice_7.1.8.1_Linux_x86-64_deb_langpack_zh-CN/DEBS/*.deb
soffice --headless --convert-to pdf 1.docx
libreoffice --headless --convert-to pdf 1.docx
第一页第二页第三页

删除安装包

rm -r ~/download/libreoffice

TODO:卸载(要一个个删,很多)

dpkg -l | grep LibreOffice
sudo dpkg -r xxx

命令行参数

详细阅读:LibreOffice command line parameters

指定保存位置(不含文件名):--outdir

wvPDF

sudo




    
 apt-get install wv texlive-base texlive-latex-base ghostscript
wvPDF 1.docx 1.pdf

效果:这份文档无法导出

aspose-words

pip install aspose-words
import aspose.words as aw
doc = aw.Document('1.docx')
doc.save('1.pdf')
print('转换完成')
第一页第二页第三页

unoconv

sudo apt-get install unoconv
unoconv -fpdf 1.docx
doc2pdf 1.docx
第一页第二页第三页

易源数据API

import base64
import requests
encoded = base64.b64encode(open('1.docx', 'rb').read())
url = 'https://word2pdf.showapi.com/word2pdf'
appcode = '你的AppCode'
headers = {
    'Authorization': 'APPCODE ' + appcode,
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
r = requests.post(url, data={'base64': encoded}, headers=headers, verify=False)
print(r)
print(r.json()['showapi_res_body']['url'])
第一页第二页第三页第四页

九云图API

创建转换任务

import json
import requests
url = 'https://api.docsdk.com/v2/jobs'
apiKey = '你的apiKey'
data = {
    'tasks': {
        'ImportURL': {
            'operation': 'import/url',
            'url': 'https://image2.9yuntu.cn/resources/api/九云图API使用说明.docx'
        'ConvertFile': {
            'input': ['ImportURL'],
            'operation': 'convert',
            'output_format': 'pdf'
        'ExportResult': {
            'input': ['ConvertFile'],
            'operation': 'export/url'
headers = {
    'Authorization': 'Bearer ' + apiKey,
    'Content-Type': 'application/json'
r = requests.post(url, data=json.dumps(data), headers=headers)
print(r)
result = r.json()
print(result)
print(result['data']['status'])
print(result['data']['job_id'])

主动查询转换结果(复制上一步的 job_id)

import requests
jobId = '上一步的job_id'
url = f'https://api.docsdk.com/v2/jobs/{jobId}'
apiKey = '你的apiKey'
headers = {
    'Authorization': 'Bearer ' + apiKey
r = requests.get(url, headers=headers)
print(r)
result = r.json()
print(result)
status = result['data']['status']
print(status)
if status == 'finished':
    tasks = result['data']['tasks']
    for task in tasks:
        files = task['result']['files']
        print(task['id'], task['status'], str(task['percent']) + '%')
        for index, file in enumerate(files):
            print(index, file['filename'], file.get('url', '无下载地址'))

安装 Python SDK

pip install docsdk
import docsdk
docsdk.configure(api_key='你的apiKey')
payload = {
    'tasks': {
        'ImportURL': {
            'operation': 'import/url',
            'url': 'https://image2.9yuntu.cn/resources/api/九云图API使用说明.docx'
        'ConvertFile': {
            'input': ['ImportURL'],
            'operation': 'convert',
            'output_format': 'pdf',
        'ExportResult': {
            'input': ['ConvertFile'],
            'operation': 'export/url'
res = docsdk.Job.create(payload=payload)  # 创建转换任务
print(res)
job_id = res['id']
res = docsdk.Job.wait(




    
job_id)  # 等待转换结果
file = res['tasks'][-1]['result']['files'][0]
filename = docsdk.download(url=file['url'], filename=file['filename'])  # 下载文件
print(filename)
第一页第二页

WPS+pywpsrpc

此方法需要 X11

查看是否已安装 X11

dpkg -l | grep xserver-xorg-core

查看是否开启 X11

cat /etc/ssh/sshd_config | grep X11Forwarding
dpkg --print-architecture

根据架构下载 WPS Office 2019 for Linux,如本人为 amd64,选择 X64

安装(本人实际安装的是wget https://wdl1.pcfg.cache.wpscdn.com/wpsdl/wpsoffice/download/linux/10920/wps-office_11.1.0.10920.XA_amd64.deb,以下为新版)

mkdir -p ~/download/wps
cd ~/download/wps
wget https://wdl1.cache.wps.cn/wps/download/ep/Linux2019/10920/wps-office_11.1.0.10920_amd64.deb
sudo dpkg -i wps-office_11.1.0.10920_amd64.deb
sudo apt-get install qt5-default
pip3 install pywpsrpc
wget https://raw.githubusercontent.com/timxx/pywpsrpc/master/examples/rpcwpsapi/convertto/convertto.py

打开 WPS(应该是中文的)

wps 1.docx

弹出,同意即可(如果没有弹出,要装 X11,阅读 Linux安装X11实现GUI


命令行

python3 convertto.py -f pdf 1.docx

这时可能会报错,再运行一次即可

Convert failed:
Details: Can't get the application
ErrCode: 0x80000008


也有可能因为网络问题渲染画面迟迟才出来报错

安装无界面模式

sudo apt install xserver-xorg-video-dummy
vim dummy.conf

输入以下内容

Section "Monitor"
        Identifier "dummy_monitor"
        HorizSync 28.0-80.0
        VertRefresh 48.0-75.0
        Modeline "1920x1080" 172.80 1920 2040 2248 2576 1080 1081 1084 1118
EndSection
Section "Device"
        Identifier "dummy_card"
        VideoRam 256000
        Driver "dummy"
EndSection
Section "Screen"
        Identifier "dummy_screen"
        Device "dummy_card"
        Monitor "dummy_monitor"
        SubSection "Display"
        EndSubSection
EndSection

启动虚拟界面

X :0 -config dummy.conf

另外开一个 SSH,实现无界面运行

export DISPLAY=localhost:0.0
echo $DISPLAY
python3 convertto.py -f pdf 1.docx
第一页第二页

删除安装包

rm -r ~/download/wps
dpkg -l | grep wps-office
sudo dpkg -r wps-office
sudo apt-get --purge remove wps-office

Supervisor 守护进程

创建 X11 的配置文件 xorg.conf

sudo vim /usr/share/X11/xorg.conf.d/xorg.conf

填入内容,具体含义见 xorg.conf

Section "Monitor"
        Identifier "dummy_monitor"
        HorizSync 28.0-80.0
        VertRefresh 48.0-75.0
        Modeline "1920x1080" 172.80 1920 2040 2248 2576 1080 1081 1084 1118
EndSection
Section "Device"
        Identifier "dummy_card"
        VideoRam 256000
        Driver "dummy"
EndSection
Section "Screen"
        Identifier "dummy_screen"
        Device "dummy_card"
        Monitor "dummy_monitor"
        SubSection "Display"
        EndSubSection
EndSection

创建子进程配置文件

sudo vim /etc/supervisor/conf.d/X11.conf
[program:X11]
command=X :0 -config /usr/share/X11/xorg.conf.d/xorg.conf
autostart=true
autorestart=true
startsecs=10
stdout_logfile=/tmp/X11.stdout.log
stderr_logfile=/tmp/X11.stderr.log

重新读取配置并更新子进程

supervisorctl reread
supervisorctl update

查看进程状态

ps -ef | grep Xorg
supervisorctl status | grep X11
import os
import argparse
from pathlib import Path
from pywpsrpc.common import S_OK
from pywpsrpc.rpcwpsapi import wpsapi, createWpsRpcInstance
os.environ['DISPLAY'] = ':0.0'  # 设置环境变量,指定哪块屏幕
formats = {
    'doc': wpsapi.wdFormatDocument,
    'docx': wpsapi.wdFormatXMLDocument,
    'rtf': wpsapi.wdFormatRTF,
    'html': wpsapi.wdFormatHTML,
    'pdf': wpsapi.wdFormatPDF,
    'xml': wpsapi.wdFormatXML,
class ConvertException(Exception):
    def __init__(self, text, hr):
        self.text = text
        self.hr = hr
    def __str__(self):
        return 'Convert failed:\nDetails: {}\nErrCode: {}'.format(self.text, hex(self.hr & 0xFFFFFFFF))
def convert_to(paths, format='pdf'):
    hr, rpc = createWpsRpcInstance()
    if hr != S_OK:
        raise ConvertException('Can not create the rpc instance', hr)
    hr, app = rpc.getWpsApplication()
    if hr != S_OK:
        raise ConvertException('Can not get the application', hr)
    app.Visible = False  # 不需要GUI
    docs = app.Documents
    for path in paths:
        path = Path(path)
        if path.is_file():
            hr, doc = docs.Open(str(path.absolute()), ReadOnly=True)
            if hr != S_OK:
                raise ConvertException('can not open file {}'.format(path.name), hr)
            new_file = '{}.{}'.format(path.parent / path.stem, format)
            hr = doc.SaveAs2(new_file, FileFormat=formats[format])
            if hr != S_OK:
                raise ConvertException('convert_file failed', hr)
            doc.Close(wpsapi.wdDoNotSaveChanges)
    app.Quit()
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('path', nargs='+')
    args = parser.parse_args()
    paths = args.path
    print(paths)
    try:
        convert_to(paths)
        print('转换完成')
    except ConvertException as e:
        print(e)

1. 报错 NotImplementedError: docx2pdf is not implemented for linux as it requires Microsoft Word to be installed

docx2pdf 不能在 Linux 上运行

2. 报错 unoconv: Cannot find a suitable pyuno library and python binary combination in /usr/lib/libreoffice

sudo vim /usr/bin/unoconv
#!/usr/bin/env python3
#!/usr/bin/python3

3. 报错 The program ‘libreoffice’ is currently not installed. To run ‘libreoffice’ please ask your administrator to install the package ‘libreoffice-common’

sudo apt-get libreoffice-common

4. 报错 Error: source file could not be loaded

sudo apt-get libreoffice-writer

5. WPS 的方案,测试代码能正常转换,部署代码报错 Can not get the application

检查环境变量 PATH 是否添加 WPS 所在目录:/usr/bin

import os
print(os.environ['PATH'])
print('/usr/bin' in os.environ['PATH'])

可能不支持并发多线程

X11 可能不支持不同用户或无 sudo 权限用户使用,Can’t start X11 applications after “su” or “su -” to another user

6. WPS 的方案,报错 convert_file failed ErrCode: 0x80010105

没有写入权限

7. WPS 可能有 BUG,需要切换为多组件模式

设置多组件模式流程:wps → 右上角设置按钮 → Settings → Others → Change window manage mode… → 选择【Multi-Module Mode】


8. Errors were encountered while processing

cd /var/lib/dpkg
sudo mv info info.bak
sudo mkdir info
sudo apt-get update
  1. pywpsrpc GitHub
  2. wpsrpc-sdk GitHub
  3. wps_cpp
  4. WPS 开放平台
  5. WPS C++ 集成源码
  6. WPSOffice二次开发帮助文档
  7. docx2pdf GitHub
  8. Converting docx to pdf with pure python (on linux, without libreoffice)
  9. LibreOffice command line parameters
  10. How to convert Word (doc) to PDF in linux
  11. unoconv: Cannot find a suitable pyuno library and python binary combination · Issue #49 · unoconv/unoconv
  12. AbiWord vs LibreOffice 2022 Comparison
  13. Linux 下的LibreOffice安装
  14. pywpsrpc Run on Server
  15. Linux deb 软件包管理
  16. Linux安装X Window服务——远程显示GUI
  17. linux服务器通过X11实现图形化界面显示
  18. Error: source file could not be loaded
  19. Python 中docx转pdf
  20. comtypes Documentation
  21. comtypes GitHub
  22. ubuntu 下使用python操作wps文档和表格
  23. python 设置linux环境变量
  24. python 如何设置linux环境变量?
  25. What is the $DISPLAY environment variable?
  26. Python实现的进程管理神器——Supervisor
  27. Where is the X.org config file? How do I configure X there?
  28. 并发执行文件转换的程序获取不到application
  29. Can’t start X11 applications after “su” or “su -” to another user
  30. xserver - What are xhost and xhost +si?
  31. How can I run /usr/bin/Xorg without sudo?
  32. /usr/bin/xauth: file /…/.Xauthority does not exist
  33. Word转PDF-阿里云
  34. Requests Documentation
  35. Python图片转base64
  36. 九云图 - API文档
  37. docsdk GitHub
from win32com.client import Dispatch, constants, gencache def doc2pdf(input, output): w = Dispatch('Word.Application') # 打开文件 doc = w.Documents.Open(input, ReadOnly=1) # 换文件 完整项目资源代码 先上源代码 程序的基本思路是在数据库中存储文件名和他的MD5信息,校验这两个数据,如果数据库里面没有就换,如果有就不换,如果文件名有但MD5不同,就要删除原有的数据条目,避免word文档回到旧版本时换不了 import subprocess # from win32com.client import gencache # from win32com.client import constants, gencache import os import sys import
一些重要文档格式之间的互在目前显得尤为重要,pdf作为通用格式在现在各个平台上兼容性是最好的,所以写python脚本将这些word文档批量pdf是最好的解决方案。 由于windows系统对于word文档有天然的兼容性优势,所以换起来很简单,普遍上是通过comtypes模块。
Python编程中raise可以实现报出错误的功能,而报错的条件可以由程序员自己去定制。在面向对象编程中,可以先预留一个方法接口不实现,在其子类中实现。如果要求其子类一定要实现,不实现的时候会导致问题,那么采用raise的方式就很好。而此时产生的问题分类是NotImplementedError。        写一段代码如下: class ClassDemo:        def test
使用python脚本完成wordpdf(兼容linux) 参考:https://v3u.cn/a_id_96 起因:看到一个需求是用java把wordpdf,在windows上使用Jacob可以实现,但linux上比较麻烦, 性能等综合考虑使用OpenOffice比较好。 感觉可以用java调用python脚本实现,这里做个记录。 在原博客中,作者在windows环境下使用了comtypes实现的换,我本地换成了pywin32实现,另,增加了一个输出目录的参数,用于指
Linux下将word换为PDF较为费劲,一方面是格式是否正确,另一方面是时间问题,下面简单列出几个工具,比较说明它们的用法和局限性。 1. openoffice+unoconv 2. docx-to-pdf-converter 3. xdocreport 4. aspose-words openoffice+unoconv 1. 安装 https://www...
您可以使用Python的docx2pdf库将Word文档换为PDF格式。您需要在Linux环境下安装该库,并使用Python代码调用它来执行换。以下是一个示例代码: from docx2pdf import convert # 将Word文档换为PDF convert("input.docx", "output.pdf") 请注意,您需要将“input.docx”替换为您要换的Word文档的文件名,并将“output.pdf”替换为您要生成的PDF文件的文件名。
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of 申时霁雨: 这个配置加在哪呀? Python划分图像文件夹为训练集、验证集和测试集——split-folders 就是效率比较低 PyCharm快捷键大全 是晨星啊: 找到了,<kbd>字符</kbd>