概述

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\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. Solr(六)Solr索引数据存放到HDFS下

    Solr索引数据存放到HDFS下 一 新建solr core hdfs 方法:http://www.cnblogs.com/Matchman/p/7287385.html 二 修改solrconfig ...

  2. Hive中Join的原理和机制

    转自:http://lxw1234.com/archives/2015/06/313.htm 笼统的说,Hive中的Join可分为Common Join(Reduce阶段完成join)和Map Joi ...

  3. C#之Redis所欲为

    一 Redis是一种支持多种数据结构的键值对数据库 1.1Redis下载地址 :https://github.com/MicrosoftArchive/Redis 建议下载 .msi结尾的应用程序进行 ...

  4. Selenium自动化测试-unittest单元测试框架

    一.Pyhon工作原理-- 核心概念:test case, testsuite, TestLoder,TextTestRunner,TextTestResult, test fixture TestC ...

  5. popup_layer插件示例

    导入popup_layer.js插件 设置好显示的div: <div class="main" id="showImg" style="disp ...

  6. redis两种持久化方法对比分析

    1.前言 最近在项目中使用到Redis做缓存,方便多个业务进程之间共享数据.由于Redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就全丢失了,于是需要开启redis的持久化功能, ...

  7. SQL关于IN和EXISTS的用法和区别的比较

    1.exist,not exist一般都是与子查询一起使用. In可以与子查询一起使用,也可以直接in (a,b.....).2.exist会针对子查询的表使用索引. not exist会对主子查询都 ...

  8. springboot+activemq中引入重发机制

    一.简介 在使用activemq消息中间件进行消息队列传输时,总会由于各种原因导致消息失败. 一个经典的场景是一个生成者向Queue中发消息,里面包含了一组邮件地址和邮件内容.而消费者从Queue中将 ...

  9. Java NIO Channel to Channel Transfers通道传输接口

    原文链接:http://tutorials.jenkov.com/java-nio/channel-to-channel-transfers.html 在Java NIO中如果一个channel是Fi ...

  10. asp.net mvc 使用 Autocomplete 实现类似百度,谷歌动态搜索条提示框。

    Autocomplete是一个Jquery的控件,用法比较简单. 大家先看下效果: 当文本框中输入内容,自动检索数据库给出下拉框进行提示功能. 需要用此控件大家先到它的官方网站进行下载最新版本: ht ...