我是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::*
来获取两者之间的内容,或者如果找不到标题,请直到页面末尾。
答案 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},则 如果用户输入{id4},则输出 如果用户输入{id3},则输出
注意:此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)
这对我有用:
为此,请记住,我在scrapy中使用python-2.7:
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")
一般来说,这应该可以正常工作。我对多个标头进行了测试,但不同的级别对我来说都可以。