python判断word页码


title: python实现word判断索引页码
date: 2019-02-12 15:09:39
tags:

  • pdf
  • word
  • python
    categories:
  • python
  • 自动化

python判断word页码

1、整体思路

​ word的源码格式类似于xml,目前无法直接解析word页码

​ 整体思路是 先将word转成pdf, 通过对PDF每一页进行文字提取,判断页码。

2、使用到的python库

​ 主要是 pdfminer库进行word转换成PDF,windows去下载pdfminer3k ,该库的准确率很高,不用担心正确率的问题

​ python处理PDF有两个比较常见的库,另一个是pypdf2,该库在我的项目中表现比较差,提取PDF中的文字时准确率比较低,所以放弃了。

3、windows下安装pdfminer3k

pip install pdfminer3k

4、环境

​ python3.6

​ windows

5、代码

import os
import sys
import importlib
importlib.reload(sys)
import re
from pdfminer.pdfparser import PDFParser, PDFDocument
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import PDFPageAggregator
from pdfminer.layout import LTTextBoxHorizontal, LAParams
from pdfminer.pdfinterp import PDFTextExtractionNotAllowed
from win32com.client import Dispatch, constants, gencache


rootDir = os.getcwd() + r"\root"
projectDir = os.getcwd()
logPath = os.path.join(projectDir, r'log.txt')
colorLogPath = os.path.join(projectDir, r'colorLog.txt')


def log(*args):
    """
    输出灰印日志
    :param data:
    """
    data = "#".join(list(args))
    # print(data)
    with open(logPath, 'a') as f:
        f.write(data + "\n")


def colorLog(*args):
    """
    输出彩印日志
    :param data:
    """
    data = "#".join(list(args))
    with open(colorLogPath, 'a', encoding='utf-8') as f:
        f.write(data + "\n")


def readPartItems(partItemsPath):
    """
    读取信息
    :param partItemsPath:
    :return:
    """
    with open(partItemsPath, 'r', encoding='utf-8') as f:
        return f.read()


def pdfParse(path, kws):
    """
     解析pdf 文本,返回关键检索信息
    :param path: pdf路径
    :param kws: 匹配的关键字列表
    :return: 元祖(blackPrint, corlorPrint,capNames)  ([灰色页] ,[彩色页])
    """
    colorPrint = []  # 彩色打印页码
    blackPrint = []  # 黑白打印页码
    cpaNames = []    #注册师
    fp = open(path, 'rb')  # 以二进制读模式打开
    # 用文件对象来创建一个pdf文档分析器
    praser = PDFParser(fp)
    # 创建一个PDF文档
    doc = PDFDocument()
    # 连接分析器 与文档对象
    praser.set_document(doc)
    doc.set_parser(praser)

    # 提供初始化密码
    # 如果没有密码 就创建一个空的字符串
    doc.initialize()

    # 检测文档是否提供txt转换,不提供就忽略
    if not doc.is_extractable:
        raise PDFTextExtractionNotAllowed
    else:
        # 创建PDf 资源管理器 来管理共享资源
        rsrcmgr = PDFResourceManager()
        # 创建一个PDF设备对象
        laparams = LAParams()
        device = PDFPageAggregator(rsrcmgr, laparams=laparams)
        # 创建一个PDF解释器对象
        interpreter = PDFPageInterpreter(rsrcmgr, device)
        count = 0  # 记录页数
        # 循环遍历列表,每次处理一个page的内容
        for page in doc.get_pages():  # doc.get_pages() 获取page列表
            count += 1
            interpreter.process_page(page)
            # 接受该页面的LTPage对象
            layout = device.get_result()
            # 这里layout是一个LTPage对象 里面存放着 这个page解析出的各种对象 一般包括LTTextBox, LTFigure, LTImage, LTTextBoxHorizontal 等等 想要获取文本就获得对象的text属性,
            results = ''
            for x in layout:
                if (isinstance(x, LTTextBoxHorizontal)):
                    results += x.get_text()

            # 正则匹配是否彩印
            pattern = '|'.join(kws)
            data = re.findall(pattern, results, re.S)

            # 正则匹配注册会计师的姓名
            pattern = '中国注册会计师:\s*(.*?)\n'
            nameList = re.findall(pattern, results, re.S)

            for i in nameList:
                cpaNames.append("".join(re.split(r'\s+', i)))

            # 区分彩灰打印页
            if data:
                colorPrint.append(str(count))
            else:
                blackPrint.append(str(count))
        return blackPrint, colorPrint, cpaNames


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)


def printCredential(cpaNames):
    # print("打印证书:", cpaNames)
    pass



def createData(path):
    data = readPartItems(path + "\project_part_items.txt")
    item = data.split("\n")
    if not os.path.exists(r'%s\pdfCachDir' % projectDir):
        os.mkdir(r'%s\pdfCachDir' % projectDir)
    pdfCachDir = r'%s\pdfCachDir' % projectDir  # pdf存放目录
    fileNameList = os.listdir(path)
    cpaNames = []  #需要打印证书的名字
    for file in fileNameList:
        pages = "Default"
        copies = "1"

        (fileName, extension) = os.path.splitext(file)
        fileAbsPath = os.path.join(path, file)
        #word
        if "封面" in fileName and extension in ['.docx', '.doc']:
            log(extension, fileAbsPath, pages, copies)
        #word
        elif "正文" in fileName and extension in ['.docx', '.doc']:
            pdfAbsPath = os.path.join(pdfCachDir, fileName + '.pdf')  # pdf 路径
            if not os.path.exists(pdfAbsPath):  # pdf是否存在

                createPdf(fileAbsPath, pdfAbsPath)


                kws = ["中国注册会计师", "中国·北京"]

                # 解析pdf 该返回二维列表 [[灰白印页], [彩印页], [cpanames]
                blackPrint, colorPrint, cpaNames = pdfParse(pdfAbsPath, kws)
                # 灰白打印记入文件
                log(extension,fileAbsPath, ",".join(blackPrint), copies)


                # 彩色打印记入文件
                colorPages = str(','.join(colorPrint[1]))

                pattern = "正文.docx:(.*?)\n"
                dataId = re.findall(pattern, data)[0]
                colorLog(item[0].split(":")[-1], item[1].split(":")[-1], copies, "%s$%s" % (dataId, colorPages))

                # 删除pdf缓存文件
                os.remove(pdfAbsPath)
                pass
        # ecxl文件操作
        elif "报表" in fileName and extension in ['.xls', '.xlsx']:
            # print('正在写入灰白打印记录', fileAbsPath)
            log(extension, fileAbsPath, pages, copies)
            pass
        # word
        elif '附注' in fileName and extension in ['.docx', '.doc']:
            # print('正在写入灰白打印记录', fileAbsPath)
            log(extension, fileAbsPath, pages, copies)
            pass
    # 最终处理打印证书
    printCredential(cpaNames)


def main(rootDir):
    fileDirs = os.listdir(rootDir)
    for fileDir in fileDirs:
        fileDirPath = os.path.join(rootDir, fileDir)
        createData(fileDirPath)

def err():
    if os.path.exists(logPath):
        os.remove(logPath)
    if os.path.exists(colorLogPath):
        os.remove(colorLogPath)
    if os.path.exists(r'%s\pdfCachDir' % projectDir):
        pdfCachDir = r'%s\pdfCachDir' % projectDir  # pdf存放目录
        for pdf in os.listdir(pdfCachDir):
            pdfPath = os.path.join(pdfCachDir, pdf)
            os.remove(pdfPath)
        os.rmdir(pdfCachDir)


if __name__ == '__main__':
    try:
        main(rootDir)
    except:
        err()

最近查看vba文档发现 调用vba可以很简单实现

Autoit 实现word拆分页解析 (python同理)

背景

之前一直在做相关工作,由于没有找到解决最佳解决方案,老办法思路是 python先将word 转成pdf,按照页码 提取文字,从而实现word的页索引工作。

最近研究了一下vba,终于找到了最佳解决方案!!!

AutoIt

我用AutoIt测试的,AutoIt调用vba

#include <MsgBoxConstants.au3>
#include <Word.au3>

; 创建应用对象
Local $oWord = _Word_Create()
If @error Then Exit MsgBox($MB_SYSTEMMODAL, "Word UDF: _Word_DocOpen 示例", _
        "创建新 Word 应用对象时发生错误." & @CRLF & "@error = " & @error & ", @extended = " & @extended)

; *****************************************************************************
; 只读打开文档
; *****************************************************************************
Local $sDocument = 'D:\Desktop\tzcpa\BJ自动打印\新建文件夹\AutoPrinter\log\backupFile\2019-04-03 08h39m03s140\天职业字[2019]11884号\2.单体审计报告2018-标准无保留意见.docx'
Local $doc = _Word_DocOpen($oWord, $sDocument, Default, Default, True)
If @error Then Exit MsgBox($MB_SYSTEMMODAL, "Word UDF: _Word_DocOpen 示例 1", "打开文档 '.\Extras\Test.doc' 发生错误." & _
        @CRLF & "@error = " & @error & ", @extended = " & @extended)

;关键部分!!!! 
; $doc 是当前活动文档,Pages是页码索引,Item是矩形框索引 改成请自行更改测试,因为一页可能有多个矩形框 
;返回值时 活动文档某一页的 矩形框中的文本

Local $objPage = $doc.ActiveWindow _
 .Panes(1).Pages(2).Rectangles.Item(2).Range.Text
MsgBox(1,1,$objPage)


MsgBox($MB_SYSTEMMODAL, "Word UDF: _Word_DocOpen 示例 1", "文档 '" & $sDocument & "' 已成功打开.")

思路

整体思路是调用vba,由于目前python没有发现 有库可以对 页对象进行操作,所以采用了调用底层vba来操作

在vba中 页对象有一个是 Rectangles属性,解释如下

下面的示例返回活动文档中第一页的矩形集合。

Dim objRectangles As Rectangles 
 
Set objRectangles = ActiveDocument.ActiveWindow _ 
 .Panes(1).Pages(1).Rectangles

然后顺藤摸瓜找到了Rectangles对象可以操作Range ,这样就可以获得某一页的某一矩形 内的 text,之后对于大多数页对象的操作也就解决了。

python同理,使win32库调用 vba就好了

  • 1
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值