如何从SEC 10-K HTML文档中提取Item 1板块对应的文本内容
SEC 10-K文档Item 1板块文本提取代码调整方案
原有代码问题
- 语法混用:同时调用Scrapy的
response.css方法和BeautifulSoup解析逻辑,结构混乱。且BeautifulSoup的select方法第二个参数为命名空间参数,无法用于筛选锚点属性,原有定位逻辑完全失效 - 锚点处理错误:10-K文档内的Item跳转链接为页内锚点,不需要二次解析锚点指向的内容片段,直接在当前DOM树中查找对应锚点即可
- 终止条件不可靠:仅通过判断Item2的父标签是否等于当前遍历标签终止遍历,会漏掉大量嵌套在其他标签内的正文内容,也容易被排版用的空白标签、换行标签打断
- 未排除目录匹配:文本匹配未过滤目录区域的Item1条目,大概率会定位到目录的Item1链接而非正文标题
调整后实现逻辑
- 统一使用BeautifulSoup处理全量HTML文档,避免多套解析逻辑混用
- 优先定位正文区域的Item1锚点,排除目录区域的锚点,兜底方案为通过目录锚点的href属性查找正文对应锚点
- 定位Item2的正文锚点作为内容终止位置
- 从Item1锚点的父元素开始遍历所有后续元素,直到遇到Item2锚点的父元素为止,收集所有中间有效元素
- 统一提取收集元素的纯文本,过滤多余空白字符和无效格式
完整可运行代码
from bs4 import BeautifulSoup import html2text import requests def extract_item1_text(html_content): soup = BeautifulSoup(html_content, 'lxml') # 定位Item1正文锚点,优先排除目录项 item1_anchor = None for a in soup.find_all('a', string=lambda s: s and s.strip().upper() in ['ITEM 1', 'ITEM 1', 'ITEM 1.']): parent = a.parent # 正文锚点父元素通常为标题类标签,内容短,后续紧跟大段正文 if parent.name in ['h1', 'h2', 'h3', 'font', 'b'] and len(parent.text.strip()) < 15: next_sib = parent.next_sibling while next_sib and str(next_sib).strip() == '': next_sib = next_sib.next_sibling if next_sib and len(next_sib.text.strip()) > 50: item1_anchor = a break # 兜底逻辑:通过目录锚点找正文锚点 if not item1_anchor: for a in soup.find_all('a', string=lambda s: s and s.strip().upper() in ['ITEM 1', 'ITEM 1', 'ITEM 1.']): if 'href' in a.attrs and a['href'].startswith('#'): item_id = a['href'].lstrip('#') item1_anchor = soup.find('a', attrs={'name': item_id}) or soup.find('a', attrs={'id': item_id}) break # 定位Item2锚点作为终止边界 item2_anchor = None for a in soup.find_all('a', string=lambda s: s and s.strip().upper() in ['ITEM 2', 'ITEM 2', 'ITEM 2.']): if 'href' in a.attrs and a['href'].startswith('#'): item_id = a['href'].lstrip('#') item2_anchor = soup.find('a', attrs={'name': item_id}) or soup.find('a', attrs={'id': item_id}) break if not item1_anchor or not item2_anchor: return '' # 收集两个锚点之间的所有有效元素 content_elements = [] current = item1_anchor.parent.next_sibling end_parent = item2_anchor.parent while current and current != end_parent: if current.name is not None: content_elements.append(current) current = current.next_sibling # 转换为纯文本并清洗 h = html2text.HTML2Text() h.ignore_links = True h.ignore_images = True h.ignore_emphasis = True full_html = ''.join([str(e) for e in content_elements]) pure_text = h.handle(full_html).strip() # 过滤多余空白行 pure_text = '\n'.join([line.strip() for line in pure_text.splitlines() if line.strip()]) return pure_text # 调用示例 if __name__ == '__main__': # SEC请求需要携带合法User-Agent,否则会返回403 headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'} # 替换为目标10-K文档的URL即可 doc_url = '替换为你的10-K文档链接' resp = requests.get(doc_url, headers=headers) item1_content = extract_item1_text(resp.text) print(item1_content)
内容的提问来源于stack exchange,提问作者Taimorr Mughal
相关产品推荐
相关产品推荐

