风控贷后审核中,需要根据用户提供的账单流水,判断用户的还款能力,来辅助做放款决策,所以提取规格化数据是很重要的第一步。
一般情况下,用户提供的账单流水几乎都是zip压缩包,解压后是PDF文件格式,而账单流水几乎都是表格形式展示的。
那么 PDF表格 怎么转化为Excel呢?或者保存到数据库呢?
- 主要用到 pdfplumber 包,下载:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ pdfplumber
- 解析表头
# 导入
import pdfplumber
import re
with pdfplumber.open(input_file_path, password=password) as pdf:
# 首页文本
first_page_text = pdf.pages[0].extract_text()
search_obj = re.search(r"兹证明:(?P<name>.*?)\(证件号码:(?P<id_card>.*?)\)在其支付宝账号(?P<account>.*?)中明细", first_page_text, re.M | re.I | re.S)
if search_obj:
user_name = search_obj.group('name').replace(' ', '').strip() # 姓名
id_card_no = search_obj.group('id_card').replace(' ', '').strip() # 身份证
account_number = search_obj.group('account').replace(' ', '').strip() # 支付宝账号
output_file_path = '支付宝|{}|{}|{}.xlsx'.format(user_name, id_card_no, account_number) # 拼接文件名
print('解析表头成功')
else:
print('解析表头失败')
- 提取数据
使用进度条,可以查看当前解析进度,还可以省略大量日志,下载:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ tqdm
# 导入进度条
from tqdm import tqdm
print('开始读取数据')
result = list()
for index, page in enumerate(tqdm(pdf.pages)): # 进度条
table_list = page.extract_table()
if table_list:
result.extend(table_list)
- 清洗数据
# 清洗数据
df = pd.DataFrame(result)
df.columns = df.iloc[2] # 提取字段
df = df.iloc[3:] # 去除脏数据
df = df.replace(' ', '', regex=True) # 去除所有空格,注意顺序不能换
df['交易时间'] = df['交易时间'].replace('\n', ' ', regex=True) # 时间格式
df = df.replace('\n|,', '', regex=True) # 去除换行
df = df.reset_index(drop=True) # 索引
df = df.fillna(np.NAN).replace('', np.NAN) # 空值填充
df['交易时间'] = pd.to_datetime(df['交易时间'].str.strip(), errors='ignore') # 时间格式
df = df.astype({'金额': 'float'}, errors='ignore') # 修改类型
df['金额'] = np.where(df['收/支'] == '支出', -df['金额'], np.where(df['收/支'] == '收入', df['金额'], 0))
- 保存数据
# 保存到文件
df.to_excel(output_file_path, index=False)
# 也可以保存到数据库(会自动建表)
df.to_sql(name="table_name", con=con, if_exists='append', index=False)
- 完整代码:
# -*- coding: utf-8 -*-
import re
import pdfplumber
import numpy as np
import pandas as pd
from tqdm import tqdm
def parse_pdf_ZFB(input_file_path: str, password: str = '') -> bool:
"""
解析解析支付宝账单流水,格式化为Excel
input_file_path:pdf文件绝对路径
password:密码
"""
result = list()
output_file_path = 'output_file_path.xlsx' # 文件输出名
with pdfplumber.open(input_file_path, password=password) as pdf:
# 解析表头
first_page_text = pdf.pages[0].extract_text()
search_obj = re.search(r"兹证明:(?P<name>.*?)\(证件号码:(?P<id_card>.*?)\)的支付宝账户(.*?)支付宝账户 (?P<account>.*?)\n收支明细", first_page_text, re.M | re.I | re.S)
if search_obj:
user_name = search_obj.group('name').replace(' ', '').strip() # 姓名
id_card_no = search_obj.group('id_card').replace(' ', '').strip() # 身份证
account_number = search_obj.group('account').replace(' ', '').strip() # 身份证
output_file_path = '支付宝|{}|{}|{}.xlsx'.format(user_name, id_card_no, account_number) # 拼接文件名
print('解析表头成功')
else:
print('解析表头失败')
print('开始读取数据')
for index, page in enumerate(tqdm(pdf.pages)): # 进度条
table_list = page.extract_table()
if table_list:
result.extend(table_list)
if result:
# 清洗数据
df = pd.DataFrame(result)
df.columns = df.iloc[8] # 字段
df = df.iloc[9:] # 去除脏数据
df = df.replace(' ', '', regex=True) # 去除所有空格,注意顺序不能换
df['时间'] = df['时间'].replace('\n', ' ', regex=True) # 时间格式
df = df.replace('\n|,', '', regex=True) # 去除换行
df = df.reset_index(drop=True) # 重置索引
df = df.fillna(np.NAN).replace('', np.NAN) # 空值填充
df['时间'] = pd.to_datetime(df['时间'].str.strip(), errors='ignore') # 时间格式
df = df.astype({'收入': 'float', '支出': 'float', '账户余额': 'float'}, errors='ignore') # 小数格式
# 保存到文件
df.to_excel(output_file_path, index=False)
print('解析文件成功')
return True
else:
print('解析文件失败')
return False