使用bs4从仅含表格的无结构财报中按标题提取指定章节内容
基于BeautifulSoup的财报章节文本提取实现
核心逻辑
- 文档无独立语义标签、不闭合的
<page>标签会被bs4自动修正为覆盖全文档范围的容器,所有章节内容(标题、正文、表格)都属于连续的文档流节点,不需要按DOM嵌套层级递归遍历,直接按文档出现顺序做状态标记即可 - 设置两个判定状态:未进入目标章节、已进入目标章节但未到达结束边界
- 边界判定规则:
- 匹配到起始标题
Management's Discussion and Analysis时,切换为已进入状态,从当前节点开始收集内容 - 匹配到下章节标题
Foreign Affairs时,立刻终止收集流程,跳出遍历
- 匹配到起始标题
代码实现
from bs4 import BeautifulSoup # 替换为实际的财报文件读取逻辑 with open("target_financial_report.html", "r", encoding="utf-8") as f: raw_html = f.read() # html.parser会自动修正不闭合的<page>标签,无需额外特殊处理 soup = BeautifulSoup(raw_html, "html.parser") # 定义章节边界标题 SECTION_START = "Management's Discussion and Analysis" SECTION_END = "Foreign Affairs" is_in_target = False collected_parts = [] # 按文档流顺序遍历所有节点(包含元素、纯文本节点,不受DOM嵌套影响) for node in soup.descendants: # 跳过空的空白、注释节点 if hasattr(node, "get_text"): current_text = node.get_text(strip=True) else: current_text = str(node).strip() if not current_text: continue # 碰到结束标题直接停止收集 if SECTION_END in current_text: break # 碰到起始标题,切换收集状态 if SECTION_START in current_text: is_in_target = True collected_parts.append(current_text) continue # 处于目标章节范围内时持续收集内容 if is_in_target: collected_parts.append(current_text) # 拼接最终提取的章节文本 final_section_text = "\n".join(collected_parts)
特殊场景适配
- 跨分页标题截断处理:如果标题因为分页被拆成相邻的零散文本节点(比如标题前半段在上一页末尾,后半段在下一页开头),可以在遍历前先合并相邻的纯文本节点,再做标题匹配,避免漏识别起始位置
- 误匹配规避:如果正文内容中出现和边界标题完全一致的字符串,可以把子串匹配规则改为精确文本匹配,也就是判断节点文本和标题完全相等时才切换状态
- 格式保留需求:如果需要保留原文档的表格、换行排版,不需要逐节点提取纯文本,可以在识别到起始节点后,顺着
next_elements顺着文档流抓取到结束节点前的所有元素,批量导出带格式的内容
内容的提问来源于stack exchange,提问作者Yash Sandansing
相关产品推荐
相关产品推荐

