2021-10-08 用Python写的Linux下的 转换word的docx文件为pdf文件,并使用Docker容器自动化部署

文档层级
2021-10-08 用Python写的Linux下的 转换word的docx文件为pdf文件,并使用Docker容器自动化部署_第1张图片
完整项目资源代码

先上源代码

程序的基本思路是在数据库中存储文件名和他的MD5信息,校验这两个数据,如果数据库里面没有就转换,如果有就不转换,如果文件名有但MD5不同,就要删除原有的数据条目,避免word文档回到旧版本时转换不了

import subprocess

# from win32com.client import gencache
# from win32com.client import constants, gencache
import os
import sys
import hashlib
import pymysql


#读取MD5
def readMD5(path):
    with open(path, 'rb') as fp:
        data = fp.read()
    file_md5 = hashlib.md5(data).hexdigest()
    return file_md5

def checkMD5(md5,filename):
    # 拿到套接字对象
    client = pymysql.connect(
        host='mysql',
        port=3306,
        user='root',
        password='sa123456',
        database='db1',
        charset='utf8'
    )
    # 拿到游标  mysql>
    # cursor() 只会把每条记录放入小元组
    cursor=client.cursor()
    cursor.execute('''
    CREATE TABLE IF NOT EXISTS `docxmd5` (
          `mymd5` varchar(32) NOT NULL,
          `filename` varchar(150) NOT NULL,
          PRIMARY KEY (`mymd5`,`filename`)
        )
    ''')
    client.commit()
    sql=f"select * from docxmd5 where mymd5='{md5}' and filename='{filename}'"
    rows=cursor.execute(sql)
    if rows:
        cursor.close()

        client.close()
        return 0

    else:
        sql2=f"insert into docxmd5 (mymd5,filename) value ('{md5}','{filename}')"
        cursor.execute(sql2)
        client.commit()
        cursor.close()
        client.close()
        return 1

def findoldMD5(filename):
    client = pymysql.connect(
        host='mysql',
        port=3306,
        user='root',
        password='sa123456',
        database='db1',
        charset='utf8'
    )
    # 拿到游标  mysql>
    # cursor() 只会把每条记录放入小元组
    cursor = client.cursor()
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS `docxmd5` (
              `mymd5` varchar(32) NOT NULL,
              `filename` varchar(150) NOT NULL,
              PRIMARY KEY (`mymd5`,`filename`)
            )
        ''')
    client.commit()
    sql = f"select * from docxmd5 where filename='{filename}'"
    rows = cursor.execute(sql)
    if rows:
        data=cursor.fetchone()
        cursor.close()
        client.close()
        return data[0]

    else:
        cursor.close()
        client.close()
        return 0

def deleteMD5(oldmd5, filename):
    client = pymysql.connect(
        host='mysql',
        port=3306,
        user='root',
        password='sa123456',
        database='db1',
        charset='utf8'
    )
    # 拿到游标  mysql>
    # cursor() 只会把每条记录放入小元组
    cursor = client.cursor()
    sql=f"delete from docxmd5 where mymd5='{oldmd5}' and filename='{filename}"

#创建PDF windows-version
'''
def createPdf(wordPath, pdfPath):
    """
    word转pdf
    :param wordPath: word文件路径
    :param pdfPath:  生成pdf文件路径
    """
    word = gencache.EnsureDispatch('Word.Application')
    doc = word.Documents.Open(wordPath, ReadOnly=1)
    doc.ExportAsFixedFormat(pdfPath,
                            constants.wdExportFormatPDF,
                            Item=constants.wdExportDocumentWithMarkup,
                            CreateBookmarks=constants.wdExportCreateHeadingBookmarks)
    word.Quit(constants.wdDoNotSaveChanges)
'''
#遍历当前目录,并把Word文件转换为PDF

def doc2pdf_linux(docPath):
    cmd = 'libreoffice --headless --convert-to pdf'.split() + [docPath]
    p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    p.wait(timeout=30)
    stdout, stderr = p.communicate()
    if stderr:
        raise subprocess.SubprocessError(stderr)



def wordToPdf(path):
    # 获取当前运行路径
    # path = os.listdir(loc)
    # 获取所有文件名的列表
    # print(path)
    try:
        filename_list = os.listdir(path)
    except:
        print('没有这个文件夹')
        return 0
    # print(filename_list)
    print('文件夹:',path,"转换中...")

    # 获取所有word文件名列表
    wordname_list = [filename for filename in filename_list \
                        if filename.endswith((".docx",))]
    for wordname in wordname_list:
        # 分离word文件名称和后缀,转化为pdf名称
        pdfname = os.path.splitext(wordname)[0] + '.pdf'

        wordpath = os.path.join(path, wordname)
        pdfpath = os.path.join(path, pdfname)



        oldmd5=0
        if os.path.exists(pdfpath):
            oldmd5=findoldMD5(wordpath)

        md5=readMD5(wordpath)

        if not checkMD5(md5,wordpath):
            print(wordpath,'已经转换过了')
            continue
        else:
            #将旧文件信息删除
            if oldmd5!=0:
                deleteMD5(oldmd5,wordpath)


        print(wordpath,pdfpath,end='\n')
        doc2pdf_linux(wordpath)

#word转pdf
if __name__ == '__main__':

    try:
        path:str=sys.argv[1]
    except:
        # 如果参数不提供就是当前目录
        path=os.getcwd()
    try:
        path=os.path.abspath(path)
        print('当前绝对路径为:',path)
        pathlist=os.walk(path)
    except:
        print(f'文件夹位置{path}错误,未能找到!')
        exit()

    for i in pathlist:
        wordToPdf(i[0])



解析

readMD5函数

读取word文件的MD5值

checkMD5函数

连接数据库并创建表,查询这个MD5与文件名,有就返回0,没有就插入并返回1

findoldMD5函数

在相关pdf文件已经存在的情况下,查询旧文件的MD5并返回

deleteMD5函数

删除旧的MD5和文件名的数据

doc2pdf_linux函数

在linux下调用系统命令转换文件

wordToPdf函数

主程序,对路径下的以docx结尾的文件遍历并调度上面的几个函数,安排数据库读取,存储和 删除

程序入口

程序入口接受一个命令行参数作为路径,也默认使用当前文件的位置作为路径,利用os.walk函数逐层遍历路径并调用wordToPdf函数

注释的部分createPdf函数

windows下的pdf转换,在windows下可以直接调用这个函数转换

docker-compose文件

version: "3.1"
services:
  # python环境
  libreoffice:
    tty: true
    stdin_open: true
    build: code
    volumes:
      - ./code:/code

  # mysql
  mysql:
    image: "mysql:latest"
    environment:
      MYSQL_ROOT_PASSWORD: sa123456
      MYSQL_DATABASE: db1
    ports:
      - 3307:3306



这里建立了两个容器服务
libreoffice是一个带python的环境,具体的构建参照code文件夹下的Dockerfile
将目录下的code文件夹映射到容器中的code文件夹
mysql建立一个数据库服务,对应python文件代码里的连接,host参数的名字就是服务名mysql

Dockerfile

FROM   gocept/libreoffice-python:py3.6
WORKDIR /code
RUN  python -m pip install --upgrade pip
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt


libreoffice基于的镜像是gocept/libreoffice-python:py3.6
镜像在https://hub.docker.com/u/library自己选择
找个带libreoffice的 且有python的pip的,没有pip的需要自己装
比如这个镜像

FROM   instructure/libreoffice:6.2
WORKDIR /code
USER root
RUN  apt-get update
RUN  apt -y install python3-pip

#RUN  pip3 install --upgrade pip3
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt


requirements.txt

PyMySQL
cryptography

这只需要两个即可
后面那个是用来在数据库里连接时避免出现

RuntimeError: 'cryptography' package is required for sha256_password or caching_sha2_password auth methods

那个pip版本要更新,所以Dockerfile升级了pip

部署运行

2021-10-08 用Python写的Linux下的 转换word的docx文件为pdf文件,并使用Docker容器自动化部署_第2张图片
将要转换的文件放入项目code文件夹下即可,程序默认会自动遍历给定的文件夹下级目录,默认是当前目录

你可能感兴趣的:(值得收藏的Python小技巧,docker,python,linux)