银行对账单分析器 - 简化版
中级
这是一个Document Extraction, AI Summarization领域的自动化工作流,包含 9 个节点。主要使用 If, Code, OpenAi, Webhook, Postgres 等节点。 AI驱动银行对账单分析与交易分类
前置要求
- •OpenAI API Key
- •HTTP Webhook 端点(n8n 会自动生成)
- •PostgreSQL 数据库连接信息
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
"name": "银行对账单分析器 - 简化版",
"tags": [],
"nodes": [
{
"id": "webhook-001",
"name": "上传对账单",
"type": "n8n-nodes-base.webhook",
"position": [
400,
300
],
"parameters": {
"path": "/upload-statement",
"options": {
"rawBody": true
},
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "file-handler-001",
"name": "文件处理器",
"type": "n8n-nodes-base.code",
"position": [
600,
300
],
"parameters": {
"jsCode": "// Simple file processor\nconst inputData = $input.all()[0];\nconst files = [];\n\n// Handle file uploads\nif (inputData.binary) {\n Object.keys(inputData.binary).forEach(key => {\n const file = inputData.binary[key];\n files.push({\n filename: file.fileName,\n contentType: file.mimeType,\n uploadedAt: new Date().toISOString()\n });\n });\n}\n\nreturn files.map(file => ({\n json: {\n filename: file.filename,\n contentType: file.contentType,\n uploadedAt: file.uploadedAt,\n status: 'ready_for_processing'\n },\n binary: inputData.binary\n}));"
},
"typeVersion": 2
},
{
"id": "file-type-switch-001",
"name": "检查文件类型",
"type": "n8n-nodes-base.if",
"position": [
800,
300
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "pdf-condition",
"operator": {
"type": "string",
"operation": "contains"
},
"leftValue": "={{ $json.contentType }}",
"rightValue": "application/pdf"
}
]
}
},
"typeVersion": 2
},
{
"id": "pdf-extractor-001",
"name": "提取PDF文本",
"type": "n8n-nodes-base.extractFromFile",
"position": [
1000,
200
],
"parameters": {
"operation": "extractText"
},
"typeVersion": 1
},
{
"id": "excel-parser-001",
"name": "解析Excel/CSV",
"type": "n8n-nodes-base.spreadsheetFile",
"position": [
1000,
400
],
"parameters": {
"options": {
"headerRow": 0
},
"operation": "parseExcel"
},
"typeVersion": 2
},
{
"id": "ai-extractor-001",
"name": "AI数据提取器",
"type": "n8n-nodes-base.openAi",
"position": [
1200,
300
],
"parameters": {
"model": "gpt-4o-mini",
"messages": {
"values": [
{
"role": "system",
"content": "Extract bank statement data and return clean JSON:\n\n{\n \"account_number\": \"****1234\",\n \"bank_name\": \"Bank Name\",\n \"statement_period\": \"2024-01-01 to 2024-01-31\",\n \"opening_balance\": 1500.00,\n \"closing_balance\": 1250.00,\n \"transactions\": [\n {\n \"date\": \"2024-01-15\",\n \"description\": \"GROCERY STORE\",\n \"amount\": -45.67,\n \"category\": \"groceries\"\n }\n ]\n}\n\nUse negative amounts for expenses, positive for income. Categorize transactions as: groceries, dining, gas, shopping, utilities, healthcare, entertainment, income, fees, or other."
},
{
"role": "user",
"content": "{{ $json.data || $json.extracted_text }}"
}
]
}
},
"credentials": {
"openAiApi": {
"id": "",
"name": "OpenAI API"
}
},
"typeVersion": 1
},
{
"id": "data-processor-001",
"name": "处理与汇总",
"type": "n8n-nodes-base.code",
"position": [
1400,
300
],
"parameters": {
"jsCode": "// Clean and validate extracted data\nconst inputData = $input.all()[0];\nlet extractedData = {};\n\n// Parse AI response\ntry {\n const content = inputData.json.message?.content || inputData.json;\n if (typeof content === 'string') {\n const jsonMatch = content.match(/{[\\s\\S]*}/);\n if (jsonMatch) {\n extractedData = JSON.parse(jsonMatch[0]);\n }\n } else {\n extractedData = content;\n }\n} catch (error) {\n console.log('Parse error:', error.message);\n extractedData = { transactions: [] };\n}\n\n// Clean transaction data\nconst cleanTransactions = (extractedData.transactions || []).map((tx, index) => ({\n id: `tx_${Date.now()}_${index}`,\n date: tx.date,\n description: (tx.description || '').trim().toUpperCase(),\n amount: parseFloat(tx.amount) || 0,\n category: tx.category || 'other',\n processed_at: new Date().toISOString()\n}));\n\n// Calculate summary\nconst totalExpenses = cleanTransactions\n .filter(tx => tx.amount < 0)\n .reduce((sum, tx) => sum + Math.abs(tx.amount), 0);\n\nconst totalIncome = cleanTransactions\n .filter(tx => tx.amount > 0)\n .reduce((sum, tx) => sum + tx.amount, 0);\n\nconst categoryTotals = {};\ncleanTransactions.forEach(tx => {\n if (tx.amount < 0) { // Only expenses\n categoryTotals[tx.category] = (categoryTotals[tx.category] || 0) + Math.abs(tx.amount);\n }\n});\n\nreturn [{\n json: {\n account_info: {\n account_number: extractedData.account_number || 'Unknown',\n bank_name: extractedData.bank_name || 'Unknown',\n statement_period: extractedData.statement_period || 'Unknown',\n opening_balance: parseFloat(extractedData.opening_balance) || 0,\n closing_balance: parseFloat(extractedData.closing_balance) || 0\n },\n transactions: cleanTransactions,\n summary: {\n total_transactions: cleanTransactions.length,\n total_expenses: totalExpenses,\n total_income: totalIncome,\n net_change: totalIncome - totalExpenses,\n category_breakdown: categoryTotals\n },\n processed_at: new Date().toISOString(),\n status: 'completed'\n }\n}]);"
},
"typeVersion": 2
},
{
"id": "save-to-db-001",
"name": "保存到数据库",
"type": "n8n-nodes-base.postgres",
"position": [
1600,
200
],
"parameters": {
"table": "bank_statements",
"columns": {
"value": {
"raw_data": "={{ JSON.stringify($json) }}",
"bank_name": "={{ $json.account_info.bank_name }}",
"processed_at": "={{ $json.processed_at }}",
"total_income": "={{ $json.summary.total_income }}",
"account_number": "={{ $json.account_info.account_number }}",
"total_expenses": "={{ $json.summary.total_expenses }}",
"statement_period": "={{ $json.account_info.statement_period }}",
"total_transactions": "={{ $json.summary.total_transactions }}"
},
"mappingMode": "defineBelow"
},
"resource": "database",
"operation": "insert"
},
"credentials": {
"postgres": {
"id": "",
"name": "PostgreSQL"
}
},
"typeVersion": 2.4
},
{
"id": "response-001",
"name": "发送响应",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
1600,
400
],
"parameters": {
"respondWith": "json",
"responseBody": "={\n \"success\": true,\n \"message\": \"Statement processed successfully\",\n \"data\": {\n \"account\": \"{{ $json.account_info.account_number }}\",\n \"transactions_processed\": {{ $json.summary.total_transactions }},\n \"total_expenses\": {{ $json.summary.total_expenses }},\n \"total_income\": {{ $json.summary.total_income }},\n \"categories\": {{ JSON.stringify($json.summary.category_breakdown) }}\n }\n}"
},
"typeVersion": 1
}
],
"notes": [
{
"id": "note-001",
"width": 160,
"height": 80,
"content": "📥 **ENTRY POINT**\n\nUsers upload bank statements here via POST request",
"position": [
320,
180
]
},
{
"id": "note-002",
"width": 160,
"height": 100,
"content": "🔍 **FILE PREP**\n\nExtracts file info and prepares for processing. Handles multiple file formats.",
"position": [
520,
180
]
},
{
"id": "note-003",
"width": 160,
"height": 120,
"content": "🔀 **SMART ROUTING**\n\nPDFs go to text extraction\nExcel/CSV files go to spreadsheet parser\n\nAutomatic format detection",
"position": [
720,
120
]
},
{
"id": "note-004",
"width": 160,
"height": 90,
"content": "📄 **PDF HANDLER**\n\nExtracts text from PDF bank statements using OCR",
"position": [
920,
80
]
},
{
"id": "note-005",
"width": 160,
"height": 90,
"content": "📊 **SPREADSHEET HANDLER**\n\nParses Excel/CSV files and converts to structured data",
"position": [
920,
480
]
},
{
"id": "note-006",
"width": 160,
"height": 140,
"content": "🤖 **AI MAGIC**\n\nGPT-4 extracts:\n• Account details\n• All transactions \n• Auto-categorizes expenses\n• Calculates balances\n\nSmart & accurate!",
"position": [
1120,
140
]
},
{
"id": "note-007",
"width": 160,
"height": 120,
"content": "🧹 **DATA CLEANUP**\n\nCleans & validates:\n• Transaction formatting\n• Amount calculations\n• Category summaries\n• Error handling",
"position": [
1320,
140
]
},
{
"id": "note-008",
"width": 160,
"height": 80,
"content": "💾 **PERSISTENCE**\n\nSaves processed data to PostgreSQL database",
"position": [
1520,
80
]
},
{
"id": "note-009",
"width": 160,
"height": 100,
"content": "✅ **SUCCESS RESPONSE**\n\nReturns summary:\n• Transaction count\n• Expense totals\n• Category breakdown",
"position": [
1520,
480
]
},
{
"id": "note-010",
"width": 200,
"height": 120,
"content": "💡 **WORKFLOW FEATURES**\n\n✓ Handles PDF & Excel files\n✓ AI-powered extraction \n✓ Auto-categorization\n✓ Database storage\n✓ Clean API responses",
"position": [
200,
450
]
},
{
"id": "note-011",
"width": 180,
"height": 140,
"content": "🎯 **TYPICAL OUTPUT**\n\n```json\n{\n \"success\": true,\n \"transactions_processed\": 45,\n \"total_expenses\": 2847.32,\n \"categories\": {\n \"groceries\": 450.23,\n \"dining\": 287.45\n }\n}\n```",
"position": [
1700,
240
]
}
],
"pinData": {},
"updatedAt": "2024-01-15T10:30:00.000Z",
"versionId": "1",
"staticData": null,
"connections": {
"File Handler": {
"main": [
[
{
"node": "Check File Type",
"type": "main",
"index": 0
}
]
]
},
"Check File Type": {
"main": [
[
{
"node": "Extract PDF Text",
"type": "main",
"index": 0
}
],
[
{
"node": "Parse Excel/CSV",
"type": "main",
"index": 0
}
]
]
},
"Parse Excel/CSV": {
"main": [
[
{
"node": "AI Data Extractor",
"type": "main",
"index": 0
}
]
]
},
"Extract PDF Text": {
"main": [
[
{
"node": "AI Data Extractor",
"type": "main",
"index": 0
}
]
]
},
"Upload Statement": {
"main": [
[
{
"node": "File Handler",
"type": "main",
"index": 0
}
]
]
},
"AI Data Extractor": {
"main": [
[
{
"node": "Process & Summarize",
"type": "main",
"index": 0
}
]
]
},
"Process & Summarize": {
"main": [
[
{
"node": "Save to Database",
"type": "main",
"index": 0
},
{
"node": "Send Response",
"type": "main",
"index": 0
}
]
]
}
},
"triggerCount": 0
}常见问题
如何使用这个工作流?
复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。
这个工作流适合什么场景?
中级 - 文档提取, AI 摘要总结
需要付费吗?
本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。
相关工作流推荐
我的工作流 4
使用ScrapeGraphAI监控供应商财务健康状况与多渠道风险预警
If
Set
Code
+4
18 节点vinci-king-01
文档提取
我的工作流 2
通过Slack和邮件使用ScrapeGraphAI监控供应链风险预警
If
Set
Code
+5
18 节点vinci-king-01
文档提取
AI驱动的GPT-4-Turbo作业评分与多格式输出
使用GPT-4-Turbo自动化作业评分并生成多格式报告
Set
Code
Webhook
+7
15 节点Cheng Siong Chin
文档提取
我的工作流程 2
使用 ScrapeGraphAI、GPT-4 和 Google Sheets 自动化深度研究
Code
Merge
Webhook
+5
16 节点vinci-king-01
市场调研
AI驱动的同行评审作业系统,带自动评分标准生成
使用GPT-4-nano、Slack和邮件通知自动化同行评审分配
Set
Code
Slack
+9
22 节点Cheng Siong Chin
文档提取
销售管道自动化仪表板
使用HubSpot CRM、ScrapeGraphAI和Google Sheets仪表板自动化销售管道
If
Code
Slack
+7
22 节点vinci-king-01
客户关系管理