word文档案例
需求:
- 读取所有的段落文本,并使用字典表示每一个段落;
- 段落字典格式如下:
{
"type": "text",
"content": "2. Python的程序结构",
"runs": [{}, {}], # 每个run字典放入列表
"page_num": 1 # 页码
}
- 所有的段落放入一个列表中;
基于python-docx读取段落
- 未读取章节的编号;
# 遍历所有的段落
paragraphs_list = []
for paragraph in docx.paragraphs:
temp = {}
temp["type"] = "text"
temp["content"] = paragraph.text # 未读出章节编号 paragraph.style 获取
temp["runs"] = []
for run in paragraph.runs:
run_dict = {}
run_dict["content"] = run.text
run_dict["family"] = run.font.name
run_dict["bold"] = run.font.bold
run_dict["italic"] = run.font.italic
run_dict["size"] = run.font.size
run_dict["color"] = run.font.color.rgb # ColorFormat.rgb
run_dict["underline"] = run.font.underline
temp["runs"].append(run_dict)
# 统计页面id
temp["page_num"] = 1 # ?
paragraphs_list.append(temp)
print("all:", paragraphs_list)
深入理解docx处理的段落:
word docx文件本质是一个压缩文件,修改后缀名为.zip,即可解压得到对应的xml文件;
基于底层的 lxml 对象:
- CT_R, Run 文本对象,对应lxml标签 <w:r>,内部包含:
- <w:rPr> run属性
- <w:t> 文本标签
- obj.text
- CT_RPr,Run对象的属性; 对应lxml标签 <w:rPr>
- CT_P,段落对象,对应lxml标签 <w:p>,内部包含:
- <w:pPr>
- <w:pStyle>
- <w:numPr>
- <w:rPr>
- <w:r> 可有多个run标签属性;
- <w:pPr>
- CT_PPr, 段落的属性
- CT_Tbl,表格对象
- CT_NumPr 对应lxml标签<w:numPr>, 最终对象(不再迭代)
- obj.ilvl,
- obj.numId,
- obj.tag
- CT_String 对应lxml标签<w:pStyle>, 最终对象(不再迭代)
- obj.tag, {http://schemas.openxmlformats.org/wordprocessingml/2006/main}pStyle
- obj.val, “a7” 与.values()函数类似;
- obj.text 获取为None;
- CT_SectPr,图片
from docx import Document
docx = Document("xxx.docx")
for i in docx.element.body: # lxml元素
print(i)
基于pywin32读取段落
# pip install pywin32
from win32com.client import Dispatch
# 打开word应用程序
word = Dispatch("Word.Application")
word.Visible = 0 # 界面不可见
word.DisplayAlerts = 0 #
# 打开word文档
docx = word.Documents.Open("C:/Users/lenovo/Desktop/cc/lauf_chapter.docx", ReadOnly=True)
# 遍历所有的段落
paras_list = []
for paragraph in docx.Paragraphs:
temp = {}
temp["type"] = "text"
# 获取文本内容
if paragraph.Range.ListFormat.ListString:
content = paragraph.Range.ListFormat.ListString + " " + paragraph.Range.Text.replace("\r", "")
else:
content = paragraph.Range.Text.replace("\r", "") # 注意Range
if content:
temp["content"] = content
# 文本属性 一行的样式必须保证一致 才可以
font = paragraph.Range.Font # font.Name 字体 .Bold .Italic .Size .Underline
temp["attr"] = {
"family": font.Name,
"bold": font.Bold,
"italic": font.Italic,
"size": font.Size,
"underline": font.Underline
}
# 段落中表格的数量
if paragraph.Range.Tables.Count: #
# 表格: 1 ['章节序号\r\x07'] 每一个段落对应一个表格的单元格
# 表格: 1 ['知识点\r\x07']
# 表格: 1 ['掌握程度\r\x07']
# 表格: 1 ['所属python级别\r\x07']
print("表格:", paragraph.Range.Tables.Count, [content])
for table in paragraph.Range.Tables:
print(table.Range.Rows.Count, table.Range.Columns.Count)
# 段落中图片的数量
if paragraph.Range.InlineShapes.Count:
print("图片:", paragraph.Range.InlineShapes.Count)
# 'ListParagraphs', 'ListStyle',
paras_list.append(temp)
print("result:", paras_list)
docx.Close(False)
word.Quit()
基于pywin32读取表格
# pip install pywin32
from win32com.client import Dispatch
# 打开 word应用程序
word = Dispatch("Word.Application")
# word界面不可见
word.Visible = 0
word.DisplayAlerts = 0
# 打开word文档,必须是一个绝对路径
docx = word.Documents.Open("C:/Users/lenovo/Desktop/cc/lauf_chapter.docx", ReadOnly=True)
table_data = []
# 遍历文档中的表格
for table in docx.Tables:
# 获取行数、列数
row_num = table.Rows.Count
col_num = table.Columns.Count
# 初始化表格数据
cur_table = [["" for j in range(col_num)] for i in range(row_num)]
# 遍历单元格
for cell in table.Range.Cells: # 无内容的cell会被自动删除
# cell.RowIndex, cell.ColumnIndex 均从1开始
row_idx = cell.RowIndex - 1
col_idx = cell.ColumnIndex - 1
# 获取cell内容
cur_table[row_idx][col_idx] = cell.Range.Text.strip().replace("\r", "").replace("\x07", "") # \x07 水平制表符号
table_data.append(cur_table)
print("一个表格的数据:", table_data[0])
# 关闭word文档
docx.Close(False)
# 退出word应用程序
word.Quit()
结果:
注意:
word中的 \x07 表示水平制表符;
table.Rows 所有的单独行,迭代时不能有合并的行,否则报错;
table.Columns 所有单独列;
table.Cell 根据rid,cid 获取单元格对象;
table.Range 表格的范围对象
table.Range.Start 开始
table.Range.End 结束
table.Range.Cells 所有单元格,内容为空的单元格会被自动删除;