大家好,我是小一!

在数据分析的日常工作中,除了Excel数据的清洗,最常见的就是pdf、word、ppt等场景下的数据清洗,这种其实还有一个更高大上的名字,叫:办公自动化

很多时候由于办公自动化场景下的数据是不规整的,所以在进行数据分析之前首要的就是进行数据提取。

例如,小一的朋友『长河』在实际工作中遇到的真实问题


最真实的办公自动化案例!_数据分析


虽然我自己对word的操作不是很熟悉,但是我也在思考过后提供了自己的解决方法:


最真实的办公自动化案例!_python_02


由于我自己对于PDF的数据提取比较擅长,也曾经写过相关的操作文档:Python办公自动化之PDF的详细操作(全),所以如果原始数据是pdf,那我就会按照上面我说的方法进行操作

但是长河他自己已经搞定了pdf的转换,那问题就变成了多个word的数据提取。

下面的文章就是他自己在实现过程中的真实思路,部分数据比较敏感,文中已经打码,但是不影响实际的阅读和练手

这个也是在实际工作中比较常遇到的问题,希望大家下次遇到的时候都能游刃有余

以下是『长河』投稿的正文:

1. 问题来源

最近面临的一个问题是从word中读取表格数据,然后整理成excel格式。

如下所示:

最真实的办公自动化案例!_python_03

word表格1,已脱敏处理

如果表格不是很多,只有几张表,完全手动处理就好,但是如果有140张表,9年的数据,该怎么处理呢?

这个时候需要程序来帮我们自动化解决了。


2. 解决问题

明确问题之后,我们接下来需要解决问题。

如果要从word中提取表格,常用的包有​​docx​​​ , 对提取中的数据进行规范处理,需要使用​​pandas​

2.1 明确数据的行和列

如果要提取word表格中的行和列,则需要明白这个表格到底有多少行和列,然后再根据具体行和列进行数据的提取。

该部分内容可以参看B站的上的一些视频,用Python操作Word

代码如下:

from docx import Document

doc = Document('one.docx')
tables = doc.tables
table = tables[0] # 表示读取的第一张表

# 查看一下多少行,多少列
print(len(table.rows),len(table.columns))

输出结果为:

5 14

说明我们提取的表格信息是一个5行14列的数据。接下来需要思考,每一行每一列是什么样子。

我们这里以第5行第2列为例进行说明:

继续写入代码为:

print(table.cell(4,1).text)

输出结果为:

13905
270
5583
1528
1791
2315
2439
...

经过不断地尝试,我们终于知道自己需要的数据在什么地方了。

考虑到表头的太过于复杂,不好定位,需要自己重新写表头信息即可,我们需要的是整个学校的数据,也就是下图中的部分

最真实的办公自动化案例!_python_04

提取表格1对应的数据

2.2 数据提取

接下来进行数据提取:

list1 = []  # 定义一个空的列表存储数据
for row in range(4,len(table.rows)):
for column in range(len(table.columns)):
list1.append(table.cell(row,column).text)
print(len(list1))
print(list1)

提取出来的数据是一串很长的列表,输出结果为:

14
['--大学\--大学\--大学\---大学\n ----\n2186588\n203224\n146649\n329602\n214014\n299323\n47413\n71033']

接下来进行迭代,转化成 ​​[[],[],[]]​​ 的形式

values = []
for i in list1:
i = i.split('\n')
values.append(i)
print(values)

结果处理完成,结果如下:

[['xx大学', 'xxxx大学', 'xx大学', ---'xxxx大学'],--- ['2186588', '203224', '146649', '329602', '214014', '299323', '47413', '71033']]
2.3 转成 DataFrame格式

前面已经把values整理好了,接下来重新整理表头信息即可:

colums = ['xx','xx','xx']
data_part1 = pd.DataFrame(values,columns).T
print(data_part1.head())

输出结果为:

学校名称       xxxxxx-  ...        xxxx      xxxxxxx
0 XX大学 13905 ... 46526 2222470
1 XX大学 270 ... 0 67822
2 XX大学 5583 ... 331010 3557540
3 XX大学 1528 ... 12826 544980
4 XX大学 1791 ... 1270 844921

[5 rows x 14 columns]

考虑到一个word文件有两张表,第二张表的数据结构如下:

最真实的办公自动化案例!_python_05

word表格2,已脱敏处理

第二张表的表头与第一张表有所不同,处理方式一样,直接上代码即可:

table = tables[1]
for row in range(3, len(table.rows)):
for column in range(len(table.columns)):
table2.append(table.cell(row, column).text)
for h in table2:
h = h.split('\n')
values2.append(h)
data2 = pd.DataFrame(values2,column2).T

data = pd.concat([data1,data2],axis =1)
2.4 完整地处理一张表

一张完整的word有两张表,所以需要使用一个判断条件进行处理,将其分为奇数位表和偶数位表,其判断依据是某数除以2余数是否为 0,

具体的代码如下:

import pandas as pd
from docx import Document
column1 = ['xx','xx','xx','xx','xx']
column2 = ['xx','xx','xx','xx','xx']

for t in range(len(tables)):
if t % 2 == 0:
table1 = []
value1 = []
table = docx.tables[t]
for row in range(4, len(table.rows)):
for column in range(len(table.columns)):
table1.append(table.cell(row, column).text)
for j in table1:
j = j.split('\n')
value1.append(j)
data1 = pd.DataFrame(value1, column1).T
if t % 2 == 1:
table2 = []
value2 = []
table = docx.tables[t]
for row in range(3, len(table.rows)):
for column in range(len(table.columns)):
table2.append(table.cell(row, column).text)
for h in table2:
h = h.split('\n')
value2.append(h)
data2 = pd.DataFrame(value2,column2).T
data = pd.concat([data1,data2],axis =1)
2.5 完整地处理多张表

如果是处理多张表,则需要设置路径,然后在具体的路径中进行处理

具体的代码如下:

import pandas as pd
from docx import Document
import os
column1 = ['xx','xx','xx','xx','xx']
column2 = ['xx','xx','xx','xx','xx']

# 设置路径
path = os.listdir('E:\one-two')
# print(path)
for i in range(len(path)):
docx = Document('E:\one-two\{}'.format(path[i]))
# print('第{}表'.format(i+1),docx)
tables = docx.tables
for t in range(len(tables)):
if t % 2 == 0:
table1 = []
value1 = []
table = docx.tables[t]
for row in range(4, len(table.rows)):
for column in range(len(table.columns)):
table1.append(table.cell(row, column).text)
for j in table1:
j = j.split('\n')
value1.append(j)
data1 = pd.DataFrame(value1, column1).T
if t % 2 == 1:
table2 = []
value2 = []
table = docx.tables[t]
for row in range(3, len(table.rows)):
for column in range(len(table.columns)):
table2.append(table.cell(row, column).text)
for h in table2:
h = h.split('\n')
value2.append(h)
data2 = pd.DataFrame(value2,column2).T
data = pd.concat([data1,data2],axis =1)
print('正在保存{}'.format(i+1))
data.to_excel('E:\one-two\{}.xlsx'.format(i),index=False)

最后的输出结果为:

最真实的办公自动化案例!_python_06

最终成效

3. 总结

学习编程会遇到很多问题和困惑。但是这个也是提高自己编程技术的关键所在。不断地探索,看B站视频,请教大佬,然后不停地​​print​​看输出结果,就会得到自己想要的东西!

感谢小一前辈提供的思路,笔芯笔芯!

一个word一个word的处理,这样反而能提高效率!