作者:新干果来源:AirPython(公众号)上一篇总结了Word中写入数据的一些常用操作。详见聊聊python办公自动化Word(上)。相比写数据,读数据也很实用!本文将讲述如何完整读取Word文档中的数据,并指出一些需要注意的地方。基本信息我们也使用python-docx依赖库来阅读Word文档。首先我们读取文档的基本信息,分别是:章节、页边距、页眉页脚边距、页面宽高、页面方向等。在获取文档的基本信息之前,我们通过构造一个文档对象Document文档路径。fromdocximportDocumentSourcefiledirectoryself.word_path='./output.docx'打开文档并建立一个文档对象self.doc=Document(self.word_path)1-Section(节)1.获取节信息注意:Sections可以设置本页的大小、页眉和页脚msg_sections=self.doc.sectionsprint("Chapterlist:",msg_sections)numberofchaptersprint('numberofchapters:',len(msg_sections))2-页边距(Pagemargin)通过章节对象的left_margin、top_margin、right_margin、bottom_margin属性值,可以得到当前章节的左边距、上边距、右边距、下边距defget_page_margin(section):"""获取一页的页边距(EMU):paramsection::return:"""#对应:leftmargin,topmargin,rightmargin,bottommarginleft,top,right,bottom=section.left_margin,section.top_margin,section.right_margin,section.bottom_margin返回left,top,right,bottom2.页边距信息first_section=msg_sections[0]left,top,right,bottom=get_page_margin(first_section)print('左边距:',left,",topmargin:",top,",Rightmargin:",right,",底部边距:",bottom)返回值的单位为EMU,与厘米和英尺的换算关系如下:3-页眉页脚边距:header_distance和footermarginsDistance:footer_distancedefget_header_footer_distance(section):"""获取页眉和页脚边距:param部分::return:"""#分别对应页眉margin和页脚marginheader_distance,footer_distance=section.header_distance,section.footer_distancereturnheader_distance,footer_distance3,页眉页脚marginheader_distance,footer_distance_header_fget(print)'页眉margin:',header_distance,",footermargin:",footer_distance)4-页面宽度和高度pagewidth:page_widthpageheight:page_heightdefget_page_size(section):"""获取页面宽度、高度:paramsection::return:"""#对应页面宽度page_width,page_height=section.page_width,section.page_heightreturnpage_width,page_height4,pagewidth,heightpage_width,page_height=get_page_size(print)',page_width,",pageheight:",page_height)5-页面方向(PageOrientation)页面方向分为:水平和垂直使用章节对象的orientation属性获取一个章节的页面方向defget_page_orientation(section):"""获取页面orientation:paramsection::return:"""returnsection.orientation5.页面方向类型:class'docx.enum.base.EnumValuecontains:PORTRAIT(0),LANDSCAPE(1)page_orientation=get_page_orientation(first_section)print("pageorientation:",page_orientation)同样可以直接使用该属性设置章节的方向fromdocx.enum.sectionimportWD_ORIENT设置页面方向(水平,垂直)设置为水平first_section.orientation=WD_ORIENT.LANDSCAPE设置为verticalfirst_section.orientation=WD_ORIENT.PORTRAITself.doc.save(self.word_path)Paragraph使用document对象的paragraphs属性获取文档中的所有段落注:此处获取的段落donotincludeheadersandfooters,Paragraphsinthetable获取文档对象中的所有段落,默认不包括:header,footer,paragraphsinthetableparagraphs=self.doc.paragraphs1,段落数paragraphs_length=len(paragraphs)print('AtotalofContains:{}paragraphs'.format(paragraphs_length))1-段落内容我们可以遍历文档中所有的段落列表,通过段落对象的text属性0,读取所有段落数据contents=[paragraph.textforparagraphinself.doc.paragraphs]print(contents)2-段落格式通过上一篇我们知道段落也是有格式的。使用paragraph_format属性获取段落的基本格式信息,包括:对齐方式、左右缩进、Linespacing、段落间距等2、获取一个段落的格式信息paragraph_someone=paragraphs[0]2.1段落内容content=paragraph_someone.textprint('paragraphcontent:',content)2.2段落格式paragraph_format=paragraph_someone.paragraph_format2.2.1alignmentalignment=paragraph_format.alignmentprint('段落对齐:',alignment)2.2.2左右缩进left_indent,right_indent=paragraph_format.left_indent,paragraph_format.right_indentprint('段落左缩进:',left_indent,",rightindent:",right_indent)2.2.3firstlineindentfirst_line_indent=paragraph_format.first_line_indentprint('paragraphfirstlineindent:',first_line_indent)2.2.4行间距line_spacing=paragraph_format.line_spacingprint('paragraphlinespacing:',line_spacing)2.2.5段前后间距space_before,space_after=paragraph_format.space_before,paragraph_format.space_afterprint('段落前后间距分别为:',space_before,',',space_after)textblock-RuntextblockRun是段落的一部分,所以要得到textblock的信息,首先要得到一个段落实例对象以文本块的基本信息和字体格式信息为例1-文本块的基本信息我们使用runs属性eoftheparagraphobject获取段落中所有的文本块对象defget_runs(paragraph):"""获取段落下的所有文本块信息,包括:编号,内容列表:paramparagraph::return:"""#段落对象中包含的文本块runruns=paragraph.runs#数量runs_length=len(runs)#文本块内容runs_contents=[run.textforruninruns]returnruns,runs_length,runs_contents2-文本块格式信息Atext块是文档中的最小文本单元。使用文本块对象的字体属性获取其字体属性并设置文本块格式属性是一一对应的,可以得到字体名称、字号、颜色、粗体、斜体等2、文本块格式信息包括:一个字的字号、字号、颜色、是否加粗等某些文本块字体属性run_someone_font=runs[0].font字体名称font_name=run_someone_font.nameprint('fontname:',font_name)字体颜色(RGB)font_color=run_someone_font.color.rgbprint('字体颜色:',font_color)print(type(font_color))字体大小font_size=run_someone_font.sizeprint('fontsize:',font_size)是否加粗True:bold;None/False:无粗体font_bold=run_someone_font.boldprint('是否斜体:',font_bold)是否斜体True:一致;None/False:非斜体font_italic=run_someone_font.italicprint('Isitalic:',font_italic)UnderlineTrue:带下划线;无/假:字体无下划线font_underline=run_someone_font.underlineprint('withunderline:',font_underline)删除线/双删除线无/假:字体没有删除线font_strike=run_someone_font.strikefont_double_strike=run_someone_font。double_strikeprint('withstrikethrough:',font_strike,"nwithdoublestrikethrough:",font_double_strike)表格文档对象的tables属性可以得到当前文档中的所有表格对象文档中的所有表格对象tables=self.doc。tables1.表的个数table_num=len(tables)print('文档中包含的表的个数Quantity:',table_num)1-表中的所有数据有2种方法可以获取表中的所有数据。第一种方式:通过遍历文档中的所有表格,然后按行和单元格遍历,最后通过单元格的text属性得到所有数据单元格的文本内容2.读取所有表格数据Alltableobjectstables=[tablefortableinself.doc.tables]print('Thecontentsare:')fortableintables:forrowintable.rows:forcellinrow.cells:print(cell.text,end='')print()print('n')另一种方式是利用表格对象的_cells属性获取表格中的所有单元格,然后遍历获取单元格的单元格值defget_table_cell_content(table):"""读取表中所有单元格的内容:paramtable::return:"""#所有单元格cells=table._cellscell_size=len(cells)#所有单元格内容content=[cell.textforcellincells]returncontent2-tablestyle3、表格样式名称TableGridtable_someone=tables[0]style=table_someone.style.nameprint("tablestyle:",style)3-表格行数,列数table.rows:行数据吧表中的eration对象table.columns:表中的列数据迭代对象defget_table_size(table):"""获取表的行号和列号:paramtable:::return:"""#几行,几行列row_length,column_length=len(table.rows),len(table.columns)返回row_length,column_length4-行数据,列数据有时候,我们需要根据行或列获取所有数据defget_table_row_datas(table):"""获取表中的行数据:paramtable::return:"""rows=table.rowsdatas=[]#获取每一行的单元格的数据组成列表,并将其添加到结果列表中forrowinrows:datas.append([cell.textforcellinrow.cells])returndatasdefget_table_column_datas(table):"""获取表中的列数据:paramtable::return:"""columns=table.columnsdatas=[]#每列获取该单元格的数据构成列表并添加到结果中listforcolumnincolumns:datas.append([cell.textforcellincolumn.cells])returndataspictures有时候,我们需要将Word文档中的图片下载到本地。Word文档实际上是一个压缩文件。使用解压工具后,我们发现文档中包含的图片都是/word/media/目录下文档图片的解压方法有两种,分别是:解压文档文件,将图片复制到对应目录下,以及使用python-docx自带的方法提取图片(推荐)defget_word_pics(doc,word_path,output_path):"""提取word文档中的图片:paramword_path:源文件名:paramoutput_path:结果目录:return:"""dict_rel=doc.part._relsforrelindict_rel:dictrel=if"image"inrel.target_ref:#图片存放目录ifnotos.path.exists(output_path):os.makedirs(output_path)img_name=re.findall("/(.*)",rel.target_ref)[0].spword_litextword_path)[0]#新名称newname=word_name.split('')[-1]ifos.sepinword_nameelseword_name.split('/')[-1]img_name=f'{newname}_{img_name}'#Wr??itetothefilewithopen(f'{output_path}/{img_name}',"wb")asf:f.write(rel.target_part.blob)bothheaderandfooter它是基于章节的。下面以某章节对象为例进行说明获取某章节first_section=self.doc.sections[0]利用章节对象的页眉和页脚属性获取页眉和页脚对象。由于页眉和页脚可能包含多个段落Paragraph,我们可以先利用页眉和页脚对象的paragraphs属性获取所有段落,然后遍历所有段落的值,最后将整个内容拼接在一起页眉和页脚。注意:页眉和页脚都可以包含多个段落header_content="".join([paragraph.textforparagraphinfirst_section.header.paragraphs])print("Headercontent:",header_content)Footerfooter_content="".join([paragraph.textforparagraphinfirst_section.footer.paragraphs])print("footercontent:",footer_content)