影刀RPA进阶教程:跨系统数据对账自动化——从对账逻辑到差异处理

系列已经写了100多篇,覆盖了数据采集、清洗、存储、展示几乎完整的链路。但在实际业务中,有一个高频场景始终没有单独讲过——跨系统数据对账

电商订单需要在ERP和电商平台之间对账、财务数据需要在银行系统和企业系统之间对账、库存需要在WMS和电商平台之间对账……这些场景的共同特征是:从两个(或多个)系统取数据,按规则比对,标记差异,生成对账报告。

picture.image

今天专门讲数据对账的自动化方案——比对规则设计、大文件分块处理、差异分类与自动修复。


picture.image

先说核心:对账的三类差异

| 差异类型 | 说明 | 示例 |

picture.image |---------|------|------| | A有B无 | 系统A有记录,系统B没有 | 淘宝有订单,ERP里没有 | | A无B有 | 系统B有记录,系统A没有 | ERP有订单,淘宝里没有 | | 数据不一致 | 两边都有记录,但字段值不同 | 金额不一致、状态不一致 |

picture.image

第一部分:对账流程架构


![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/ef036b60e1274e768fc5f4fd2efe417d~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783651342&x-signature=MPo9IVVVAIIJXb%2BmgvLRH5SWE18%3D)
【系统A数据】              【系统B数据】
     ↓                          ↓
  采集(API/Excel/数据库)   采集(API/Excel/数据库)
     ↓                          ↓
  清洗(统一格式)           清洗(统一格式)
  
![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/1fb1b1f48280407fa7d697ac75e646f0~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783651342&x-signature=upoYeZ%2FqQftBEzddK1bv5j0ZC64%3D)
     ↓                          ↓
            ↓                  ↓
          【数据比对引擎】
                 ↓
          【差异分类处理】
                 ↓
                 
![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/1f518d4f9ec849c2926da5fd1383c85f~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783651342&x-signature=H2wGVkOqUl0o6eGdK6jVzOp%2Fkqk%3D)
          【对账报告生成】
                 ↓
          【差异人工复核】

picture.image


第二部分:数据采集与统一格式

2.1 定义统一数据格式

# ===== 统一订单格式 =====
# 无论来自哪个系统,都转换成这个格式
{
    "order_id": "O20260701001",      # 订单号(唯一键)
    "platform": "淘宝",               # 来源平台
    "order_date": "2026-07-01",      # 订单日期
    "amount": 299.00,                # 订单金额
    "status": "已完成",              # 订单状态
    "buyer": "张三",                 # 买家
    "item_name": "蓝牙耳机",         # 商品名
    "quantity": 1,                   # 数量
    "source": "淘宝API"              # 数据来源
}

2.2 从不同数据源统一采集

# ============================================
# 子流程:采集淘宝订单(通过API)
# ============================================

子流程 Fetch_Taobao_Orders(开始日期, 结束日期):
    输出日志("【采集】淘宝订单:" + 开始日期 + " ~ " + 结束日期)
    
    # 调用淘宝API获取订单
    HTTP请求(
        方法="GET",
        URL="https://gw.api.taobao.com/router/rest?method=taobao.trade.fullinfo.get...",
        请求头={"Authorization": "Bearer " + TOKEN}
    )
    
    订单列表 = 解析订单数据(HTTP响应内容)
    
    # 转换为统一格式
    统一格式列表 = []
    按列表循环(订单列表, 循环项=订单):
        统一格式 = {
            "order_id": 订单["tid"],
            "platform": "淘宝",
            "order_date": 订单["created"][:10],
            "amount": float(订单["payment"]),
            "status": 映射状态(订单["status"]),
            "buyer": 订单["buyer_nick"],
            "item_name": 订单["orders"][0]["title"],
            
![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/5f2d4c0a7cbe460c91c9fe3120cc56ee~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783651342&x-signature=YUnNWNcpeUAvuyDn1R1S4vozkgc%3D)
            "quantity": int(订单["orders"][0]["num"]),
            "source": "淘宝API"
        }
        将 统一格式 加入列表(统一格式列表)
    结束循环
    
    返回结果(统一格式列表)
结束子流程

# ============================================
# 子流程:采集ERP订单(通过数据库)
# ============================================

子流程 Fetch_ERP_Orders(开始日期, 结束日期):
    输出日志("【采集】ERP订单:" + 开始日期 + " ~ " + 结束日期)
    
    # 连接ERP数据库
    执行Python代码(
        输入: 开始日期, 结束日期,
        输出: 订单列表,
        代码="""
import pymysql
import json

conn = pymysql.connect(
    host='192.168.1.100',
    user='rpa_user',
    
![picture.image](https://p3-volc-community-sign.byteimg.com/tos-cn-i-tlddhu82om/e5945cfd64c9462fb1b723a4e34000c1~tplv-tlddhu82om-image.image?=&rk3s=8031ce6d&x-expires=1783651342&x-signature=PhSJzy8cdkJ8TVHrkQ6wlYlDcIc%3D)
    password='xxx',
    database='erp'
)
cursor = conn.cursor()
cursor.execute('''
    SELECT order_no, create_date, total_amount, order_status, customer_name, product_name, qty
    FROM orders
    WHERE create_date BETWEEN %s AND %s
''', (start_date, end_date))
rows = cursor.fetchall()
conn.close()

# 转换为统一格式
result = []
for row in rows:
    result.append({
        'order_id': row[0],
        'platform': 'ERP',
        'order_date': row[1].strftime('%Y-%m-%d'),
        'amount': float(row[2]),
        'status': row[3],
        'buyer': row[4],
        'item_name': row[5],
        'quantity': int(row[6]),
        'source': 'ERP数据库'
    })
订单列表 = json.dumps(result, ensure_ascii=False)
"""
    )
    
    返回结果(订单列表)
结束子流程

第三部分:数据比对引擎

3.1 建立索引加快比对

# ============================================
# 比对引擎(Python)
# ============================================
import pandas as pd
import json

def reconcile(data_a, data_b, key_field='order_id'):
    """
    数据对账核心引擎
    data_a, data_b: 两个系统的数据列表
    key_field: 用于匹配的唯一键
    返回:比对结果
    """
    # 转换为DataFrame
    df_a = pd.DataFrame(data_a)
    df_b = pd.DataFrame(data_b)
    
    # 建立索引(加速查找)
    df_a.set_index(key_field, inplace=True)
    df_b.set_index(key_field, inplace=True)
    
    # 获取所有键
    keys_a = set(df_a.index)
    keys_b = set(df_b.index)
    
    # 差异分类
    only_in_a = keys_a - keys_b      # A有B无
    only_in_b = keys_b - keys_a      # A无B有
    both = keys_a & keys_b           # 共有
    
    # 数据不一致(字段值不同)
    inconsistent = []
    for key in both:
        row_a = df_a.loc[key]
        row_b = df_b.loc[key]
        diff_fields = []
        
        # 比较关键字段(排除key本身)
        for field in ['amount', 'status', 'quantity']:
            if field in row_a and field in row_b:
                if row_a[field] != row_b[field]:
                    diff_fields.append({
                        'field': field,
                        'value_a': row_a[field],
                        'value_b': row_b[field]
                    })
        
        if diff_fields:
            inconsistent.append({
                'key': key,
                'differences': diff_fields,
                'row_a': row_a.to_dict(),
                'row_b': row_b.to_dict()
            })
    
    # 返回结果
    return {
        'total_a': len(df_a),
        'total_b': len(df_b),
        'only_in_a': list(only_in_a),
        'only_in_b': list(only_in_b),
        'both_count': len(both),
        'inconsistent': inconsistent,
        'consistent_count': len(both) - len(inconsistent)
    }

3.2 影刀中调用比对引擎

# ============================================
# 影刀端:执行对账
# ============================================

# 1. 采集数据
调用子流程(Fetch_Taobao_Orders, 输入: 开始日期, 结束日期, 输出=淘宝订单)
调用子流程(Fetch_ERP_Orders, 输入: 开始日期, 结束日期, 输出=ERP订单)

# 2. 执行对账
执行Python代码(
    输入: 
        data_a=淘宝订单,
        data_b=ERP订单,
        key_field="order_id",
    输出: 
        reconciliation_result=对账结果,
    代码=上面的比对引擎代码
)

解析JSON(对账结果, 存入变量=对账结果对象)

# 3. 输出统计
输出日志("===== 对账结果 =====")
输出日志("A系统(淘宝)总订单数:" + 对账结果["total_a"])
输出日志("B系统(ERP)总订单数:" + 对账结果["total_b"])
输出日志("A有B无:" + 获取列表长度(对账结果["only_in_a"]) + " 条")
输出日志("A无B有:" + 获取列表长度(对账结果["only_in_b"]) + " 条")
输出日志("数据不一致:" + 获取列表长度(对账结果["inconsistent"]) + " 条")
输出日志("数据一致:" + 对账结果["consistent_count"] + " 条")

第四部分:差异分类与处理策略

4.1 差异分类

# ============================================
# 差异分类
# ============================================

# 获取差异列表
A有B无列表 = 对账结果["only_in_a"]
A无B有列表 = 对账结果["only_in_b"]
不一致列表 = 对账结果["inconsistent"]

# ----- 差异分类 -----
设置变量(严重差异 = [])
设置变量(中等差异 = [])
设置变量(轻微差异 = [])

# 1. 金额差异 > 10元 → 严重
按列表循环(不一致列表, 循环项=差异):
    金额A = 差异["row_a"]["amount"]
    金额B = 差异["row_b"]["amount"]
    金额差 = 绝对值(金额A - 金额B)
    
    如果 金额差 > 10:
        将 差异 加入列表(严重差异)
    否则如果 金额差 > 1:
        将 差异 加入列表(中等差异)
    否则:
        将 差异 加入列表(轻微差异)
    结束If
结束循环

# 2. 状态不一致 → 中等
按列表循环(不一致列表, 循环项=差异):
    状态A = 差异["row_a"]["status"]
    状态B = 差异["row_b"]["status"]
    如果 状态A != 状态B:
        如果 差异 不在 严重差异 中:
            将 差异 加入列表(中等差异)
        结束If
    结束If
结束循环

# 3. 数量差异 → 中等
按列表循环(不一致列表, 循环项=差异):
    数量A = 差异["row_a"]["quantity"]
    数量B = 差异["row_b"]["quantity"]
    如果 数量A != 数量B:
        如果 差异 不在 严重差异 中 且 差异 不在 中等差异 中:
            将 差异 加入列表(中等差异)
        结束If
    结束If
结束循环

4.2 差异自动修复

# ============================================
# 差异修复策略
# ============================================

# 1. 金额差异 → 以淘宝为准(假设电商平台数据更准确)
按列表循环(严重差异, 循环项=差异):
    订单号 = 差异["key"]
    正确金额 = 差异["row_a"]["amount"]
    输出日志("【修复】订单 " + 订单号 + " 金额以淘宝为准:" + 正确金额)
    
    # 更新ERP数据库
    执行Python代码(
        输入: order_id=订单号, correct_amount=正确金额,
        代码=更新ERP金额的SQL
    )
结束循环

# 2. A有B无 → 补录到ERP
按列表循环(A有B无列表, 循环项=订单号):
    订单详情 = 查找订单(淘宝订单, 订单号)
    输出日志("【补录】订单 " + 订单号 + " 补录到ERP")
    
    # 调用ERP创建订单API
    调用子流程(Create_ERP_Order, 输入: 订单详情)
结束循环

# 3. A无B有 → 补录到淘宝(或标记为待确认)
按列表循环(A无B有列表, 循环项=订单号):
    订单详情 = 查找订单(ERP订单, 订单号)
    输出日志("【标记】订单 " + 订单号 + " 在淘宝中不存在,标记待确认")
    
    # 写入待确认列表
    将 订单详情 加入列表(待确认订单列表)
结束循环

4.3 差异报告生成

# ============================================
# 生成对账报告
# ============================================

报告 = """
📊 **数据对账报告 - {日期}**
━━━━━━━━━━━━━━━━━━━━━━━━━━━

📋 **总体统计**
• A系统(淘宝):{total_a} 条
• B系统(ERP):{total_b} 条
• 一致:{consistent_count} 条
• 不一致:{inconsistent_count} 条

⚠️ **差异明细**

**严重差异({severe_count}条)**
{severe_detail}

**中等差异({medium_count}条)**
{medium_detail}

**轻微差异({minor_count}条)**
{minor_detail}

🔧 **修复建议**
{fix_suggestions}
━━━━━━━━━━━━━━━━━━━━━━━━━━━
🕐 生成时间:{time}
"""

# 填充报告
报告 = 报告.replace("{日期}", 当前日期)
报告 = 报告.replace("{total_a}", str(对账结果["total_a"]))
报告 = 报告.replace("{total_b}", str(对账结果["total_b"]))
报告 = 报告.replace("{consistent_count}", str(对账结果["consistent_count"]))
报告 = 报告.replace("{inconsistent_count}", str(len(不一致列表)))
报告 = 报告.replace("{severe_count}", str(获取列表长度(严重差异)))
# ... 其他替换

# 发送报告
调用子流程(Send_Notification, 输入: 报告)

第五部分:大文件对账优化

当数据量超过1万行时,需要分块处理:

# ============================================
# 分块对账(大数据量)
# ============================================

子流程 Chunk_Reconciliation(系统A数据, 系统B数据, 分块大小=1000):
    """
    分批对账,避免内存溢出
    """
    A总数 = 获取列表长度(系统A数据)
    B总数 = 获取列表长度(系统B数据)
    
    设置变量(所有差异 = [])
    
    # 按分块大小分批
    A块数 = (A总数 + 分块大小 - 1) // 分块大小
    B块数 = (B总数 + 分块大小 - 1) // 分块大小
    
    # 对A的每个分块,与B的所有分块比对
    # 但更高效:对B建立索引后再分块比对
    执行Python代码(
        输入: data_a=系统A数据, data_b=系统B数据, chunk_size=分块大小,
        输出: 差异结果,
        代码="""
import pandas as pd

def chunk_reconcile(data_a, data_b, chunk_size):
    df_b = pd.DataFrame(data_b)
    df_b.set_index('order_id', inplace=True)
    
    all_diffs = []
    total_chunks = (len(data_a) + chunk_size - 1) // chunk_size
    
    for i in range(total_chunks):
        start = i * chunk_size
        end = min(start + chunk_size, len(data_a))
        chunk_a = data_a[start:end]
        df_chunk = pd.DataFrame(chunk_a)
        df_chunk.set_index('order_id', inplace=True)
        
        # 合并对账
        merged = df_chunk.join(df_b, how='inner', lsuffix='_a', rsuffix='_b')
        # 比较字段...
        # (省略具体比对逻辑)
        
        print(f"已处理分块 {i+1}/{total_chunks}")
    
    return all_diffs
"""
    )
    
    返回结果(差异结果)
结束子流程

第六部分:完整主流程

# ============================================
# 主流程:Daily_Reconciliation
# 执行频率:每天一次
# ============================================

输出日志("===== 每日对账流程启动 =====")

# ----- 1. 设置对账日期(默认昨天)-----
对账日期 = 获取昨天日期()
输出日志("对账日期:" + 对账日期)

# ----- 2. 采集数据 -----
输出日志("【1/4】采集数据")
调用子流程(Fetch_Taobao_Orders, 输入: 对账日期, 输出=淘宝订单)
调用子流程(Fetch_ERP_Orders, 输入: 对账日期, 输出=ERP订单)

# ----- 3. 执行对账 -----
输出日志("【2/4】执行对账")
调用子流程(Reconcile_Data, 
    输入: 淘宝订单, ERP订单,
    输出: 对账结果
)

# ----- 4. 差异处理 -----
输出日志("【3/4】差异处理")
调用子流程(Process_Differences, 输入: 对账结果)

# ----- 5. 生成报告 -----
输出日志("【4/4】生成报告")
调用子流程(Generate_Reconciliation_Report, 输入: 对账结果)

输出日志("===== 每日对账流程完成 =====")

常见问题速查

问题原因解决方法
数据量太大内存不足全部加载到内存用分块对账
订单号格式不一致不同系统命名规则不同做订单号映射表
时区导致日期不对系统时区不同统一用UTC时间
金额小数点位数不同系统精度不同统一四舍五入到两位
状态码不一致系统映射不同建立状态映射表

推荐资源

  • 本系列第63篇《SQLite/MySQL数据库读写》
  • Python Pandas文档(mergejoinconcat
  • 本系列第96篇《数据质量与一致性校验》

#影刀RPA #RPA自动化 #数据对账 #跨系统 #数据一致性

作者:林焱

本文为《影刀RPA学习手册》系列文章之一,内容源于实操经验的整理与分享。

0
0
0
0
评论
未登录
暂无评论