Scrapy如何提取元素直接子文本节点 排除子元素内文本(CSS/XPath)
问题原因
你之前使用的CSS选择器逻辑存在两个问题:
.classA:not(.classD)是筛选自身不包含classD类名的classA元素,和「排除子元素内文本」的需求没有关联*::text只会选中目标元素下所有后代标签内的文本节点,本身就不会抓取直接挂载在父元素下、不属于任何子标签的直属文本,自然拿不到你需要的内容。
推荐方案:XPath 一步实现(稳定性最高)
XPath原生支持直接筛选元素的直属文本节点,不会递归进入子元素抓取内容,写法非常简洁:
# 定位目标div,仅取它的直接子文本节点 raw_text = response.xpath('//div[contains(@class, "classA")]/text()').getall() # 过滤掉换行、缩进产生的空白文本 target_text = [t.strip() for t in raw_text if t.strip()]
运行后target_text就是你需要的["Text I want to grab.", "More text I want to grab"]。
如果需要更精准匹配同时携带classA classB classC三个类名的div,避免误匹配其他带classA的节点,可以把XPath写得更严格:
raw_text = response.xpath('//div[contains(@class, "classA") and contains(@class, "classB") and contains(@class, "classC")]/text()').getall() target_text = [t.strip() for t in raw_text if t.strip()]
备选方案:CSS选择器配合节点遍历
CSS选择器本身没有提供选取直属文本节点的语法,无法一步拿到结果,需要先定位父节点再遍历子节点筛选:
# 先定位到目标父元素 parent = response.css('.classA.classB.classC')[0] target_text = [] # 遍历父元素的直接子节点 for child in parent.root.iterchildren(): # 跳过所有标签类型的子节点,只保留文本节点 if child.__class__.__name__ == '_Element': continue content = str(child).strip() if content: target_text.append(content)
最终得到的结果和XPath方案完全一致。
内容的提问来源于stack exchange,提问作者Vishnubly
相关产品推荐
相关产品推荐

