XPath:如何在相同级别的2个html标签之间获取文本?

时间:2019-04-30 12:18:29

标签: html python-2.7 xpath scrapy

我是的新手,并且正在与一起从生成的不同html页面获取文本。
我从用户(<h1|2|.. id="title-{id}">text</h1|2|3..>)获得标题标签的{id}。我需要从此标题和同一级别的下一个标题之间的所有html标记中获取文本。因此,如果标头是h1,则需要获取所有标签的所有文本,直到下一个h1标头。
所有标头ID具有相同的模式“ title- {id}”,其中生成{id}。
为了更加清楚,这里是一个示例:

<html>
    <body>
        ...
        <h2 id="tittle-id1">id1</h2>
        bunch of tags containing text I want to get
        <h2 id="tittle-id2">id2</h2>
        ...
    </body>
</html>

注意:我不知道它可能是什么标题。可以是从<h1><h6>的任何html标头标记


更新:
在尝试一些操作时,我注意到我不确定下一个标头是否处于同一级别甚至存在。由于标题用作标题和副标题。给定的ID可能是最后一个字幕,因此,我将在页面的最后一个甚至最后一个页面具有更高级别的标题。因此,基本上我只有标题的ID,并且需要获取“段落”的所有文本。


解决方法:
我找到了一种解决方法:
我分3个步骤完成:
首先,我使用//*[@id='title-{id}],它使我能够获得带有标记的完整行,因此现在我知道它是哪个标记头。
其次,我使用//*[id='title-{id}]/following-sibling::*,这允许查找相同或更高级别{myHeader}的下一个标头。
最后,我使用//*[id='title-{id}]/following-sibling::*//{myHeader}//preceding-sibling::*来获取两者之间的内容,或者如果找不到标题,请直到页面末尾。

3 个答案:

答案 0 :(得分:2)

这里是获取h2标签之间所有元素的xpath。

//h2/following-sibling::*[count(following-sibling::h2)=1]

这是我用来模拟场景的示例html。 (更新ID以检查下面显示的其他选项)。

  

// [@ id ='tittle-id1'] /以下:: [计数(以下同级:: [name()= name(上一个同级:: < / em> [@ id ='tittle-id1'])])= 1]

<html><head></head><body>
 
        ...
        <h2 id="tittle-id1">id1</h2>
		  <h3 id="tittle-id3"> h3 tag</h3>
		  <h4 id="tittle-id4"> h4 tag</h4>
		  <h3 id="tittle-id5"> 2nd h3  tag</h3>
        bunch of tags containing text I want to get
		   <h5 id="tittle-id6"> h5 tag </h5>
        <h2 id="tittle-id2">id2</h2>
		<h4 id="tittle-id7"> 2nd h4 tag</h4>
        ...
    
	
</body></html>

如果用户输入{id1},则

输出 enter image description here

如果用户输入{id4},则输出

enter image description here

如果用户输入{id3},则输出

enter image description here

注意:此xpath旨在适合原始发布场景。

答案 1 :(得分:1)

因为XPath中的谓词过滤了上下文节点列表,否则您将无法执行联接选择,除非您能够从源值的相对上下文中重新引入目标值。选择所有具有与特定id属性相同名称的元素的示例:

//*[name()=name(//*[@id=$generated-id-string])]

现在,对于“标记之间的问题” ,通常将Kaysian方法用于交集:

//*[name()=name(//*[@id=$generated-id-string])]/preceding-sibling::node()[
   count(.|//*[@id=$generated-id-string]/following-sibling::node())
      =
   count(//*[@id=$generated-id-string]/following-sibling::node())
]

http://www.xpathtester.com/xpath/0dcfdf59dccb8faf3705c22167ae45f1中测试

答案 2 :(得分:0)

这对我有用:
为此,请记住,我在中使用

name_query = u"//*[name()=name(//*[@id='"+id+"'])]"
all = response.xpath(name_query)
for selector in all.getall():
     if self.id in selector:
          position = all.getall().index(selector)
balise = "h" + all.getall()[position].split("<h")[1][0]
title = all.getall()[position].split(">")[1].split("<")[0]
query = u"//*[preceding-sibling::"+balise+"[1] ='"+title+"' and following-sibling::"+balise+"]"
self.log('query = '+query)
results = response.xpath(query)
results.pop(len(results)-1)
with open(filename,'wb') as f:
    for text in results.css("::text").getall():
        f.write(text.encode('utf-8')+"\n")

一般来说,这应该可以正常工作。我对多个标头进行了测试,但不同的级别对我来说都可以。