如何抓取指定h4标签间的网页内容?Scrapy CSS选择器问题求助
解决Scrapy抓取指定H4标签间内容的问题
原选择器的问题分析
你用的#apPage > div > div.monograph_cont > h4:nth-child(5) ~ *:not(h4)::text存在两个核心问题:
- 依赖DOM位置不可靠:
h4:nth-child(5)靠节点位置定位目标标题,一旦页面结构更新(比如新增/删除元素),选择器直接失效。 - 范围失控+文本提取不全:
~ *: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
相关产品推荐
相关产品推荐

