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

如何抓取指定h4标签间的网页内容?Scrapy CSS选择器问题求助

解决Scrapy抓取指定H4标签间内容的问题

原选择器的问题分析

你用的#apPage > div > div.monograph_cont > h4:nth-child(5) ~ *:not(h4)::text存在两个核心问题:

  1. 依赖DOM位置不可靠:h4:nth-child(5)靠节点位置定位目标标题,一旦页面结构更新(比如新增/删除元素),选择器直接失效。
  2. 范围失控+文本提取不全:~ *:not(h4)会匹配目标h4之后所有非h4元素(直到页面末尾),所以会混入后续无关内容;同时直接用::text只会提取当前元素的文本,无法获取<li>等子元素里的内容。

方案1:用XPath精准截取(推荐)

XPath在范围选择上比CSS更灵活,通过文本匹配目标h4,再精准选取两者之间的所有元素:

# 定位两个目标H4节点(用文本匹配,不依赖位置)
side_effects_h4 = response.xpath('//h4[text()="What Are Side Effects of Abilify?"]')
dosage_h4 = response.xpath('//h4[text()="Dosage for Abilify"]')

# 选取两个H4之间的所有元素:第一个H4之后,第二个H4之前的所有兄弟节点
target_elements = side_effects_h4.xpath('following-sibling::*[count(preceding-sibling::h4[text()="What Are Side Effects of Abilify?"]) = 1 and count(preceding-sibling::h4[text()="Dosage for Abilify"]) = 0]')

# 提取所有文本(包括<li>等子元素内的内容),并清理空白字符
all_text = target_elements.xpath('.//text()').getall()
cleaned_text = [text.strip() for text in all_text if text.strip()]

这段代码的优势:

  • 用文本匹配标题,不受页面结构变动影响
  • 精准限定范围,只抓取两个h4之间的内容
  • .//text()会递归获取所有子元素的文本,不会遗漏<li>里的内容

方案2:改进CSS选择器(适合坚持用CSS的场景)

CSS没有原生的范围截断能力,但可以结合:contains()和相邻兄弟选择器缩小范围:

# 先获取目标H4之后、直到下一个目标H4之前的所有元素
target_elems = response.css('#apPage > div > div.monograph_cont h4:contains("What Are Side Effects of Abilify?") ~ *:not(h4:contains("Dosage for Abilify"))')

# 遍历每个元素,提取其所有子节点的文本
all_text = []
for elem in target_elems:
    # 用空格分隔的` ::text`获取当前元素下所有子节点的文本
    elem_text = elem.css(' ::text').getall()
    cleaned = [t.strip() for t in elem_text if t.strip()]
    all_text.extend(cleaned)

注意:CSS的:contains()对文本匹配是模糊的,如果页面有其他h4包含相同片段文本可能出错,稳定性不如XPath方案。


关键要点总结

  • 避免用nth-child这类依赖DOM位置的选择器,优先用文本/属性匹配目标节点
  • 提取包含子元素的文本时,要使用递归选择(XPath的.//text()或CSS的 ::text)
  • 截取两个节点之间的内容,XPath的兄弟节点计数是最可靠的方式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 08:47:45