- 内容提要
- 作者简介
- 技术评审者简介
- 致谢
- 译者序 会编程的人不一样
- 前言
- 本书的读者对象
- 编码规范
- 什么是编程
- 本书简介
- 下载和安装 Python
- 启动 IDLE
- 如何寻求帮助
- 聪明地提出编程问题
- 小结
- 第一部分 Python 编程基础
- 第1章 Python 基础
- 第2章 控制流
- 第3章 函数
- 第4章 列表
- 第5章 字典和结构化数据
- 第6章 字符串操作
- 第二部分 自动化任务
- 第7章 模式匹配与正则表达式
- 第8章 读写文件
- 第9章 组织文件
- 第10章 调试
- 第11章 从 Web 抓取信息
- 第12章 处理 Excel 电子表格
- 第13章 处理 PDF 和 Word 文档
- 第14章 处理 CSV 文件和 JSON 数据
- 第15章 保持时间、计划任务和启动程序
- 第16章 发送电子邮件和短信
- 第17章 操作图像
- 第18章 用 GUI 自动化控制键盘和鼠标
- 附录A 安装第三方模块
- 附录B 运行程序
- 附录C 习题答案
13.3 Word 文档
利用python-docx模块,Python可以创建和修改Word文档,它带有.docx文件扩展名。运行pip install python-docx,可以安装该模块(附录A介绍了安装第三方模块的细节)。
注意
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对象。
图13-4 一个Paragraph对象中识别的Run对象
Word文档中的文本不仅仅是字符串。它包含与之相关的字体、大小、颜色和其他样式信息。在Word中,样式是这些属性的集合。一个Run对象是相同样式文本的延续。当文本样式发生改变时,就需要一个新的Run对象。
13.3.1 读取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' ❹ >>> doc.paragraphs[1].text 'A plain paragraph with some bold and some italic' ❺ >>> len(doc.paragraphs[1].runs) 4 ❻ >>> doc.paragraphs[1].runs[0].text 'A plain paragraph with some ' ❼ >>> doc.paragraphs[1].runs[1].text 'bold' ❽ >>> doc.paragraphs[1].runs[2].text ' and some ' ❾ >>> doc.paragraphs[1].runs[3].text 'italic'
在❶行,我们在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文件中读取文本,像其他的字符串值一样使用它。
13.3.2 从.docx文件中取得完整的文本
如果你只关心Word文档中的文本,不关心样式信息,就可以利用getText()函数。它接受一个.docx文件名,返回其中文本的字符串。打开一个新的文件编辑器窗口,输入以下代码,并保存为readDocx.py:
#! python3 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 >>> 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 '\n\n'.join(fullText)
可以看到,只需要几行代码,就可以写出函数,读取.docx文件,根据需要返回它的内容字符串。
13.3.3 设置Paragraph和Run对象的样式
在Windows平台的Word中,你可以按下Ctrl-Alt-Shift-S,显示样式窗口并查看样式,如图13-5所示。在OS X上,可以点击ViewStyles菜单项,查看样式窗口。
Word和其他文字处理软件利用样式,保持类似类型的文本在视觉展现上一致,并易于修改。例如,也许你希望将内容段落设置为11点,Times New Roman,左对齐,右边不对齐的文本。可以用这些设置创建一种样式,将它赋给所有的文本段落。然后,如果稍后想改变文档中所有内容段落的展现形式,只要改变这种样式,所有段落都会自动更新。
图13-5 在Windows平台上按下Ctrl-Alt-Shift-S,显示样式窗口
对于Word文档,有3种类型的样式:段落样式可以应用于Paragraph对象,字符样式可以应用于Run对象,链接的样式可以应用于这两种对象。可以将Paragraph和Run对象的style属性设置为一个字符串,从而设置样式。这个字符串应该是一种样式的名称。如果style被设置为None,就没有样式与Paragraph或Run对象关联。
默认Word样式的字符串如下:
在设置style属性时,不要在样式名称中使用空格。例如,样式名称可能是Subtle Emphasis,你应该将属性设置为字符串'SubtleEmphasis',而不是'Subtle Emphasis'。包含空格将导致Word误读样式名称,并且应用失败。
如果对Run对象应用链接的样式,需要在样式名称末尾加上'Char'。例如,对Paragraph对象设置Quote链接的样式,应该使用paragraphObj.style = 'Quote'。但对于Run对象,应该使用runObj.style = 'QuoteChar'。
在当前版本的python-docx (0.7.4)中,只能使用默认的Word样式,以及打开的文件中已有的样式,不能创建新的样式,但这一点在将来的模块版本中可能会改变。
13.3.4 创建带有非默认样式的Word文档
如果想要创建的Word文档使用默认样式以外的样式,就需要打开一个空白Word文档,通过点击样式窗口底部的New Style按钮,自己创建样式(图13-6展示了Windows平台上的情形)。
图13-6 新建样式按扭(左边)和“根据格式设置创建新样式”对话框(右边)
这将打开“Creat New Style from Formatting”对话框,在这里可以输入新样式。然后,回到交互式环境,用docx.Document()打开这个空白Word文档,利用它作为Word文档的基础。这种样式的名称现在就可以被python-docx使用了。
13.3.5 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 'Title' >>> 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 ', 'italic') >>> 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')
这里,我们使用了text和style属性,以便容易地看到文档的段落中有什么。我们可以看到,很容易将段落划分成Run,并单独访问每个Run。所以我们取得了第二段中的第一、第二和第四个Run,设置每个Run的样式,将结果保存到一个新文档。
文件顶部的单词Document Title将具有Normal样式,而不是Title样式。针对文本A plain paragraph的Run对象,将具有QuoteChar样式。针对单词bold和italic的两个Run对象,它们的underline属性设置为True。图13-7展示了文件中段落和Run的样式看起来的样子。
图13-7 restyled.docx文件
访问https://python-docx.readthedocs.org/en/latest/user/styles.html,你可以看到,python-docx使用样式的更完整文档。
13.3.6 写入Word文档
在交互式环境中输入以下代码:
>>> import docx >>> doc = docx.Document() >>> doc.add_paragraph('Hello world!') < docx.text.Paragraph object at 0x0000000003B56F60> >>> doc.save('helloworld.docx')
要创建自己的.docx文件,就调用docx.Document(),返回一个新的、空白的Word Document对象。Document对象的add_paragraph()方法将一段新文本添加到文档中,并返回添加的Paragraph对象的引用。在添加完文本之后,向Document对象的save()方法传入一个文件名字符串,将Document对象保存到文件。
这将在当前工作目录中创建一个文件,名为helloworld.docx。如果打开它,就像图13-8的样子。
图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 object at 0x000000000366AD30> >>> paraObj1 = doc.add_paragraph('This is a second paragraph.') >>> paraObj2 = doc.add_paragraph('This is a yet another paragraph.') >>> paraObj1.add_run(' This text is being added to the second paragraph.') < docx.text.Run object at 0x0000000003A2C860> >>> doc.save('multipleParagraphs.docx')
得到的文本如图13-9所示。请注意,文本This text is being added to the second paragraph.被添加到paraObj1中的Paragraph对象中,它是添加到doc中的第二段。add_paragraph()和add_run()分别返回Paragraph和Run对象,这样你就不必多花一步来提取它们。
图13-9 添加了多个Paragraph和Run对象的文档
要记住,对于python-docx的0.5.3版本,新的Paragraph对象只能添加在文档的末尾,新的Run对象只能添加在Paragraph对象的末尾。
可以再次调用save()方法,保存所做的变更。
add_paragraph()和add_run()都接受可选的第二个参数,它是表示Paragraph或Run对象样式的字符串。例如:
>>> doc.add_paragraph('Hello world!', 'Title')
这一行添加了一段,文本是Hello world!,样式是Title。
13.3.7 添加标题
调用add_heading()将添加一个段落,并使用一种标题样式。在交互式环境中输入以下代码:
>>> doc = docx.Document() >>> doc.add_heading('Header 0', 0) < docx.text.Paragraph object at 0x00000000036CB3C8> >>> doc.add_heading('Header 1', 1) < docx.text.Paragraph object at 0x00000000036CB630> >>> doc.add_heading('Header 2', 2) < docx.text.Paragraph object at 0x00000000036CB828> >>> doc.add_heading('Header 3', 3) < docx.text.Paragraph object at 0x00000000036CB2E8> >>> doc.add_heading('Header 4', 4) < docx.text.Paragraph object at 0x00000000036CB3C8> >>> doc.save('headings.docx')
add_heading()的参数,是一个标题文本的字符串,以及一个从0到4的整数。整数0表示标题是Title样式,这用于文档的顶部。整数1到4是不同的标题层次,1是主要的标题,4是最低层的子标题。add_heading()返回一个Paragraph对象,让你不必多花一步从Document对象中提取它。
得到的headings.docx文件如图13-10所示。
图13-10 带有标题0到4的headings.docx文档
13.3.8 添加换行符和换页符
要添加换行符(而不是开始一个新的段落),可以在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 object at 0x0000000003785518> ❶ >>> doc.paragraphs[0].runs[0].add_break(docx.text.WD_BREAK.PAGE) >>> doc.add_paragraph('This is on the second page!') < docx.text.Paragraph object at 0x00000000037855F8> >>> doc.save('twoPage.docx')
这创建了一个两页的Word文档,第一页上是This is on the first page!,第二页上是This is on the second page!。虽然在文本This is on the first page!之后,第一页还有大量的空间,但是我们在第一段的第一个Run之后插入分页符,强制下一段落出现在新的页面中❶。
13.3.9 添加图像
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 object at 0x00000000036C7D30>
第一个参数是一个字符串,表示图像的文件名。可选的width和height关键字参数,将设置该图像在文档中的宽度和高度。如果省略,宽度和高度将采用默认值,即该图像的正常尺寸。
你可能愿意用熟悉的单位来指定图像的高度和宽度,诸如英寸或厘米。所以在指定 width 和 height 关键字参数时,可以使用 docx.shared.Inches()和docx.shared.Cm()函数。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论