基于 TextIn 与 Coze 的财报数据自动化抽取实践
本文介绍利用 TextIn 智能文档解析与 Coze 自动化工作流构建财报抽取机器人的方案。针对财报 PDF 表格结构复杂、格式多样及手工处理成本高的问题,通过 xParse 引擎统一解析电子 PDF 与扫描件,结合 Coze 编排文件上传、解析、抽取及输出流程。方案包含标题命中策略、数据结构约定及关键代码实现,支持多期报表对比与结构化导出,实现从原始文档到业务可用数据的端到端自动化。

本文介绍利用 TextIn 智能文档解析与 Coze 自动化工作流构建财报抽取机器人的方案。针对财报 PDF 表格结构复杂、格式多样及手工处理成本高的问题,通过 xParse 引擎统一解析电子 PDF 与扫描件,结合 Coze 编排文件上传、解析、抽取及输出流程。方案包含标题命中策略、数据结构约定及关键代码实现,支持多期报表对比与结构化导出,实现从原始文档到业务可用数据的端到端自动化。

面对季度、年度财报堆叠如山的 PDF 文档,技术团队如何快速、准确地将其中复杂的表格数据转化为结构化信息?本文将介绍一种高效实践方案:利用 TextIn 的智能文档解析能力,结合 Coze 的自动化工作流编排,快速构建一个能够处理多格式财报、抽取关键表格的自动化流程。
财报处理长期存在几大核心难点:
1. 表格结构复杂:资产负债表、利润表等核心表格常存在跨页、续表情况,且合并报表与母公司报表两套体系并存,单元格合并频繁,对程序的结构化识别构成首要挑战。
2. 文档格式多样:资料库中通常是电子 PDF 与扫描件图像混合共存,要求解决方案同时具备强大的文本解析与 OCR 版面分析能力。
3. 手工处理成本高昂:三大表及附注的手动复制、粘贴、核对工作极其耗时,且容易出错,难以满足及时性、准确性要求。
本方案采用清晰的分工架构,将复杂问题模块化:
这种组合将专业的文档解析、灵活的业务逻辑编排与友好的交互界面相结合,使开发者能聚焦于核心的抽取规则,快速搭建从原始文档到业务可用数据的端到端流水线。
财报机器人使用演示:
工作流: ![工作流架构图]
输出结果: ![输出结果图]
开始节点:接收用户上传的财报文件(File)。
TextIn 插件节点:将财报解析为结构化 JSON,核心使用 result.detail(包含 paragraph/table/image 等元素)以及 result.markdown。
代码节点:仅遍历 detail,通过'表标题 → 后续表格'方式抽取三大表,并统一输出为 tables{balanceSheet,incomeStatement,cashFlow}。
结束节点:将 tables / debug / markdown 输出给 Bot,用于展示与后续问答分析。
TextIn xParse - 插件节点的输出(result.detail / result.markdown 等,详情见 TextIn xParse API 文档)
Response {
code: # 接口状态码
message: # 状态信息
result: {
markdown: # 文档级 Markdown
detail[]: # 元素明细数组(只处理 type=table)
(仅当 item.type == "table" 时关注)
type: # 固定为 "table"(表格块)
sub_type: # "bordered"(有线) / "borderless"(无线)
page_id: # 表格所在页(续表拼接用)
paragraph_id: # 表格元素 ID(续表拼接用)
rows: # 表格行数
cols: # 表格列数
text: # 表格整体文本(md/html;展示用,抽字段优先 cells)
continue?: # 是否跨页/跨段续表(可选字段)
cells[]: # 单元格数组(抽取字段核心)
row: # 行号(从 0 开始)
col: # 列号(从 0 开始)
row_span?: # 行合并跨度(默认 1)
col_span?: # 列合并跨度(默认 1)
text: # 单元格文本(字段值通常从这里拿)
}
}
TextIn 的返回结果中对表格块(type=table)的两种常见数据形态(务必兼容)
形态 A:HTML/Markdown 表格(最常见于工作流插件输出) 抽取方式:解析
text→ 转二维矩阵(headers/rows)item.text内包含<table>...</table>(或 Markdown table)item.type == "table"形态 B:单元格数组 cells(部分接口/参数下提供)
item.cells[]存在,包含row/col/text等 抽取方式:优先用cells拼 matrix(更结构化),不存在再回退到解析text
财务三大表抽取 - 代码节点的输出示例(tables)
tables.balanceSheet / incomeStatement / cashFlow均为数组,设计理由如下:
title/page_id再做合并与筛选。tables
{
"balanceSheet": [
{
"headers": [ "项 目", "附注", "2025 年 6 月 30 日", "2024 年 12 月 31 日" ],
"page_id": [ 2 ],
"rows": [ [ "流动资产:", "", "-", "-" ] ],
"title": "合并资产负债表"
}
],
"incomeStatement": [
{
"headers": [ "项 目", "附注", "2025 年 1-6 月", "2024 年 1-6 月" ],
"page_id": [ 4 ],
"rows": [ [ "一、营业总收入", "", "88,095,798,091.41", "85,336,441,428.97" ] ],
"title": "母公司利润表"
}
],
"cashFlow": [
{
"headers": [ "项 目", "附注", "2025 年 1-6 月", "2024 年 1-6 月" ],
"page_id": [ 5 ],
"rows": [ [ "一、经营活动产生的现金流量;", "", "-", "-" ] ],
"title": "母公司现金流量表"
}
]
}
Debug
{
"debug": {
"detailLen": 823,
"titleCandidates": 6,
"hitTitles": [
{ "idx": 120, "page_id": 2, "title": "合并资产负债表" },
{ "idx": 260, "page_id": 4, "title": "母公司利润表" }
],
"picked": [
{ "titleIdx": 120, "tableIdx": 125, "tableType": "balanceSheet" },
{ "titleIdx": 260, "tableIdx": 268, "tableType": "incomeStatement" }
],
"tableBlocks": 12
}
}
标题命中策略(table_title + 关键词)
sub_type=table_title:优先使用版面分析识别到的'表格标题'元素,减少正文段落(header/text)误命中概率。代码实现:
const TITLE_PATTERNS = {
balanceSheet: ["资产负债表", "合并资产负债表", "母公司资产负债表"],
incomeStatement: ["利润表", "合并利润表", "母公司利润表", "损益表", "收益表"],
cashFlow: ["现金流量表", "合并现金流量表", "母公司现金流量表", "现金流量"]
};
function normalizeTitle(s) {
return String(s || "")
.replace(/\*\*/g, "")
.replace(/[\s ]/g, "")
.replace(/[《》]/g, "");
}
function matchType(norm) {
for (const [k, kws] of Object.entries(TITLE_PATTERNS)) {
if (kws.some(kw => norm.includes(kw))) return k;
}
return null;
}
function extractFromDetail(detail) {
const tables = {
balanceSheet: [],
incomeStatement: [],
cashFlow: []
};
const debug = {
hitTitles: [],
picked: [],
tableBlocks: 0,
titleCandidates: 0
};
for (let i = 0; i < detail.length; i++) {
const item = detail[i];
if (!item || typeof item !== "object") continue;
const rawTitle = String(item.text || "");
const title = normalizeTitle(rawTitle);
// ✅ 简单校验:标题长度太长跳过
if (title.length > 20) continue;
// ✅ 查询 TextIn 接口返回数据中的表格标题,避免正文误命中
if (String(item.sub_type || "").toLowerCase() !== "table_title") continue;
const ttype = matchType(title);
if (!ttype) continue;
debug.hitTitles.push({ idx: i, page_id: item.page_id, title: rawTitle });
debug.titleCandidates++;
// 查找后续表格
let j = i + 1;
while (j < detail.length) {
const nextItem = detail[j];
if (!nextItem || nextItem.type !== "table") break;
// 找到第一个表格即视为该标题下的表
tables[ttype].push({
headers: nextItem.headers || [],
page_id: nextItem.page_id ? [nextItem.page_id] : [],
rows: nextItem.rows || [],
title: rawTitle
});
debug.picked.push({
titleIdx: i,
tableIdx: j,
tableType: ttype
});
debug.tableBlocks++;
break;
}
}
return { tables, debug };
}
TextIn 开发者信息(x-ti-app-id / secret_code)
x-ti-app-id 与 x-ti-secret-code(下文统称 app_id/secret_code)。ParseX.result(作为代码节点输入),其中 result.detail 是抽表主数据源。ParseX.result)tables{balanceSheet,incomeStatement,cashFlow} + debug财报抽取机器人是一个高效的起点,接下来,基于 TextIn 提供的精准结构化数据与 Coze 灵活的工作流,还可以轻松延伸出更多智能化的数据处理能力:
title 相同且表头一致合并 rows,并合并 page_id,彻底解决数据割裂问题。tables 列表,通过添加代码节点或 Coze 插件,转换为更通用的 CSV 或 XLSX 格式文件。这能让财务、业务部门的同事无缝接手,直接在 Excel 环境中进行后续分析与可视化。通过 TextIn 与 Coze 的组合,我们完成了从杂乱文档到结构化数据,再到可交互、可扩展的业务工具的完整路径,构建了一个可靠、可重复、且持续进化的数据流水线。无论是应对合规检查,还是满足定期的经营分析,这个财报机器人都能成为你技术工具箱中一个反应迅速、值得信赖的数字化助手。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online