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)
问题原因
find_previous_sibling('h5')的缺陷:该方法会查找当前节点之前最近的h5元素,不区分该h5是否属于当前div的专属标题。因此text3、text4会错误匹配到前面的Title2。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
相关产品推荐
相关产品推荐

