You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

BeautifulSoup previous_sibling/find_previous_sibling使用异常求助

问题描述

现有一段HTML结构,部分class为text的div有对应的h5标题,部分没有。使用find_previous_sibling('h5')获取对应标题时,后两个无标题的div会拿到不属于它们的标题;使用previous_sibling并判断是否为h5元素时,没有任何返回结果。

示例HTML结构:

<div id="content">
    <h5>Title1</h5>
    <div class="text">text 1</div>

    <h5>Title2</h5>
    <div class="text">text 2</div>

    <div class="text">text 3</div>

    <div class="text">text 4</div>
</div>

测试代码:

html = BeautifulSoup(response.text,'lxml')
content = html.find('div',{'id': 'content'})
paras = content.find_all('div', {'class': 'text'})

for para in paras:
    title = p.find_previous_sibling('h5')  # 存在变量名笔误:p应为para
    if title:
        print(title.get_text())

    pr = para.previous_sibling
    if pr:
        print(pr)
问题原因
  1. find_previous_sibling('h5')的缺陷:该方法会查找当前节点之前最近的h5元素,不区分该h5是否属于当前div的专属标题。因此text3、text4会错误匹配到前面的Title2。
  2. previous_sibling的误区:HTML中的换行、空格会被BeautifulSoup解析为NavigableString类型的空白节点,直接调用previous_sibling拿到的是这些空白内容,而非目标h5元素。
正确解决方案

方案一:遍历子节点记录最近标题

通过遍历content的直接子节点,实时记录最近出现的h5标题,遇到text类div时直接关联当前记录的标题:

from bs4 import BeautifulSoup

html_content = '''
<div id="content">
    <h5>Title1</h5>
    <div class="text">text 1</div>

    <h5>Title2</h5>
    <div class="text">text 2</div>

    <div class="text">text 3</div>

    <div class="text">text 4</div>
</div>
'''

soup = BeautifulSoup(html_content, 'lxml')
content = soup.find('div', {'id': 'content'})

current_title = None
for child in content.children:
    # 跳过空白节点
    if child.name is None:
        continue
    # 更新当前记录的标题
    if child.name == 'h5':
        current_title = child.get_text(strip=True)
    # 匹配text类div并输出关联结果
    elif child.name == 'div' and 'text' in child.get('class', []):
        text_content = child.get_text(strip=True)
        print(f"标题: {current_title if current_title else '无'}, 内容: {text_content}")

输出结果:

标题: Title1, 内容: text 1
标题: Title2, 内容: text 2
标题: 无, 内容: text 3
标题: 无, 内容: text 4

方案二:循环查找有效兄弟节点

修正previous_sibling的用法,循环向前查找兄弟节点,跳过空白内容直到找到h5或无节点:

paras = content.find_all('div', {'class': 'text'})
for para in paras:
    sibling = para.previous_sibling
    title = None
    while sibling:
        if sibling.name == 'h5':
            title = sibling.get_text(strip=True)
            break
        # 跳过空白节点,继续向前查找
        sibling = sibling.previous_sibling
    print(f"标题: {title if title else '无'}, 内容: {para.get_text(strip=True)}")

该方法会精准判断当前text div是否有对应的前置h5标题,避免错误匹配。

内容的提问来源于stack exchange,提问作者jdleung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:33:27