Python 如何选择所有子文本,但不包括带有Scapy XPath的标记?

Python 如何选择所有子文本,但不包括带有Scapy XPath的标记?,python,html,xpath,scrapy,Python,Html,Xpath,Scrapy,我有这个html: <div id="content"> <h1>Title 1</h1><br><br> <h2>Sub-Title 1</h2> <br><br> Description 1.<br><br>Description 2. <br><br> <h2>Sub-Ti

我有这个html:

<div id="content">
    <h1>Title 1</h1><br><br>

    <h2>Sub-Title 1</h2>
    <br><br>
    Description 1.<br><br>Description 2.
    <br><br>

    <h2>Sub-Title 2</h2>
    <br><br>
    Description 1<br>Description 2<br>
    <br><br>

    <div class="infobox">
        <font style="color:#000000"><b>Information Title</b></font>
        <br><br>Long Information Text
    </div>
</div>
但是我还没有到达排除部分,我仍然在努力从文章中抓取文本

我试过这个:

response.xpath('//*[@id="content"]/text()').extract()
但它只返回描述1。和说明2。从两个子标题

然后我试着:

response.xpath('//*[@id="content"]//*/text()').extract()
它只返回标题1、子标题1、子标题2、信息标题和长信息文本

这里有两个问题:

如何从content div获取所有儿童文本? 如何从选择中排除infobox div? 使用substant::axis查找子体文本节点,并明确声明这些文本节点的父节点不能是div[@class='infobox']元素

将上述内容转换为XPath表达式:

//div[@id = 'content']/descendant::text()[not(parent::div/@class='infobox')]
然后,结果与我使用在线XPath工具测试的结果类似,如下所示。如您所见,div[@class='infobox']的文本内容不再显示在结果中

-----------------------
Title 1
-----------------------
-----------------------
Sub-Title 1
-----------------------
-----------------------
Description 1.
-----------------------
Description 2.
-----------------------
-----------------------
Sub-Title 2
-----------------------
-----------------------
Description 1
-----------------------
Description 2
-----------------------
-----------------------
-----------------------
你的方法有什么问题

您的第一次尝试:

//*[@id="content"]/text()
简单地说,是指:

查找文档中任何不一定是div的元素,该元素具有属性@id,其值为content。对于此元素,返回其所有直接子文本节点

问题:您正在丢失不是外部div的直接子级的文本节点,因为它们位于该div的子元素内

您的第二次尝试:

//*[@id="content"]//*/text()
翻译为:

查找文档中任何不一定是div的元素,该元素具有属性@id,其值为content。对于该元素,查找任何子元素节点并返回该子元素的所有文本节点

问题:您正在丢失div的直接子文本节点,因为您只查看作为div的后代元素的子元素的文本节点

编辑:

回应你的评论:

//div[@id = 'content']/descendant::text()[not(ancestor::div/@class='infobox')]

对于您将来的问题,请确保您显示的HTML能够代表您的实际问题。

您好,谢谢您的回答。但是,如果infobox div包含另一个子元素,则排除解决方案不起作用,请参阅上面我编辑的html示例。@suud我已经编辑了我的答案。如果使用祖先::而不是父::,则表达式将忽略信息框中的任何文本,无论它是否位于另一个元素中。谢谢,这解决了我的问题。我需要的是//div[@class=body]/genderant::text[notancestor::script]举个例子问:在genderant之前放两个斜杠而不是一个斜杠有区别吗?@ilius这两个斜杠//是genderant或self::axis的缩写。如果您的意思是//div[@id='content']//genderant::text[notancestor::div/@class='infobox'],则不会有什么区别,但//or genderant::是多余的。
//div[@id = 'content']/descendant::text()[not(ancestor::div/@class='infobox')]