4. 识别财报中的会计期间
任务说明
从一份财报文本中识别其对应的会计期间(如“2023年年度报告”)。输入为财报文本字符串,输出为结构化的期间信息:报告年度、报告类型(年度/半年度/一季度/三季度),以及标准化的期间描述。
实现思路
财报文本中,会计期间通常出现在标题、页眉或正文首段,常见格式包括:
- “XX股份有限公司2023年年度报告”
- “2023年第一季度报告”
- “2023年半年度报告”
- “2023年第三季度报告”
核心策略:用正则表达式匹配“20xx年”与报告类型关键词的组合,优先匹配标题行(前200个字符内),若未命中再全文搜索。报告类型关键词按优先级排序,避免“年度”被“半年度”错误截断。
完整代码
import re
from typing import Optional, Dict
def identify_report_period(text: str) -> Optional[Dict[str, str]]:
"""
从财报文本中识别会计期间。
返回: {"year": "2023", "period_type": "annual", "description": "2023年年度报告"}
未识别到时返回 None。
"""
# 报告类型关键词(按优先级从高到低排列)
period_patterns = [
("annual", r"年度报告"),
("semi_annual", r"半年度报告"),
("q3", r"第三季度报告|三季度报告"),
("q1", r"第一季度报告|一季度报告"),
]
# 年份匹配:20xx年
year_pattern = r"(20[0-2]\d)年"
# 优先在标题区域(前200字符)查找
search_regions = [text[:200], text]
for region in search_regions:
for period_type, type_pattern in period_patterns:
# 组合匹配:年份 + 报告类型
combined = re.search(year_pattern + r"?" + type_pattern, region)
if combined:
# 提取年份(若组合中未捕获,则单独在附近查找)
year_match = re.search(year_pattern, region[:combined.end()])
if not year_match:
continue
year = year_match.group(1)
return {
"year": year,
"period_type": period_type,
"description": f"{year}年{combined.group(0).replace(year + '年', '')}"
}
# 兜底:单独找年份 + 报告类型(允许中间有其他字符)
for period_type, type_pattern in period_patterns:
type_match = re.search(type_pattern, text)
if type_match:
# 在类型词前50字符内找年份
start = max(0, type_match.start() - 50)
year_match = re.search(year_pattern, text[start:type_match.start()])
if year_match:
year = year_match.group(1)
return {
"year": year,
"period_type": period_type,
"description": f"{year}年{type_match.group(0)}"
}
return None
# 最小调用示例
if __name__ == "__main__":
sample = "江苏恒瑞医药股份有限公司2023年年度报告"
result = identify_report_period(sample)
print(result)
# 预期输出: {'year': '2023', 'period_type': 'annual', 'description': '2023年年度报告'}
运行与验证
- 将上述代码保存为
identify_period.py,直接运行:python identify_period.py,观察输出是否为示例中的预期结果。 - 用以下测试用例验证识别准确性:
test_cases = [
"万科企业股份有限公司2023年半年度报告",
"中兴通讯2023年第一季度报告全文",
"中国平安保险(集团)股份有限公司2023年第三季度报告",
"某公司2022年年度报告摘要",
"没有期间信息的普通文本"
]
for t in test_cases:
print(t, "->", identify_report_period(t))
通过条件:前4条分别正确识别为半年度、一季度、三季度、年度;第5条返回 None。若某条未识别或类型错误,说明正则顺序或年份提取逻辑需调整。
关键说明
- 正则中
year_pattern + "?" + type_pattern的?表示年份可省略,实际匹配时年份仍会被后续逻辑捕获,这样设计是为了兼容“年度报告”前无年份但正文有年份的情况。 - 标题区域优先搜索可避免正文中“本报告期”等干扰词影响判断;若标题区未命中,再全文搜索并回溯年份。
- “半年度”必须排在“年度”之前匹配,否则“半年度报告”会被“年度报告”错误截断为“年度”。