财报数据结构化:非结构化财报文本解析、表格数据抽取、关键财务指标提取
做财报分析这么多年,我最大的感触就是——数据才是硬道理。但现实很骨感,你拿到的财报往往是PDF、图片甚至扫描件。这些非结构化数据,说白了就是一堆“死”信息,机器看不懂,人也难提取。怎么办?
这一章,我们就来聊聊怎么把这些“死”数据变“活”。我个人习惯把整个过程拆成三步:文本解析、表格抽取、指标提取。每一步都有坑,咱们一个一个踩过去。
一、非结构化财报文本解析
先说说文本解析。财报里的文字部分,比如“管理层讨论”、“风险提示”,这些内容虽然不像表格那么规整,但信息量巨大。我早期做项目时,直接拿正则去匹配,结果发现——根本行不通。为什么?因为财报的排版千奇百怪,有的用分号,有的用句号,有的甚至用空格当分隔符。
核心思路:用OCR + NLP 组合拳。先通过OCR把图片转成文字,再用NLP做实体识别和关系抽取。
举个例子,我常用的工具是 pytesseract 配合 spaCy。代码大概长这样:
import pytesseract
from PIL import Image
import spacy
# 加载中文模型
nlp = spacy.load("zh_core_web_sm")
# OCR识别
img = Image.open("财报截图.png")
text = pytesseract.image_to_string(img, lang='chi_sim')
# NLP解析
doc = nlp(text)
for ent in doc.ents:
print(ent.text, ent.label_)
嗯,这里要注意:OCR的准确率直接决定了后续分析的质量。我遇到过最坑的一次,是把“净利润”识别成了“净利闰”,结果指标全乱了。所以,我建议你在OCR之后,加一层拼写校正或者词典匹配。
避坑指南:我曾经在某个项目中,直接用默认OCR参数去解析一份扫描版财报,结果识别率不到60%。后来加了图像预处理(二值化、去噪),识别率才提到85%以上。
二、表格数据抽取
表格是财报的“硬骨头”。利润表、资产负债表、现金流量表,这些表格结构复杂,有的跨行,有的跨列,有的甚至合并单元格。你想想看,如果直接按行读取,很容易把“营业收入”和“营业成本”搞混。
我个人习惯用 camelot 或 tabula-py 这类工具。它们专门针对PDF表格做了优化。举个例子:
import camelot
# 读取PDF中的表格
tables = camelot.read_pdf("财报.pdf", pages="1-3", flavor="lattice")
for table in tables:
print(table.df) # 输出DataFrame格式
这里有个关键点:flavor 参数。如果是带边框的表格,用 lattice;如果是无边框的,用 stream。我刚开始做的时候,总是默认用 lattice,结果遇到无边框表格就全乱了。后来才学会先看一眼表格样式,再选参数。
警告:表格抽取后,一定要做后处理。比如合并单元格、去除空行、对齐列名。我曾经因为没做后处理,直接把抽取的数据喂给模型,结果模型学了一堆噪声。
抽取完成后,我一般会转成结构化数据,比如CSV或JSON。这样后续的指标提取就方便多了。
三、关键财务指标提取
指标提取,说白了就是从结构化数据里“挖”出我们关心的数字。比如营收、净利润、毛利率、资产负债率等等。这些指标通常有固定的名称和位置,但不同财报的表述可能不一样。比如“营业收入”有的叫“主营业务收入”,有的叫“营收”。
我的做法是:建一个指标词典,把同义词都列进去。然后基于规则或正则去匹配。代码示例:
import re
# 指标词典
indicator_dict = {
"营业收入": ["营业收入", "主营业务收入", "营收"],
"净利润": ["净利润", "净利", "归属于母公司股东的净利润"],
"毛利率": ["毛利率", "销售毛利率"]
}
def extract_indicator(text, indicator_name):
patterns = indicator_dict[indicator_name]
for pattern in patterns:
match = re.search(rf"{pattern}[::]\s*([\d,]+\.?\d*)", text)
if match:
return float(match.group(1).replace(",", ""))
return None
你可能会问:如果财报里没有直接给出指标,比如毛利率需要自己算怎么办?嗯,这种情况很常见。我的做法是:先提取“营业收入”和“营业成本”,然后手动计算毛利率。说白了,就是多一步计算逻辑。
核心经验:指标提取的准确率,90%取决于词典的完备性。我建议你定期更新词典,尤其是遇到新财报格式时。
知识体系框架
为了让你更直观地理解整个流程,我画了一张图。这张图展示了从非结构化财报到结构化指标的完整链路:
这张图里,左边是非结构化财报,中间是解析和抽取两个并行路径,右边是最终的结构化指标。你想想看,如果没有中间这两步,我们只能手动去翻财报,效率低不说,还容易出错。
实践中的注意事项
最后,我总结几个实战中容易踩的坑:
- 编码问题:中文财报经常出现GBK、UTF-8混用的情况。我建议统一转成UTF-8,否则解析时会出现乱码。
- 表格合并:有些财报的表格是跨页的,比如“资产负债表”可能从第2页延续到第3页。抽取时要注意合并,否则数据会断。
- 指标单位:有的财报用“亿元”,有的用“万元”。提取后一定要统一单位,否则计算会出错。我习惯全部转成“元”。
- 异常值处理:财报里偶尔会出现“-”或“N/A”表示无数据。这些要提前过滤掉,否则会影响后续分析。
个人经验:我做过一个项目,需要从1000份财报中提取“研发投入”指标。一开始用正则匹配,准确率只有70%。后来改用BERT做实体识别,准确率提到了92%。但代价是训练成本高。所以,具体用什么方法,要看你的数据量和精度要求。
好了,这一章的内容就到这里。记住,数据结构化是财报分析的地基。地基不稳,后面的一切都是空中楼阁。