概述

Python 中可以读取 word 文件的库有 python-docx 和 pywin32。

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

  优点 缺点
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\test.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, 12, False, "", True, "", False, False, False, False)
    doc.Close()
    w.Quit()
    os.remove(path)
    return newpath

python-docx

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

import docx

fn = r'E:\abc\test.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 Office\Office12\2052\WDMAIN11.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\test.doc )限制是 260。路径最后有一个字符串结束符 '\0' 要占掉一个字符,所以完整路径实际限长是259。**

 

Python:读取 .doc、.docx 两种 Word 文件简述及“Word 未能引发事件”错误的更多相关文章

  1. 简介C#读取XML的两种方式

    简介C#读取XML的两种方式 作者: 字体:[增加 减小] 类型:转载 时间:2013-03-03 在程序中访问进而操作XML文件一般有两种模型,分别是使用DOM(文档对象模型)和流模型,使用DOM的 ...

  2. day2 编程语言介绍、Python运行程序的两种方式、变量

    一 编程语言介绍 1. 机器语言 用计算机能理解的二进制指令直接编写程序,直接控制硬件 2. 汇编语言 用英文标签取代二进制指令编写程序,本质也是直接控制硬件 3. 高级语言 用人能理解的表达方式去编 ...

  3. python读取与写入csv,txt格式文件

    python读取与写入csv,txt格式文件 在数据分析中经常需要从csv格式的文件中存取数据以及将数据写书到csv文件中.将csv文件中的数据直接读取为dict类型和DataFrame是非常方便也很 ...

  4. 用Python计算幂的两种方法,非递归和递归法

    用Python计算幂的两种方法: #coding:utf-8 #计算幂的两种方法.py #1.常规方法利用函数 #不使用递归计算幂的方法 """ def power(x, ...

  5. Python实现屏幕截图的两种方式

    Python实现屏幕截图的两种方式 使用windows API 使用PIL中的ImageGrab模块 下面对两者的特点和用法进行详细解释. 一.Python调用windows API实现屏幕截图 好处 ...

  6. Python 输出百分比的两种方式

    Python 输出百分比的两种方式 注: 在python3环境下测试. 方式1:直接使用参数格式化:{:.2%} {:.2%}: 显示小数点后2位 显示小数点后2位: >>> pri ...

  7. Python 下JSON的两种编解码方式实例解析

    概念   JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写.在日常的工作中,应用范围极其广泛.这里就介绍python下它的两种编解码方法: ...

  8. Git 的两种忽略文件方式 gitignore 和 exclude

    Git 的两种忽略文件方式 gitignore 和 exclude .gitignore 不用说了,大家都知道. 有一个 exclude 可能接触比较少. 知道这个功能后发现,用在服务器上非常方便,因 ...

  9. Python 发送 email 的两种方式

    Python发送email的两种方式,分别为使用登录邮件服务器.调用sendmail命令来发送三种方法 Python发送email比较简单,可以通过登录邮件服务来发送,linux下也可以使用调用sen ...

随机推荐

  1. PHP中的 $_SERVER 函数说明详解

    用php在开发软件的时候,我们经常用到 $_SERVER[]这个函数,今天就来讲下这个数组的值,方便以后使用: A: $_SERVER['ARGC'] #包含传递给程序的 命令行参数的个数(如果运行在 ...

  2. 和同门一起做的PHP网站

    用的是PHP语言开发,使用ThinkPHP框架,数据库是mysql  统计是用的站长统计,前端很多都是别人网 上扒下来的.css.js水平不高啊.服务器是香港恒创科技的,性价比还可以哦,而且还免备案. ...

  3. mapreduce shuffle 和sort 详解

        MapReduce 框架的核心步骤主要分两部分:Map 和Reduce.当你向MapReduce 框架提交一个计算作业时,它会首先把计算作业拆分成若干个Map 任务,然后分配到不同的节点上去执 ...

  4. python_字典 list_4

    >>> import string>>> import random #组合字符>>> x=string.ascii_letters+string ...

  5. C++之Binary Heap/Max Heap

    #include <iostream> #include <time.h> #include <random> using namespace std; //Bin ...

  6. c++ 输出精度

    1  保留小数点后**位 cout.flags(ios::fixed); cout.precision(4); //设置输出精度,

  7. Linux kernel的中断子系统之(八):softirq

    返回目录:<ARM-Linux中断系统>. 总结:中断分为上半部和下半部,上半部关中断:下半部开中断,处理可以延迟的事情.下半部有workqueue/softirq/tasklet三种方式 ...

  8. CLR、程序集、反射和控制反转

    以前面试包括自己学习的时候经常会碰到这3个东西,也查过相关介绍,晦涩难懂,虽然看完之后,当时勉强理解,不过过一段时间又忘了.其实这篇文章可以分两篇(clr.程序集)和(反射.控制反转)来写,但它们之间 ...

  9. localStorage和sessionStorage区别(包括同源的定义)

    localStorage和sessionStorage一样都是用来存储客户端临时信息的对象. 他们均只能存储字符串类型的对象(虽然规范中可以存储其他原生类型的对象,但是目前为止没有浏览器对其进行实现) ...

  10. Struts2(一)---struts2的环境搭建及实例

    刚刚接触struts2,有点懵懵懂懂,还是习惯于先写代码,然后慢慢来理解其中的思想. 这篇文章主要内容是strusts的环境搭建及通过一个简单的例子来理解到底是怎么使用struts来简化编程的. 1. ...