当前位置:首页>python>降本增效新实践:RPA+Python自研流程,一键生成信贷十级分类清单

降本增效新实践:RPA+Python自研流程,一键生成信贷十级分类清单

  • 2026-10-03 06:56:34
降本增效新实践:RPA+Python自研流程,一键生成信贷十级分类清单
一、项目背景

此前,Y行贷款十级分类清单均依托外包公司搭建的平台生成与下载,每年需支付固定服务费用,不仅持续产生运营成本,数据生成环节也高度依赖外部系统,自主掌控能力较弱。

在全行推进降本增效的工作要求下,团队主动对接业务部门,充分梳理实际数据需求。业务端涉及对公、对私、信用卡信贷台账,转贴现、营销管户台账及客户基础信息等多类核心数据表,数据来源分散、整合流程繁琐,原有模式已难以适配高效管理需求。

为打破对外包平台的依赖、优化数据处理效率,项目将各类关键台账与基础数据表统一归集至MySQL数据库,计划通过技术手段搭建内部自动化处理体系,从根源上压缩外部服务成本、提升业务运转效率。

二、核心代码
import pymysqlimport pandas as pdimport warningsfrom contextlib import closingwarnings.filterwarnings('ignore')# 行业映射字典industry = {    'A': '农、林、牧、渔业',    'B': '采矿业',    'C': '制造业',    'D': '电力、热力、燃气及水生产和供应业',    'E': '建筑业',    'F': '批发和零售业',    'G': '交通运输、仓储和邮政业',    'H': '住宿和餐饮业',    'I': '信息传输、软件和信息技术服务业',    'J': '金融业',    'K': '房地产业',    'L': '租赁和商务服务业',    'M': '科学研究和技术服务业',    'N': '水利、环境和公共设施管理业',    'O': '居民服务、修理和其他服务业',    'P': '教育',    'Q': '卫生和社会工作',    'R': '文化、体育和娱乐业',    'S': '公共管理、社会保障和社会组织',    'T': '国际组织'}# 机构映射字典branch = {    '营业部': '321023***',    '新城分理处': '321023***',    '红旗分理处': '321023***',    '王桥分理处': '321023***',    '白田路支行': '321023***',    '清算中心': '321023***',    '管理机构': '321023***'}def fetch_table(cursor, table_name, data_date=None, columns=None):    """    通用查询函数:执行SQL并返回DataFrame    :param cursor: 数据库游标    :param table_name: 表名    :param data_date: 数据日期(若需要过滤)    :param columns: 预定义的列名列表(若不提供则从cursor.description获取)    :return: DataFrame    """    if data_date is not None:        sql = f"SELECT * FROM {table_name} WHERE `数据日期` = %s"        cursor.execute(sql, (data_date,))    else:        sql = f"SELECT * FROM {table_name}"        cursor.execute(sql)    data = cursor.fetchall()    if columns is None:        # 从cursor.description获取列名        columns = [desc[0] for desc in cursor.description]    return pd.DataFrame(data, columns=columns)def process_pious(cur, data_date):    """处理个人贷款数据"""    # 获取pious表    pious_columns = ['***', '***', '***', ······]    pious = fetch_table(cur, 'pious', data_date, pious_columns)    # 获取pbasic表    pbasic_columns = ['***', '***', '***', ······]    pbasic = fetch_table(cur, 'pbasic', data_date, pbasic_columns)    pious_res = (pious.query("贷款余额等值人民币 > 0")                 [["数据日期", "借据机构号", "借据号", "客户号", "核心客户号", "客户名称", "放款日期",                   "到期日期", "贷款余额等值人民币", "科目号", "借据管户人名称", "借新还旧", '展期标志',                   "担保方式", "贷款投向5", "贷款类型", "五级分类-个人"]]                 .merge(pbasic[["客户号", "证件号码"]], on="客户号")                 .rename(columns={"贷款类型": "贷款类别"}))    pious_label = (pious_res.pivot_table(index=["客户号"], values=["贷款余额等值人民币"], aggfunc="sum")                   .reset_index()                   .rename(columns={"贷款余额等值人民币": "单户贷款余额合计"}))    pious_label["贷款类型"] = pious_label["单户贷款余额合计"].apply(lambda x: "小额自然人" if x <= 300000 else "大额自然人")    pious_fin = (pious_res.merge(pious_label[["客户号", "贷款类型"]], on="客户号")                 [["数据日期", "借据机构号", "借据号", "证件号码", "核心客户号", "客户名称", "放款日期",                   "到期日期", "贷款余额等值人民币", "科目号", "贷款类型", "借据管户人名称", "借新还旧",                   '展期标志', "担保方式", "贷款投向5", "贷款类别", "五级分类-个人"]]                 .rename(columns={"借据机构号": "机构号", "证件号码": "证件号", "客户名称": "借款人",                                  "放款日期": "借款日期", "贷款余额等值人民币": "余额", "借据管户人名称": "管户员",                                  "借新还旧": "是否借新还旧", "五级分类-个人": "五级分类", "贷款投向5": "主贷款投向"}))    for col in ["是否借新还旧", '展期标志', "担保方式", "主贷款投向", "贷款类别", "五级分类"]:        pious_fin[col] = pious_fin[col].apply(lambda x: x.split(".")[0] if len(x) > 0 else "")    pious_fin["主贷款投向"] = pious_fin["主贷款投向"].apply(lambda x: industry[x[0]] if len(x) > 0 else "")    pious_fin['借款日期'] = pd.to_datetime(pious_fin['借款日期'], format='%Y%m%d').dt.strftime('%Y-%m-%d')    pious_fin['到期日期'] = pd.to_datetime(pious_fin['到期日期'], format='%Y%m%d').dt.strftime('%Y-%m-%d')    return pious_findef process_cious(cur, data_date):    """处理企业贷款数据"""    cious_columns = ['***', '***', '***', ······]    cious = fetch_table(cur, 'cious', data_date, cious_columns)    cbasic_columns = ['***', '***', '***', ······]    cbasic = fetch_table(cur, 'cbasic', data_date, cbasic_columns)    cious_res = (cious.query("贷款余额等值人民币 > 0")                 [["数据日期", "借据机构号", "借据号", "客户号", "核心客户号", "客户名称", "放款日期",                   "到期日期", "贷款余额等值人民币", "科目号", "借据管户人名称", "借新还旧", '展期标志',                   "担保方式", "贷款投向5", "贷款类型", "五级分类"]]                 .merge(cbasic[["客户号", "证件号码"]], on="客户号")                 .rename(columns={"贷款类型": "贷款类别"}))    cious_label = (cious_res.pivot_table(index=["客户号"], values=["贷款余额等值人民币"], aggfunc="sum")                   .reset_index()                   .rename(columns={"贷款余额等值人民币": "单户贷款余额合计"}))    cious_label["贷款类型"] = cious_label["单户贷款余额合计"].apply(lambda x: "小额企事业" if x <= 5000000 else "大额企事业")    cious_fin = (cious_res.merge(cious_label[["客户号", "贷款类型"]], on="客户号")                 [["数据日期", "借据机构号", "借据号", "证件号码", "核心客户号", "客户名称", "放款日期",                   "到期日期", "贷款余额等值人民币", "科目号", "贷款类型", "借据管户人名称", "借新还旧",                   '展期标志', "担保方式", "贷款投向5", "贷款类别", "五级分类"]]                 .rename(columns={"借据机构号": "机构号", "证件号码": "证件号", "客户名称": "借款人",                                  "放款日期": "借款日期", "贷款余额等值人民币": "余额", "借据管户人名称": "管户员",                                  "借新还旧": "是否借新还旧", "贷款投向5": "主贷款投向"}))    for col in ["是否借新还旧", '展期标志', "担保方式", "主贷款投向", "贷款类别", "五级分类"]:        cious_fin[col] = cious_fin[col].apply(lambda x: x.split(".")[0] if len(x) > 0 else "")    cious_fin["主贷款投向"] = cious_fin["主贷款投向"].apply(lambda x: industry[x[0]] if len(x) > 0 else "")    cious_fin['借款日期'] = pd.to_datetime(cious_fin['借款日期'], format='%Y%m%d').dt.strftime('%Y-%m-%d')    cious_fin['到期日期'] = pd.to_datetime(cious_fin['到期日期'], format='%Y%m%d').dt.strftime('%Y-%m-%d')    return cious_findef process_ztx(cur, data_date):    """处理转贴现数据"""    ztx_columns = ['***', '***', '***', ······]    ztx = fetch_table(cur, 'tmp_ztx', columns=ztx_columns)  # 该表没有数据日期过滤    mapping = {        "科目号": "13067520",        "贷款类型": "大额企事业",        "管户员": "***",        "是否借新还旧": "否",        "担保方式": "其他-买断式转贴现",        "主贷款投向": "",        "贷款类别": "买断式转贴现",        "五级分类": "正常"    }    for attr, val in mapping.items():        ztx[attr] = val    ztx['借据号'] = ztx[['票号', '子票区间']].apply(lambda x: f"{x[0]},{x[1]}", axis=1)    ztx['数据日期'] = data_date    ztx["展期标志"] = "否"    ztx_fin = ztx[["数据日期", "核心机构号", "借据号", "交易对手组织机构代码", "交易对手行号", "交易对手",                   "出票日", "到期日", "票面金额", "科目号", "贷款类型", "管户员", "是否借新还旧",                   "展期标志", "担保方式", "主贷款投向", "贷款类别", "五级分类"]].rename(columns={        "核心机构号": "机构号",        "交易对手组织机构代码": "证件号",        "交易对手行号": "*****",        "交易对手": "借款人",        "出票日": "借款日期",        "到期日": "到期日期",        "票面金额": "余额"    })    return ztx_findef process_card(cur, data_date):    """处理信用卡数据"""    # 查询card表    card_columns = ['***', '***', '***', ······]    card = fetch_table(cur, 'card', data_date, card_columns)    # 查询market表    market_columns = ['***', '***', '***', ······]    market = fetch_table(cur, 'tmp_market', columns=market_columns)  # 无数据日期    # 查询khtybh表    khtybh_columns = ['***', '***', '***', ······]    khtybh = fetch_table(cur, 'tmp_khtybh', columns=khtybh_columns)    # 查询pbasic表(用于补充核心客户号)    pbasic_columns = ['***', '***', '***', ······]    pbasic = fetch_table(cur, 'pbasic', data_date, pbasic_columns)    # 处理market空值    index_null = market.loc[market["营销人工号"].isnull() | market["营销人姓名"].isnull() | market["营销机构"].isnull(), :].index    mapping_null = {"营销人工号": "管护人工号", "营销人姓名": "管护人姓名", "营销机构": "管护机构"}    for key, val in mapping_null.items():        market.loc[index_null, key] = market.loc[index_null, val]    market = market.loc[~(market["营销人工号"].isnull() | market["营销人姓名"].isnull() | market["营销机构"].isnull()), :].reset_index(drop=True)    market["营销机构"] = market["营销机构"].apply(lambda x: x.replace("***", "").replace("***", "营业部"))    market["机构号"] = market["营销机构"].apply(lambda x: branch[x] if x in branch else '321023***')    market_res = market[["客户姓名", "账号", "证件号码", "营销人工号", "营销人姓名", "机构号"]].rename(columns={        "客户姓名": "姓名",        "账号": "卡号",        "证件号码": "客户统一编号",        "营销人工号": "管户员工号",        "营销人姓名": "管户员"    })    # 合并数据    card_tmp = (card.query("本币透支金额 > 0")[["数据日期", "卡号", "账号", "客户统一编号", "姓名", "本币透支金额", "贷记卡五级分类"]]                .merge(market_res, on=["卡号", "姓名", "客户统一编号"], how="left")                .merge(khtybh, on=["卡号", "姓名", "客户统一编号"], how="left"))    card_res = (card_tmp[["数据日期", "机构号", "账号", "客户统一编号", "核心客户号", "姓名", "本币透支金额", "贷记卡五级分类", "管户员"]]                .rename(columns={"账号": "借据号", "客户统一编号": "证件号码", "姓名": "借款人", "本币透支金额": "余额", "贷记卡五级分类": "五级分类"})                .merge(pbasic[["核心客户号", "证件号码"]].rename(columns={"核心客户号": "核心客户号2"}), on="证件号码", how="left")                .rename(columns={"证件号码": "证件号"}))    # 填充缺失的核心客户号    card_res.loc[card_res["核心客户号"].isnull(), "核心客户号"] = card_res.loc[card_res["核心客户号"].isnull(), "核心客户号2"]    # 添加固定字段    mapping_c = {        "借款日期": data_date,        "到期日期": data_date,        "科目号": "1305",        "贷款类型": "信用卡",        "展期标志": "否",        "是否借新还旧": "信用卡",        "担保方式": "信用/免担保透支",        "主贷款投向": "信用卡",        "贷款类别": "信用卡"    }    for attr, val in mapping_c.items():        card_res[attr] = val    card_res['借款日期'] = pd.to_datetime(card_res['借款日期'], format='%Y%m%d').dt.strftime('%Y-%m-%d')    card_res['到期日期'] = pd.to_datetime(card_res['到期日期'], format='%Y%m%d').dt.strftime('%Y-%m-%d')    card_fin = card_res[["数据日期", "机构号", "借据号", "证件号", "核心客户号", "借款人", "借款日期", "到期日期",                         "余额", "科目号", "贷款类别", "管户员", "是否借新还旧", "展期标志", "担保方式",                         "主贷款投向", "贷款类型", "五级分类"]]    for col in ["五级分类"]:        card_fin[col] = card_fin[col].apply(lambda x: x.split(".")[0] if len(x) > 0 else "")    return card_findef main(data_date, host, port, user, password, database, charset='utf8'):    """    主函数:从数据库读取数据,生成贷款分类清单Excel文件    :param data_date: 数据日期,格式为YYYYMMDD(如20260228)    :param host: 数据库主机    :param port: 数据库端口    :param user: 数据库用户名    :param password: 数据库密码    :param database: 数据库名称    :param charset: 字符集,默认为utf8    """    # 建立数据库连接    try:        conn = pymysql.connect(            host=host,            port=port,            user=user,            password=password,            database=database,            charset=charset        )    except pymysql.Error as e:        print(f"数据库连接失败: {e}")        return    try:        with closing(conn.cursor()) as cur:            # 处理各类贷款数据            pious_fin = process_pious(cur, data_date)            cious_fin = process_cious(cur, data_date)            ztx_fin = process_ztx(cur, data_date)            card_fin = process_card(cur, data_date)        # 合并所有数据        result = pd.concat([pious_fin, cious_fin, ztx_fin, card_fin], ignore_index=True)        result[["数据日期", "机构号", "科目号"]] = result[["数据日期", "机构号", "科目号"]].astype("str")        # 统一担保方式        mapping_r = ["信用", "抵押", "保证", "贴现", "质押"]        for ensure in mapping_r:            result.loc[result["担保方式"].str.contains(ensure), "担保方式"] = ensure        # 输出文件        output_filename = f"D:/MyDocx/贷款十级分类清单/{data_date[:4]}年{data_date[4:6]}月份贷款十级分类清单(SASP版v2.0).xlsx"        result.to_excel(output_filename, index=False)        print(f"文件已生成: {output_filename}")    except Exception as e:        print(f"处理过程中发生错误: {e}")    finally:        conn.close()if __name__ == '__main__':    # 示例调用(实际使用时请替换为真实参数)    # 注意:这里演示了如何手动传入 config.ini 中的参数    main(        data_date="***",        host="***",        port=3306,        user="root",        password="***",        database="***",        charset="utf8"    )
本脚本中的敏感信息已做脱敏处理,仅作为功能展示使用。实际部署运行时,需结合本地数据库的具体配置(如主机、端口、账号密码等),并根据本地数据表的字段名称、数据类型等实际情况完成适配调整,确认所有参数与表结构匹配后,脚本方可正常执行。
三、代码说明

3.1 脚本整体功能与核心逻辑

以上Python脚本的核心作用是从MySQL数据库中提取个人贷款、企业贷款、转贴现、信用卡四类业务的相关数据,经过标准化清洗、字段整合、分类标注后,将所有数据汇总生成统一格式的贷款十级分类清单Excel文件。

脚本整体遵循“数据提取→分业务模块清洗→字段标准化→数据合并→文件输出”的逻辑流程,依托pandas完成数据处理,借助pymysql实现数据库交互,同时通过上下文管理器保障数据库资源的安全释放。

3.2 前期准备与基础配置

脚本开头完成了核心库的导入与基础常量定义:导入pymysql用于数据库连接和数据查询,pandas用于结构化数据处理,warnings库用于屏蔽无关警告,contextlib.closing用于管理数据库游标等资源;通过warnings.filterwarnings('ignore')过滤执行过程中的警告信息,避免干扰输出。

此外,定义了两个关键映射字典:industry字典实现行业编码(单字母编码如A、B、C)到具体行业名称(如农、林、牧、渔业,采矿业)的转换,解决行业标识不统一的问题;branch字典完成机构名称(如白田路支行、营业部等)到机构编号的映射,为后续机构字段的标准化提供基础。

3.3 通用数据查询函数设计

脚本封装了fetch_table通用查询函数,作为所有数据表查询的基础工具。

该函数接收数据库游标、表名、数据日期、列名列表等参数,支持两种查询模式:若传入数据日期,则执行带日期过滤的SQL查询,仅提取指定日期的数据;若未传入数据日期,则查询整张表的全部数据。

查询结果通过游标获取后,会结合列名(未指定列名时从游标描述中自动提取)转换为pandas的DataFrame格式,这一设计让不同业务表的查询逻辑复用,提升了代码的模块化和可维护性。

3.4 个人贷款数据处理模块

process_pious函数专门处理个人贷款数据:首先通过通用查询函数提取个人贷款表(pious)和个人客户基础信息表(pbasic)的指定字段,筛选出贷款余额等值人民币大于0的有效数据,仅保留核心字段后,通过“客户号”关联pbasic表补充客户证件号码。

接着通过透视表按客户号汇总单户贷款余额,以30万元为阈值将个人贷款划分为“小额自然人”和“大额自然人”两类,再将分类结果合并回原数据。

随后对字段进行标准化重命名(如“借据机构号”改为“机构号”、“放款日期”改为“借款日期”),对“是否借新还旧”“展期标志”等字段做格式清洗(去除小数点后冗余内容),通过industry字典将贷款投向的字母编码转换为具体行业名称,并将数字格式的日期(YYYYMMDD)转换为标准的“YYYY-MM-DD”格式,最终输出结构化的个人贷款数据。

3.5 企业贷款数据处理模块

process_cious函数处理企业贷款数据,逻辑与个人贷款高度适配但针对企业特性调整:先提取企业贷款表(cious)和企业客户基础表(cbasic)的指定字段,筛选贷款余额大于0的记录,关联补充证件号码后,按客户号汇总单户余额,以500万元为阈值划分“小额企事业”和“大额企事业”类别。

后续同样执行字段重命名、格式清洗、行业编码转换和日期格式化操作,区别在于企业贷款依赖的基础表字段(如cbasic表包含企业规模、资产总额等企业专属信息)和分类阈值与个人贷款不同,最终输出符合统一格式的企业贷款数据。

3.6 转贴现数据处理模块

process_ztx函数针对转贴现这类非传统贷款业务设计,处理逻辑更侧重字段补充:首先提取转贴现表(tmp_ztx)的全量数据(无日期过滤),由于该表缺少贷款分类所需的部分字段,通过固定值映射补充(如科目号、贷款类型、五级分类等),并将票号与子票区间拼接为借据号,补充数据日期、展期标志等必要字段。

随后对字段进行重命名,使其适配整体数据结构(如“核心机构号”改为“机构号”、“出票日”改为“借款日期”),解决了转贴现数据格式与贷款数据不统一的问题,最终输出标准化的转贴现数据。

3.7 信用卡数据处理模块

process_card函数处理信用卡透支数据,涉及多表关联且逻辑更复杂:

首先提取信用卡表(card)、营销信息表(tmp_market)、客户编号映射表(tmp_khtybh)和个人基础表(pbasic)的指定字段;

先处理tmp_market表的空值问题(营销信息缺失时用管护信息补充),并将营销机构名称转换为机构编号;

筛选出本币透支金额大于0的信用卡记录,依次关联tmp_market、tmp_khtybh补充管户员、核心客户号等信息,再关联pbasic表填充缺失的核心客户号。

之后补充固定字段(如借款/到期日期统一为数据日期、科目号固定为1305、贷款类型标注为信用卡等),格式化日期字段并清洗五级分类字段,最终输出标准化的信用卡透支数据。

3.8 主函数与执行闭环

main函数是脚本的执行入口,接收数据日期、数据库连接参数等输入后,首先尝试建立MySQL数据库连接,连接失败则输出错误并终止。

连接成功后,通过closing上下文管理器管理游标资源,依次调用四类业务的处理函数获取标准化数据,将所有数据合并为一个DataFrame,并将数据日期、机构号、科目号转换为字符串类型保证格式统一。

随后对“担保方式”字段做进一步标准化(将包含“信用”“抵押”等关键词的字段值统一为核心词),最终将合并后的数据输出到指定路径的Excel文件,文件名包含年份、月份和版本信息。

脚本通过try-except-finally结构捕获执行异常,确保无论处理是否成功,数据库连接都会被关闭,避免资源泄露。脚本末尾的if__name__=='__main__'块提供了示例调用方式,方便测试和实际使用时替换参数执行。

四、运行实录
五、末尾总结

本次依托影刀RPA、Python与MySQL数据库打造的贷款十级分类清单自动化项目,成功实现了信贷数据处理的自主化与智能化,彻底打破了对外包平台的长期依赖,从源头削减了外部服务成本,是Y行落实降本增效工作要求的生动实践。

项目深度贴合业务部门实际需求,将对公、对私、信用卡等各类信贷台账、客户基础信息表统一归集管理,通过AI优化Python代码大幅提升数据处理性能,构建了标准化的数据清洗与整合流程。

操作层面实现极简自动化,仅需选择数据日期,系统即可自动完成数据库连接、数据查询、清洗整合全流程,最终精准生成符合要求的清单文件。

该项目以业务微开发赋能流程自动化,不仅优化了信贷数据处理效率、提升了数据管控自主性,更为Y行数字化转型提供了可复制、可推广的实操方案,助力业务运营向高效、集约、自主的方向持续升级。

最新文章

随机文章