20

2020-12-31_锦秀汐潮的博客-CSDN博客

 3 years ago
source link: https://blog.csdn.net/weixin_38341889/article/details/111944345
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一个利用Python从PDF表格内提取数据的案列

1. 对PDF文件进行处理

 我得到的PDF文件是这样的

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl8zODM0MTg4OQ==,size_16,color_FFFFFF,t_70#pic_center
我需要从中提取出每个煤矿公司的名称和所在的省份、城市、县区以及生产能力,并将数据导入Excel,总共4322条数据(PS:本来想直接PDF转成Excel,但是转出来格式混乱,没法用)。
虽然Python有对PDF处理的第三方库,但研究了一下觉得实现不了想要的效果,所以网上找了一个PDF在线转Word的网站,将其转为doc格式文件(PS:找了好几个如迅捷这样的PDF转Word软件,都要收费,挺贵的),
这里提供转换好的Word

2.利用Python对Word进行读取

我用的是docx第三方库,具体使用方法有很多教程大家可以自行去学习

import docx
from docx import Document #导入库
path = "全国煤炭企业产能分布.doc" #文件路径
document = Document(path) #读入文件
tables = document.tables #获取文件中的表格集

但是运行后报错
在这里插入图片描述
原来是Document只能读docx格式的,不能读doc格式的文档(PS:当时转换完没有注意这点),于是尝试用Word自身另存为docx格式,发现还是不行,于是网上找了一下,发现需要强制转换,参考python读取doc/docx文件这篇博客,最后处理好是这样的(PS:注意观察换行符)
在这里插入图片描述
运行一下查看一下每个表格单元格内的文本

for i in tables:	#遍历所有表格
    print(len(i.rows))	#显示每个表格有多少行
    for j in range(0,len(i.rows)):	#遍历所有行
        row_cells = i.rows[j].cells	#获得每行的单元格集合对象
        for cell in row_cells:	#遍历每个单元格
            print(cell.text)	#显示每个单元格的文本,注意一定要加  .text

结果显示为:
在这里插入图片描述
在这里插入图片描述
可以发现两个问题,一是有重复项,二是公司名称断行,回过头研究发现是因为Document读取的时候是按行读取,而转化来的Word表格虽然显示只有1行,但实际上是三行拼接起来,仔细看了一下,发现里面的单元格也没有合并
在这里插入图片描述

3.对数据进行处理

为了方便查看获取的数据的规律,我先把所有得到的数据放到一个列表中

rowH = []	#创建一个空列表用来储存数据
for i in tables:	#遍历所有表格
    print(len(i.rows))	#显示每个表格有多少行
    for j in range(0,len(i.rows)):	#遍历所有行
        row_cells = i.rows[j].cells	#获得每行的单元格集合对象
        for cell in row_cells:	#遍历每个单元格
            rowH.append(cell.text)	#向列表中添加数据
     print(rowH)	#放在表格循环内,方便观察每个表格最终获得的数据

结果显示为:
在这里插入图片描述
可以发现里面有许多不需要的数据和空数据,这些都需要去掉

#处理数据
#去掉空数据
rowH = [i for i in rowH if i != '']
#去重
rowH2 = []	#创建一个新列表储存去重后的数据
rowH2 = list(set(rowH))	#转换为合集去重
rowH2.sort(key=rowH.index)	#保持原来的元素排列顺序
print(rowH2)	#这里放在放在行循环中,方便观察规律
rowH = []	#每次执行完要把rowH清空,否则数据全在一个列表,而不是每一行一个列表

结果显示为:
在这里插入图片描述
可以发现,其中有“序号”、“(万吨/年)”和空列表是我们不需要的,所以当循环到这一行的时候我们就跳过,不添加到列表中
还有一个就是单独有一个许可证编号的列表也是我们不需要的,但是不能通过列表长度排除,因为省份列表也只有一个元素,所以创建一个全国省份的总列表,如果列表元素不在里面,则表明这是不需要的
还有当列表长度大于3时,我们只需要取前3个元素即可

#如果列表为空则跳过循环
sfList = ['河北省','山西省','辽宁省','吉林省','黑龙江省','江苏省','浙江省','安徽省','福建省','江西省','山东省','河南省','湖北省','湖南省','广东省','海南省','四川省','贵州省','云南省','陕西省','甘肃省','青海省','台湾省','内蒙古自治区','广西壮族自治区','西藏自治区','宁夏回族自治区','新疆维吾尔自治区','北京市','天津市','上海市','重庆市','香港特别行政区','澳门特别行政区']
if rowH2 == []:
    continue
#当列表元素有“序号”、“(万吨/年)”时,跳过循环
a = '序号'
b = '(万吨/年)'
if a in rowH2:
    continue
elif b in rowH2:
    continue
#当列表长度为1,且元素不在全国省份列表内时,跳过循环
if len(rowH2)==1 and rowH2[0] not in sfList:
    continue
#当列表长度大于3时,只取前三个元素
if len(rowH2) > 3:
   	rowH2 = rowH2[0:3]

处理完的结果:
在这里插入图片描述
好了,现在的数据看着就很nice了,不用说大家都可以找出上面的规律吧:

  1. 每次列表长度为1的时候就是省份,直到下一个列表长度为1时才改变
  2. 每次列表长度为2的时候就是城市、县区,直到下一个列表长度为2时才改变,且每个县区之后就开始进入公司数据阶段,直到进入下个县区或者是省份
  3. 每2个长度为3列表组成一个完整的公司数据
rowH3 = []	#定义一个新列表储存最终数据
cs = 0	#用来判断是奇偶
sf = ''	#用来储存省份
xq = '' #用来储存县区
id = ''	#用来储存序号
name = '' #用来储存公司名称
cn = ''	#用来储存产能
#当列表长度为1时,赋值给sf,直到下一个列表长度为1时再改变
if len(rowH2)==1:
    sf = rowH2[0]
    continue	#减少执行后续代码,直接进入下一个循环
#当列表长度为2时,赋值给xq,直到下一个列表长度为2时再改变
if len(rowH2)==2:
    xq = rowH2[1]
    cs = 0	#表明开始进入公司数据阶段
    continue
#当列表长度为3时进行判断
if len(rowH2) == 3:
#如果cs为偶数,则说明这是一个公司的第一条数据,只记录,不保存
    if cs%2 == 0:
        id = rowH2[0]
        name = rowH2[1]
        cn = rowH2[2]
    else:
#如果cs为奇数,则说明这是一个公司的第二条数据,这时判断公司名称和之前的是否一致,如果一致则不做任何操作,如果不同则说明需要将两个字符串拼接起来才是完整的公司名称
        if name != rowH2[1]:
            name = name + rowH2[1]
#判断完毕后才将最终的一条数据保存进列表中
        rowH3.append(id)
        rowH3.append(sf)
        rowH3.append(xq)
        rowH3.append(name)
        rowH3.append(cn)
#cs+1,改变cs奇偶状态,为下一次循环做判断依据
    cs = cs + 1
rowH3 = [] #清空rowH3列表

结果显示为:
在这里插入图片描述
这个时候我们就得到我们想要的数据了,再将其储存到Excel中就好,我使用的是xlsxwriter第三方库,代码如下:

import xlsxwriter
# 写excel
workbook = xlsxwriter.Workbook('全国煤炭企业产能分布.xlsx')  # 创建一个excel文件
worksheet = workbook.add_worksheet(u'sheet1')  # 在文件中创建一个名为TEST的sheet,不加名字默认为sheet1
#在第一行将表头提前写入
worksheet.write(0, 0, U'序号')
worksheet.write(0, 1, U'省份')
worksheet.write(0, 2, U'城市')
worksheet.write(0, 3, U'煤矿名称')
worksheet.write(0, 4, U'生产能力(万吨/年)')
row = 1	#行数记录
#写入表格
if len(rowH3) != 0:
     worksheet.write(row, 0, rowH3[0])
     worksheet.write(row, 1, rowH3[1])
     worksheet.write(row, 2, rowH3[2])
     worksheet.write(row, 3, rowH3[3])
     worksheet.write(row, 4, rowH3[4])
     row = row + 1
#关闭连接
workbook.close()

至此终于成功
在这里插入图片描述
这仅是个人的一个思路,作抛砖迎玉之用,请各路大神批评指正
完整代码


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK