• 【Python 库】读取 .doc、.docx 两种 Word 文件简述及“Word 未能引发事件”错误


    概述

    Python 中可以读取 word 文件的库有 python-docxpywin32

    下表比较了各自的优缺点。

     优点缺点
    python-docx 跨平台 只能处理 .docx 格式,不能处理.doc格式
    pywin32 仅限 windows 平台 .doc 和 .docx 都能处理

    pywin32

    这个库很强大,不仅仅可以读取 word,本文仅介绍其读取 word 功能。网上介绍用 pywin32 读取 .doc 的文章真不多,因为,真心不好用

    以下是 pywin32 读取 .doc 的代码示例,但是读取表格有问题,输出全是空,原因不明,因为不打算用所以没有深入研究。另外,如果表格中有纵向合并单元格,会报错:“无法访问此集合中单独的行,因为表格有纵向合并的单元格。”

    from win32com.client import Dispatch

    word = Dispatch('Word.Application')     # 打开word应用程序
    # word = DispatchEx('Word.Application') # 启动独立的进程
    word.Visible = 0        # 后台运行,不显示
    word.DisplayAlerts = 0  # 不警告

    path = r'E:abc est.doc'
    doc = word.Documents.Open(FileName=path, Encoding='gbk')

    for para in doc.paragraphs:
        print(para.Range.Text)

    for t in doc.Tables:
        for row in t.Rows:
            for cell in row.Cells:
                print(cell.Range.Text)

    doc.Close()
    word.Quit

    但是 pywin32 有另外一个功能,就是将 .doc 格式另存为 .docx 格式,这样我们就可以使用 python-docx 来处理了。

    # 将 .doc 文件转成 .docx 
    def doc2docx(path):
        w = win32com.client.Dispatch('Word.Application')
        w.Visible = 0
        w.DisplayAlerts = 0
        doc = w.Documents.Open(path)
        newpath = os.path.splitext(path)[0] + '.docx'
        doc.SaveAs(newpath, 12False""True""FalseFalseFalseFalse)
        doc.Close()
        w.Quit()
        os.remove(path)
        return newpath

    python-docx

    python-docx 可以按段落读取 word,对于表格,可以单独的提取,代码如下:

    import docx

    fn = r'E:abc est.docx'
    doc = docx.Document(fn)

    for paragraph in doc.paragraphs:
            print(paragraph.text)

    for table in doc.tables:
        for row in table.rows:
            for cell in row.cells:
                print(cell.text)

    对于纵向合并单元格,python-docx 的处理也很贴心。看下面的截图:

    word 表格截图:



    代码运行结果截图:
     

    综上所述,对于大批量 word 文件的读取,我建议使用 python-docx 库,若是 .doc 文件,则用 pywin32 库将其转化为 .docx 文件,然后再调用 python-docx 库读取。

    Word 未能引发事件

    这是我遇到的一个实际问题,困扰了我半天时间。

    我的爬虫在爬取到 .doc 文件之后,就通过上面的方法将其转为 .docx 格式,原本一切都好,下班挂机在跑,第二天来一看,报了这个错:pywintypes.com_error: (-2147352567, '发生意外。', (0, 'Microsoft Word', 'Word 未能引发事件。', 'D:工具Microsoft OfficeOffice122052WDMAIN11.CHM', 25482, -2146822286), None)


    我用报错的文件单独调试了 doc2docx 方法,并没有报错。网上查了这个错误,没有啥收获。

    反复测试后发现总是那个网页报错,说明 bug 可以重现,那么问题到底出在哪里?

    我将代码一行行删去,直到只留下执行到报错所必须的代码:

    def get_winningbid_detail(url, name):
        r = requests.get(url)
        r.encoding = 'utf-8'
        html = r.text
        soup = BeautifulSoup(html, 'lxml')

        ps = soup.find_all(text=re.compile('附件'))
        if len(ps) > 0:
            os.makedirs(os.path.join(download_dir, name), exist_ok=True)
            for p in ps:
                a_tab = p.find_next_sibling('a')
                if a_tab is not None:
                    link = homepage + a_tab['href']
                    localfilename = os.path.join(download_dir, name, a_tab.text)
                    # print(localfilename)
                    with open(localfilename, 'wb+'as sw:
                        sw.write(requests.get(link).content)
                    if localfilename.endswith('.doc'):
                        doc2docx(localfilename)

    反复读这段代码,并没有发现什么问题。

    因为有些网页的附件名称是相同的,例如 "公告.doc",所以我按每个网页的标题(在总览页面爬到的)分文件夹放置下载的文件,所以方法中传了一个 name 参数,而如果 name 参数传空,则不会报错。

    其实由此已经可以发现 bug 所在了,但我却没想到,又反复折腾了很久才发现,原来是文件名太长了。

    在 windows 下面,单个文件名的长度限制是 25,完整的路径长度(如 E:abc est.doc )限制是 260。路径最后有一个字符串结束符 '' 要占掉一个字符,所以完整路径实际限长是259。**

     
  • 相关阅读:
    lenovo thinkpad e40 is suite for ubuntu 10.04lts
    Ubuntu下思维导图软件Xmind
    myeclipse pluse service & exteration好像老报错,怎么用啊
    svn相关工作
    gssapiauthentication
    Java中的流
    dedecms的include文件夹是干什么的?
    dedecms利用memberlist标签调用自定义会员模型的会员信息
    织梦程序做的网站,会员下载的弹窗问题
    dede中弹出框函数function ShowMsg
  • 原文地址:https://www.cnblogs.com/gl1573/p/10114839.html
Copyright © 2020-2023  润新知