2. 提取利润表中的营业收入
任务说明
利润表中的“营业收入”在不同企业的报表中可能存在多种表述,例如“营业总收入”“营业收入”“主营业务收入”等。本案例的目标是:给定一段利润表文本,自动定位并提取营业收入金额,同时识别其原始表述方式,为后续财务指标计算提供结构化输入。
实现方案
采用关键词匹配 + 正则表达式提取的方式。核心逻辑为:先通过关键词列表定位包含营业收入的行,再从该行中提取数值(支持千分位逗号与负号),最后返回金额与匹配到的原始表述。为覆盖常见格式,关键词按优先级排序,优先匹配更精确的表述。
代码实现
import re
from typing import Optional, Tuple
# 营业收入常见表述(按优先级从高到低排列)
REVENUE_KEYWORDS = [
"营业总收入",
"营业收入",
"主营业务收入",
"一、营业收入", # 部分报表带编号前缀
"营业收入合计",
]
def extract_revenue(text: str) -> Optional[Tuple[str, float]]:
"""
从利润表文本中提取营业收入。
参数:
text: 利润表文本(可包含多行)
返回:
(原始表述, 金额数值) 元组;若未找到则返回 None。
金额为负数时表示亏损(极少见,但保留处理能力)。
"""
if not text or not text.strip():
return None
# 按行拆分,逐行匹配
for line in text.splitlines():
line = line.strip()
if not line:
continue
# 1. 先检查该行是否包含任一关键词
matched_keyword = None
for kw in REVENUE_KEYWORDS:
if kw in line:
matched_keyword = kw
break
if matched_keyword is None:
continue
# 2. 从该行提取数值(支持千分位逗号、负号、小数点)
# 匹配模式:可选负号 + 数字 + 可选(千分位逗号+3位数字)* + 可选(.小数)
number_pattern = r'-?\d{1,3}(?:,\d{3})*(?:\.\d+)?|-?\d+(?:\.\d+)?'
matches = re.findall(number_pattern, line)
if not matches:
continue
# 3. 取最后一个数值(通常金额位于行末;若行末为括号注释则取最后一个数字)
raw_number = matches[-1].replace(',', '')
try:
value = float(raw_number)
except ValueError:
continue
# 4. 返回原始表述(用整行文本作为表述,便于追溯)
return line, value
return None
# ---------- 最小验证闭环 ----------
if __name__ == "__main__":
# 测试样本1:标准表述
sample1 = """利润表
编制单位:XX股份有限公司
项目本期金额上期金额
一、营业总收入 1,234,567,890.00 987,654,321.00
二、营业总成本 1,000,000,000.00 800,000,000.00"""
result1 = extract_revenue(sample1)
print("样本1结果:", result1)
assert result1 is not None
assert result1[1] == 1234567890.00
assert "营业总收入" in result1[0]
# 测试样本2:仅写“营业收入”
sample2 = "利润表\n营业收入 500,000.00\n营业成本 300,000.00"
result2 = extract_revenue(sample2)
print("样本2结果:", result2)
assert result2 is not None
assert result2[1] == 500000.00
# 测试样本3:无营业收入(应返回None)
sample3 = "利润表\n营业成本 100.00\n管理费用 50.00"
result3 = extract_revenue(sample3)
print("样本3结果:", result3)
assert result3 is None
# 测试样本4:带编号前缀
sample4 = "利润表\n一、营业收入 1,000.00\n二、营业成本 800.00"
result4 = extract_revenue(sample4)
print("样本4结果:", result4)
assert result4 is not None
assert result4[1] == 1000.00
print("全部测试通过")
运行与验证
运行方式:将上述代码保存为 extract_revenue.py,在命令行执行 python extract_revenue.py。
验证标准:程序输出4个样本的提取结果,并在最后打印“全部测试通过”。每个样本的断言(assert)均验证了金额数值与表述匹配的正确性。若所有断言通过,说明代码能正确识别不同表述并提取金额;若某个断言失败,程序将抛出异常并终止。
关键说明
- 代码优先匹配更精确的关键词(如“营业总收入”优先于“营业收入”),避免“营业收入”误匹配到“营业总收入”所在行时提取错误金额。
- 数值提取采用正则表达式,兼容千分位逗号与小数;若同一行出现多个数字(如本期与上期并列),默认取最后一个数值——实际使用时可根据报表列顺序调整索引。
- 若报表中营业收入为负数(极端情况),代码同样能正确提取负值。