最真实的办公自动化案例!
共 5275字,需浏览 11分钟
·
2022-01-14 01:18
在数据分析的日常工作中,除了Excel数据的清洗,最常见的就是pdf、word、ppt等场景下的数据清洗,这种其实还有一个更高大上的名字,叫:办公自动化。
很多时候由于办公自动化场景下的数据是不规整的,所以在进行数据分析之前首要的就是进行数据提取。
例如,小一的朋友『长河』在实际工作中遇到的真实问题:
虽然我自己对word的操作不是很熟悉,但是我也在思考过后提供了自己的解决方法:
由于我自己对于PDF的数据提取比较擅长,也曾经写过相关的操作文档:Python办公自动化之PDF的详细操作(全),所以如果原始数据是pdf,那我就会按照上面我说的方法进行操作
但是长河他自己已经搞定了pdf的转换,那问题就变成了多个word的数据提取。
下面的文章就是他自己在实现过程中的真实思路,部分数据比较敏感,文中已经打码,但是不影响实际的阅读和练手
这个也是在实际工作中比较常遇到的问题,希望大家下次遇到的时候都能游刃有余
以下是『长河』投稿的正文:
1. 问题来源
最近面临的一个问题是从word中读取表格数据,然后整理成excel格式。
如下所示:
如果表格不是很多,只有几张表,完全手动处理就好,但是如果有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
...
经过不断地尝试,我们终于知道自己需要的数据在什么地方了。
考虑到表头的太过于复杂,不好定位,需要自己重新写表头信息即可,我们需要的是整个学校的数据,也就是下图中的部分
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文件有两张表,第二张表的数据结构如下:
第二张表的表头与第一张表有所不同,处理方式一样,直接上代码即可:
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)
最后的输出结果为:
3. 总结
学习编程会遇到很多问题和困惑。但是这个也是提高自己编程技术的关键所在。不断地探索,看B站视频,请教大佬,然后不停地print
看输出结果,就会得到自己想要的东西!
感谢小一前辈提供的思路,笔芯笔芯!
一个word一个word的处理,这样反而能提高效率!
推荐阅读
推荐阅读