如何基于CEO_PAY_RATIO标签提取至指定hr标签间的HTML内容?
解决BeautifulSoup提取嵌套标签区间内容的问题
我需要提取HTML中从name属性为CEO_PAY_RATIO的<a>标签起始,到style包含width:100%的<hr>标签结束区间内的内容。但现有两段基于BeautifulSoup的Python代码,在<a>标签嵌套在<p>等标签内时,仅能提取到“CEO PAY RATIO”,无法获取后续的目标内容,求解决方法。
初始提取函数
def extract_content(soup, name): tag = soup.find('a', {'name': name}) all_breaks = soup.select('hr[style*="width:100%"]') content = "" if tag: current_tag = tag.find_next() print(len(all_breaks)) while current_tag and not (current_tag.name == 'hr' and current_tag in all_breaks): content += current_tag.get_text().strip() + " " current_tag = current_tag.find_next() return content.strip()
测试代码
soup = BeautifulSoup(html_text, "html.parser") # 预处理文档(移除<font>标签) for font in soup.select("font"): font.unwrap() soup.smooth() # 查找目标标签 tag = soup.find('a', {'name':"CEO_PAY_RATIO"}) text = [] while tag := tag.next_sibling: if tag.name == "hr" and "width:100%" in tag.attrs.get("style", ""): break t = tag.get_text(strip=True, separator=" ") if t: text.append(t) text = "\n".join(text) print(text)
目标HTML片段
<p style="margin-bottom:0pt;margin-top:0pt;text-indent:0%;font-weight:bold;color:#0061F0;font-size:22pt;font-family:Segoe UI;text-transform:uppercase;font-style:normal;font-variant: normal;"><a name="_AEIOULastRenderedPageBreakAEIOU209"> <a name="CEO_PAY_RATIO"></a><font style="font-weight:bold;color:#0061F0;font-size:22pt; font-family:Segoe UI;text-transform:uppercase;font-style:normal;font-variant: normal;"> <a name="CEO_PAY_RATIO"></a>CEO PAY</font><font style="font-weight:bold;color:#0061F0;font-size:22pt; font-family:Segoe UI;text-transform:uppercase;font-style:normal;font-variant: normal;"> RATIO</font></p> <some other stuff> <hr style="page-break-after:always;width:100%;"/> <some other we don't want>
问题根源
两段代码的核心缺陷:
- 初始函数用
tag.find_next()仅遍历当前标签的子节点和同级后续节点,无法跳出<p>标签获取外部内容; - 测试代码用
tag.next_sibling只遍历当前标签的同级兄弟节点,同样无法触及<p>之后的元素。
修复后的代码
from bs4 import BeautifulSoup def extract_target_content(soup): # 定位起始<a>标签(取第一个匹配项) start_tag = soup.find('a', {'name': 'CEO_PAY_RATIO'}) if not start_tag: return "" # 定位终止<hr>标签 end_tag = soup.find('hr', style=lambda s: s and 'width:100%' in s) if not end_tag: return "" content = [] current_node = start_tag while current_node: # 遇到终止标签则停止遍历 if current_node is end_tag: break # 提取元素节点的有效文本 if current_node.name: text = current_node.get_text(strip=True, separator=" ") if text: content.append(text) # 遍历文档流中的下一个节点(跨层级) current_node = current_node.next_element return "\n".join(content) # 使用示例 soup = BeautifulSoup(html_text, "html.parser") # 预处理移除font标签 for font in soup.select("font"): font.unwrap() result = extract_target_content(soup) print(result)
代码说明
- 用
next_element替代原有的遍历方法:该方法会遍历文档流中的下一个节点,不受层级限制,能跳出<p>标签获取后续内容; - 直接通过节点对象判断终止条件,避免重复查找;
- 保留文本过滤逻辑,仅收集非空有效文本。
内容的提问来源于stack exchange,提问作者ken
相关产品推荐
相关产品推荐

