目录



>>> from helper import info; info()
页面更新时间: 2020-07-02 11:23:37
操作系统/OS: Linux-4.19.0-9-amd64-x86_64-with-debian-10.4 ;Python: 3.7.3

5.3. 微软DOCX文档

利用 python-docx 模块,Python可以创建和修改微软 DOCX 文档,它带有.docx文件扩展名。 运行 pip install python-docx ,可以安装该模块。

注意

OSI参考模型最初是在1983年由国际标准化组织出版,标准号为 ISO 7498。 在第一次用 pip 安装 python-docx 时,注意要安装python-docx ,而不是 docx 。 安装名称 docx 是指另一个模块,本书没有介绍。 但是,在导入 python-docx 模块时,需要执行 import docx ,而不是 import python-docx

如果你没有Word 软件,LibreOffice Writer 和 OpenOffice Writer 都是免费的替代软件,它们 可以在Windows、OS X 和Linux 上打开.docx 文件。 可以分别从 https://www.libreoffice.org 和http://openoffice.org 下载它们。python-docx 的完整文档在 https://python-docx.readthedocs.org/ 。 尽管有针对OS X 平台的Word 版本,但本章将使用 Windows 平台的Word。和纯文本相比, .docx 文件有很多结构。这些结构在python-docx 中用3种不同的类型来表示。在最高一层,Document 对象表示整个文档。Document 对象包含一个 Paragraph 对象的列表,表示文档中的段落 (用户在Word 文档中输入时,如果按下回车,新的段落 就开始了)。每个Paragraph 对象都包含一个Run 对象 的列表。图13-4 中的单句段落有4 个Run 对象。

image0

Word 文档中的文本不仅仅是字符串。它包含与之相关的 字体、大小、颜色和其他样式信息。在Word 中,样式是 这些属性的集合。一个 Run 对象是相同样式文本的 延续。当文本样式发生改变时,就需要一个新的 Run 对象。

读取Word文档

让我们尝试使用 python-docx 模块。从 http://nostarch.com/automatestuff/ 下载 demo.docx,并将它保存在当前工作目录中。 然后在交互式环境中输入以下代码:

>>> import docx
>>> doc = docx.Document('demo.docx')
>>> len(doc.paragraphs)
7
>>> doc.paragraphs[0].text
'Document Title'
>>> for x in doc.paragraphs:
>>>     print(x.text)
Document Title
A plain paragraph with some bold and some italic
Heading, level 1
Intense quote
first item in unordered list
first item in ordered list
>>> doc.paragraphs[1].text
'A plain paragraph with some bold and some italic'
>>> len(doc.paragraphs[1].runs)
5
>>> doc.paragraphs[1].runs[0].text
'A plain paragraph with'
>>> doc.paragraphs[1].runs[1].text
' some '
>>> doc.paragraphs[1].runs[2].text
'bold'
>>> doc.paragraphs[1].runs[3].text
' and some '

在1行,我们在Python中打开了一个.docx文件, 调用 docx.Document() ,传入文件名 demo.docx。这将返回一个 Document 对象, 它有 paragraphs 属性,是 Paragraph 对象 的列表。如果我们对 doc.paragraphs 调用 len(), 将返回7。这告诉我们,该文档有7个 Paragraph 对象。 每个 Paragraph 对象都有一个 text 属性,包含 该段中文本的字符串(没有样式信息)。这里,第一个 text 属性包含 'DocumentTitle',第二个包含 'A plain paragraph with some bold and some italic'

每个 Paragraph 对象也有一个 runs 属性,它是 Run 对象的列表。 Run 对象也有一个 text 属性, 包含那个延续中的文本。我们看看第二个 Paragraph 对象 中的 text 属性, 'A plain paragraph with some bold and some italic'。 对这个 Paragraph 对象调用 len() ,结果告诉 我们有4个 Run 对象第一个对象包含 'A plain paragraph with some' 。然后,文本变为 粗体样式,所以 'bold' 开始了一个新的 Run 对象。 在这之后,文本又回到了非粗体的样式,这导致了第三个 Run 对象,'and some' 。最后,第四个对象 包含 'italic' ,是斜体样式。

有了 python-docx ,Python程序就能从.docx文件中 读取文本,像其他的字符串值一样使用它。

从 DOCX 文件中取得完整的文本

如果你只关心Word文档中的文本,不关心样式信息, 就可以利用 getText() 函数。它接受一个.docx文件名, 返回其中文本的字符串。打开一个新的文件编辑器 窗口,输入以下代码,并保存为 readDocx.py :

>>> import docx
>>>
>>> def getText(filename):
>>>     doc = docx.Document(filename)
>>>     fullText =[]
>>>     for para in doc.paragraphs:
>>>         fullText.append(para.text)
>>>     return'\n'.join(fullText)

getText()函数打开了 Word文档,循环遍历 paragraphs 列表中的所有 Paragraph 对象,然后将它们的文本添加到 fullText列表中。 循环结束后,fullText 中的字符串连接在一起, 中间以换行符分隔。

readDocx.py 程序可以像其他模块一样导入。 现在如果你只需要Word文档中的文本,就可以 输入以下代码:

>>> import readDocx
>>> readDocx.getText('demo.docx')
'Document TitlenA plain paragraph with some bold and some italicnHeading, level 1nIntense quotenfirst item in unordered listnfirst item in ordered listnn'
>>> print(readDocx.getText('demo.docx'))
Document Title
A plain paragraph with some bold and some italic
Heading, level 1
Intense quote
first item in unordered list
first item in ordered list

也可以调整 getText() ,在返回字符串之前 进行修改。例如,要让每一段缩进,就将文件中 的 append()调用替换为:

fullText.append( ’ ’ + para.text)

要在段落之间增加空行,就将 join() 调用 代码改成:

return ‘:raw-latex:`\n`:raw-latex:`n `’.join(fullText)

可以看到,只需要几行代码,就可以写出函数,读取.docx文件, 根据需要返回它的内容字符串。

设置 ParagraphRun 对象的样式

在Windows平台的Word中,你可以按下Ctrl-Alt-Shift-S, 显示样式窗口并查看样式,如图13-5所示。在OSX上, 可以点击View→Styles菜单项,查看样式窗口。

Word和其他文字处理软件利用样式,保持类似类型的文本 在视觉展现上一致,并易于修改。例如,也许你希望将 内容段落设置为11点,Times New Roman ,左对齐, 右边不对齐的文本。可以用这些设置创建一种样式, 将它赋给所有的文本段落。然后,如果稍后想改变文档中 所有内容段落的展现形式,只要改变这种样式,所有 段落都会自动更新。

image0

图13-5在Windows平台上按下Ctrl-Alt-Shifl-S,显示样式窗口

对于Word文档,有3种类型的样式:段落样式可以应用于 Paragraph 对象,字符样式可以应用于 Run 对象, 链接的样式可以应用于这两种对象。可以将 ParagraphRun对象的 style 属性设置为一个字符串,从而 设置样式。这个字符串应该是一种样式的名称。如果 style 被设置为 None ,就没有样式与 ParagraphRun 对象关联。

默认Word样式的字符串如下:

image1

在设置 style 属性时,不要在样式名称中使用空格。 例如,样式名称可能是 Subtle Emphasis ,你应该将 属性设置为字符串 'SubtleEmphasis' ,而不是 'Subtle Emphasis' 。 包含空格将导致Word误读 样式名称,并且应用失败。

如果对 Run 对象应用链接的样式,需要在样式名称 末尾加上 'Char' 。例如,对 Paragraph 对象 设置 Quote 链接的样式,应该使用 paragraphObj.style='Quote'。但对于 Run 对象, 应该使用 runObj.style = 'QuoteChar'

在当前版本的python-docx(0.7.4)中,只能使用默认的 Word样式,以及打开的文件中已有的样式,不能创建新的 样式,但这一点在将来的模块版本中可能会改变。

创建带有非默认样式的Word文档

如果想要创建的Word文档使用默认样式以外的样式, 就需要打开一个空白Word文档,通过点击样式窗口 底部的New Style按钮,自己创建样式(图13-6展示 了Windows平台上的情形)。

image2

图13-6新建样式按扭(左边)和“根据格式设置创 建新样式”对话框(右边)

这将打开“Creat New Style from Formatting” 对话框,在这里可以输入新样式。然后,回到交互 式环境,用 docx.Document() 打开这个空白 Word文档,利用它作为Word文档的基础。这种样式 的名称现在就可以被 python-docx 使用了。

Run 属性

通过 text 属性, Run 可以进一步设置样式。 每个属性都可以被设置为3个值之一:True (该属性 总是启用,不论其他样式是否应用于该 Run )、 False (该属性总是 禁用)或 None (默认 使用该 Run 被设置的任何属性)。

表13-1列出了可以在 Run 对象上设置的 text 属性。

表13-1 Run 对象的 text 属性

属性

描述

bold

文本以粗体出现

italic

文本以斜体出现

underline

文本带下划线

strike

文本带删除线

double_strike

文本带双删除线

all_caps

文本以大写首字母出现

small_caps

文本以大写首字母出现,小写字母小两个点

shadow

文本带阴影

outline

文本以轮廓线出现,而不是实心

rtl

本从右至左书写

imprint

文本以刻入页面的方式出现

emboss

文本以凸出页面的方式出现

例如,为了改变 demo.docx 的样式, 在交互式环境中输入以下代码:

>>> doc = docx.Document('demo.docx')
>>> doc.paragraphs[0].text
'Document Title'
>>> doc.paragraphs[0].style
_ParagraphStyle('Title') id: 140543097339632
>>> doc.paragraphs[0].style = 'Normal'
>>> doc.paragraphs[1].text
'A plain paragraph with some bold and some italic'
>>> (doc.paragraphs[1].runs[0].text, doc.paragraphs[1].runs[1].text, doc.
>>> paragraphs[1].runs[2].text, doc.paragraphs[1].runs[3].text)
('A plain paragraph with', ' some ', 'bold', ' and some ')
>>> doc.paragraphs[1].runs[0].style = 'QuoteChar'
>>> doc.paragraphs[1].runs[1].underline = True
>>> doc.paragraphs[1].runs[3].underline = True
>>> doc.save('restyled.docx')
/home/shaopp/.local/lib/python3.5/site-packages/docx/styles/styles.py:139: UserWarning: style lookup by style_id is deprecated. Use style name as key instead.
  return self._get_style_id_from_style(self[style_name], style_type)

这里,我们使用了 textstyle 属性, 以便容易地看到文档的段落中有什么。我们可以 看到,很容易将段落划分成 Run ,并单独访问 每个 Run 。所以我们取得了第二段中的第一、 第二和第四个 Run ,设置每个 Run 的样式, 将结果保存到一个新文档。

文件顶部的单词 Document Title 将具有 Normal 样式,而不是 Title 样式。针对文本 A plain paragraph的 Run 对象,将具有 QuoteChar 样式。针对单词 bolditalic 的两个 Run 对象,它们的 underline 属性设置 为 True 。图13-7展示了文件中段落和 Run 的 样式看起来的样子。

image0

图 13-7 restyled.docx 文件

访问 [https://python-docx.readthedocs.org/en/latest/user/styles.html] (https://python-docx.readthedocs.org/en/latest/user/styles.html), 你可以看到 python-docx 使用样式的更完整文档。

写入Word文档

在交互式环境中输入以下代码:

>>> import docx
>>> doc = docx.Document()
>>> doc.add_paragraph('Hello world')
<docx.text.paragraph.Paragraph at 0x7fd2bc24c7f0>
>>> doc.save('helloworld.docx')

要创建自己的.docx文件,就调用docx.Document(), 返回一个新的、空白的Word Document对象。 Document对象的add_paragraph()方法将一段新 文本添加到文档中,并返回添加的 Paragraph对象的引用。 在添加完文本之后,向Document对象的 save() 方法传入一个文件名字符串,将Document对象保存到文件。

这将在当前工作目录中创建一个文件,名为 helloworld.docx 。如果打开它,就像图13-8的样子。

image0

图 13-8 利用 add_paragraph(’Hello world!’)创建的Word文档

可以用新的段落文本,再次调用 add_paragraph()方法, 添加段落。或者,要在已有段落的末尾添加文本,可以调用 Paragraph 对象的 add_run() 方法,向它传入一 个字符串。在交互式环境中输入以下代码:

>>> import docx
>>> doc = docx.Document()
>>> doc.add_paragraph('Hello world!')
<docx.text.paragraph.Paragraph at 0x7fd2bc24ca20>
>>> paraObjl = doc.add_paragraph('This is a second paragraph.')
>>> para0bj2 = doc.add_paragraph('This is a yet another paragraph.')
>>> paraObjl.add_run('This text is being added to the second paragraph.')
<docx.text.run.Run at 0x7fd2bc2397f0>
>>> doc.save('multipleParagraphs.docx')

得到的文本如图13-9所示。请注意,文本This text is being added to the second paragraph.被添加到paraObjl 中的Paragraph对象中, 它是添加到doc中的第二段。add_paragraph()add_run() 分别返回 ParagraphRun对象,这样 你就不必多花一步来提取它们。

image0

图13-9添加了多个ParagraphRun对象的文档

要记住,对于python-docx的0.5.3版本,新的Paragraph 对象只能添加在文档的末尾,新的Run对象只能添加 在Paragraph对象的末尾。

可以再次调用 save() 方法,保存所做的变更。

add_paragraph()add_run()都接受可选的第二个参数, 它是表示ParagraphRun对象样式的字符串。例如:

>>> doc.add_paragraph('Hello world!', 'Title')
<docx.text.paragraph.Paragraph at 0x7fd2bc227a90>

这一行添加了一段,文本是 Hello world!,样式是`Title`` 。

添加标题

调用 add_heading() 将添加一个段落,并使用一种标题样式。 在交互式环境中输入以下代码:

>>> doc = docx.Document()
>>> doc.add_heading('Header 0', 0)
<docx.text.paragraph.Paragraph at 0x7fd2bc1f0be0>
>>> doc.add_heading('Header 1', 1)
<docx.text.paragraph.Paragraph at 0x7fd2bc1f0b38>
>>> doc.add_heading('Header 2', 2)
<docx.text.paragraph.Paragraph at 0x7fd2bc24c550>
>>> doc.add_heading('Header 3', 3)
<docx.text.paragraph.Paragraph at 0x7fd2bc24cac8>
>>> doc.add_heading('Header 4', 4)
<docx.text.paragraph.Paragraph at 0x7fd2bc1f60b8>
>>> doc.save('headings.docx')

add_heading()的参数,是一个标题文本的字符串, 以及一个从0到4的整数。整数0表示标题是 Title 样式, 这用于文档的顶部。整数1到4是不同的标题层次,1是主要 的标题,4 是最低层的子标题。add_heading() 返回一个 Paragraph对象,让你不必多花一步从 Document对象中提取它。

得到的headings.docx文件如图13-10所示。

image0

图13-10 带有标题0到4的headings.docx文档

添加换行符和换页符

要添加换行符(而不是开始一个新的段落),可以在 Run 对象上调用 add_break() 方法,换行符将出现在它 后面。如果希望添加换页符,可以将 docx.text.WD_BREAK.PAGE 作为唯一的参数,传递给 add_break() ,就像下面代 码中间所做的一样:

>>> doc = docx.Document()
>>> doc.add_paragraph('This is on the first page!')
<docx.text.paragraph.Paragraph at 0x7fd2bc1f6400>

doc.paragraphs[0].runs[0].add_break(docx.text.WD_BREAK_PAGE) doc.add_paragraph(‘This is on the second page!’)

>>> doc.save('twoPage.docx')

这创建了一个两页的Word文档,第一页上是 This is on the first page!,第二页上是 This is on the second page!。虽然在文本 This is on the first page!之后,第一页还 有大量的空间,但是我们在第一段的第一个Run 之后插入分页符,强制下一段落出现在新的页面中。

添加图像

Document 对象有一个 add_picture()方法, 让你在文档末尾添加图像。假定当前工作目录中有一个 文件 zophie.png ,你可以输入以下代码,在 文档末尾添加 zophie.png ,宽度为1英寸, 高度为4厘米(Word可以同时使用英制和公制单位):

>>> doc.add_picture('zophie.png', width=docx.shared.Inches(1),height=docx.shared.Cm(4))
<docx.shape.InlineShape at 0x7fd2bc1f4240>

第一个参数是一个字符串,表示图像的文件名。可选的 widthheight 关键参数,将设置该图像在 文档中的宽度和高度。如果省略,宽度和高度将采用默认 即该图像的正常尺寸。

你可能愿意用熟悉的单位来指定图像的高度和宽度,诸如 英寸或厘米。所以在指定 widthheight 关键字 参数时,可以使用docx_shared.Inches()docx.shared.Cm() 函数。

小结

Word文档更可靠,可以用 python-docx 模块来读取。可以通过 ParagraphRun 对象来操作Word文档中的文本。可以设置 这些对象的样式,尽管必须使用默认的样式,或文档中已有的样式。 可以添加新的段落、标题、换行换页符和图像,尽管只能在文档的 末尾。

在处理PDF和Word文档时有很多限制,这是因为这些格式的本意是 很好地展示给人看,而不是让软件易于解析。下一章将探讨存储 信息的另外两种常见格式:JSON和CSV文件。这些格式是设的。你会看到,Python处理这些格式要容易得多。


>>> import helper; helper.info()
页面更新时间: 2019-03-02 09:21:53
操作系统/OS: Linux-4.9.0-8-amd64-x86_64-with-debian-9.8
Python: 3.5.3