【Python私活案例】100元,PDF爬虫+解析+解析数据+存储Excel文件

蚂蚁学Python

共 5865字,需浏览 12分钟

 ·

2021-11-22 19:33

使用Python提取pdf信息的那些事

我一直都是一个pdf电子书和pdf格式控的宅男,没想到这辈子居然和老朋友以这种方式见面了。还记得上次专注的看pdf文件实在《明朝那些事》,于是有了今天的Python版的提取pdf信息的那些事。

1.需求

这次是要提取两个合同pdf文件中的相关信息,具体要求是先要读取excel文件,并将其中的两种类型的pdf合同连接读取出来,进行逐一的下载,这就是提取pdf文件的链接excel:

2.代码

我使用了requests库来进行了简单的pdf文件提取,因为他的链接不做验证,直接提取,连header都省了,这个还挺好的。

# 保存pdf文件
os.makedirs('./baoli/',exist_ok=True)
os.makedirs('./fenqi/',exist_ok=True)
for i in df.index:
    baoli_url = df.loc[i,'保理合同']#.split('pdf?')[0].__add__('pdf')
    fenqi_url = df.loc[i,'分期支付协议']#.split('pdf?')[0].__add__('pdf')
    baoli_name = df.loc[i,'保理合同'].split('.pdf?')[0].replace('/','-').split('-')[-1].__add__('.pdf')
    fenqi_name = df.loc[i,'分期支付协议'].split('.pdf?')[0].replace('/','-').split('-')[-1].__add__('.pdf')
    
    loan_application_no = df.loc[i,'loan_application_no']
    baoli_name = str(loan_application_no)+'_'+baoli_name
    fenqi_name = str(loan_application_no)+'_'+fenqi_name
    print(baoli_url)
    print(fenqi_url)
    res1 = requests.get(baoli_url)
    res2 = requests.get(fenqi_url)

    with open('./baoli/'+baoli_name,'wb'as file:
        file.write(res1.content)

    with open('./fenqi/'+fenqi_name,'wb'as file:
        file.write(res2.content)

这里我把下载好的文档自动归类为两类合同的不同文件夹中,方便他们查找,然后我是用的他们的一个业务字段命名的文件名,这样居然在后续的使用中,成为了唯一能够传递这个字段的方法!!

然后就是对第一类合同信息的提取,这里我把关键字段做了脱敏处理,这年头干啥都要小心小心再小心,不然罗翔老师的视频不是白看了!?

这里我主要用了PyPDF2这个类库提取pdf信息,将里面我要提取的对应字段拿到,然后把他们存储到一个临时列表,这样的操作应用到所有的同类pdf文件,然后将这种临时列表全部存储到一个最终的结果列表中,这个结果列表事先已经存储好了要生成的dataframe的项字段列,因此最后可以直接通过dataframe的构造方法,生成datarame对象,进而直接写入excel

from PyPDF2 import PdfFileReader
from pathlib import Path
baoli_path = Path('./baoli/')
baoli_list = baoli_path.glob('*.pdf')

baoli = [['XXXXX','ZZZZZ','YYYYY','TTTTT','YYYYY']] 
for i in baoli_list:
    path = f'./baoli/{i.name}'
    baoli_reader = PdfFileReader(path)
    baoli_fields = baoli_reader.getFields()
    temp = [i.stem.split('_')[0]]
    for field in baoli_fields:
        if field == 'contractNo':
            contract_no = list(baoli_fields[field].values())[-1]
            temp.append(contract_no)
            # print(contract_no)
        elif field == 'signDate':
            sign_date = list(baoli_fields[field].values())[-1]
            temp.append(sign_date)
            # print(sign_date)
        elif field == 'signContractNo':
            sign_contract_no = list(baoli_fields[field].values())[-1]
            temp.append(sign_contract_no)
            # print(sign_contract_no)
    temp.append('《分期支付协议》')
    baoli.append(temp)
print(baoli)

紧接着就是第二段代码,逻辑和上面的一模一样,但是工作量却远远超出了第一个,主要是在pdf文件中要逐个去匹配对应的字段名,这里的字段多达10几个

同时,我需要一一验证这些字段对应的pdf的英文代码是什么,从而确认提取的信息是否准确,然后才能正确的取数:

# 提取分期协议信息
fenqi_path = Path('./fenqi/')
fenqi_list = fenqi_path.glob('*.pdf')
fenqi = [['基础合同编号','商户住所',
          '商户统一社会信用代码','商户法定代表人',
          '底层合同期限','应收账款','商户名称','消费者姓名',
          '服务费用',
          '基础合同签署日期']]
for j in fenqi_list:
    path = f'./fenqi/{j.name}'
    fenqi_reader = PdfFileReader(path)
    fenqi_fields = fenqi_reader.getFields()
    temp = []
    date = []
    for field in fenqi_fields:
        if field == 'contractNo':
            f_contract_no = list(fenqi_fields[field].values())[-1]
            temp.append(f_contract_no)
            # print(f_contract_no)
        elif field == 'merchantCreditCode':
            f_merchant_credit_code = list(fenqi_fields[field].values())[-1]
            temp.append(f_merchant_credit_code)
            # print(f_merchant_credit_code)
        elif field == 'merchantAddress':
            f_merchant_address = list(fenqi_fields[field].values())[-1]
            temp.append(f_merchant_address)
            # print(f_merchant_address)
        elif field == 'legalPerson':
            legalPerson = list(fenqi_fields[field].values())[-1]
            temp.append(legalPerson)
            # print(legalPerson)
        elif field == 'merchantName':
            merchantName = list(fenqi_fields[field].values())[-1]
            temp.append(merchantName)
            # print(merchantName)
        elif field == 'userName':
            userName = list(fenqi_fields[field].values())[-1]
            temp.append(userName)
            # print(userName)
        elif field == 'money':
            money = list(fenqi_fields[field].values())[-1]
            temp.append(money)
            # print(money)
        elif field == 'periods':
            periods = int(list(fenqi_fields[field].values())[-1])+1
            temp.append(periods)
            # print(periods)
        elif field == 'serviceMoeny':
            serviceMoeny = list(fenqi_fields[field].values())[-1]
            temp.append(serviceMoeny)
            # print(serviceMoeny)
        elif field == 'yyyy':
            year = list(fenqi_fields[field].values())[-1]
            if year:
                date.append(year)
            else:
                date.append('年为空')
            # print(year)
        elif field == 'mm':
            month = list(fenqi_fields[field].values())[-1]
            if month:   
                date.append(month)
            else:
                date.append("月为空")
            # print(month)
        elif field == 'dd':
            day = list(fenqi_fields[field].values())[-1]
            if day:
                date.append(day)
            else:
                date.append("天为空")
    date = date[0]+'年'+date[1]+'月'+date[2]+'日'
    temp.append(date)
    fenqi.append(temp)
print(fenqi)

接下来在做了些生成excel文件的格式整理:

#调整格式
import xlwings as xw
app = xw.App(visible=False,add_book=False)
workbook = app.books.open(r'final.xlsx')
worksheet = workbook.sheets['总表']
worksheet.autofit()
workbook.save()
workbook.close()
app.quit()

于是,花了几个小时时间终于完成了所有的工作,但是第二天,诡异的事情发生了,在pdf匹配字段中,这些字段在代码里面都算局部变量,但是只有两个变量报错, 说这个变量不存在,而它们的作用域和其他的变量是一摸一样的,我感觉好奇怪,最后我不得已,将代码里的临时列表temp,提升为内层for循环的全局变量,然后错误就消失了,此外,我还添加了年月日的空值判断,因为她说她的数据集中的日期会有读取不正常的情况,所以我就做了这个样的判断,帮她把所有的问题都搞定了,看到她开心的状态,我觉得我也很有成就感,希望大家一切都顺利!


最后,推荐蚂蚁老师的Pandas入门课程,极佳的实战课


扫码:Pandas入门到实战课


点击阅读原文,也能到达目的地

浏览 44
点赞
评论
收藏
分享

手机扫一扫分享

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

手机扫一扫分享

举报