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

小詹学Python

共 5275字,需浏览 11分钟

 ·

2022-01-14 01:18


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

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

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


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


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

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

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

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

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

1. 问题来源

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

如下所示:

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
...

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

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

提取表格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文件有两张表,第二张表的数据结构如下:

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)

最后的输出结果为:

最终成效
3. 总结

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

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

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

推荐阅读


牛逼!Python常用数据类型的基本操作(长文系列第①篇)

牛逼!Python的判断、循环和各种表达式(长文系列第②篇)

牛逼!Python函数和文件操作(长文系列第③篇)

牛逼!Python错误、异常和模块(长文系列第④篇)


浏览 37
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报