如何使用单个XPath查询选择节点集?

如何使用单个XPath查询选择节点集?,xpath,Xpath,我正试图从我最喜欢的航空公司提取旅程和价格信息 我的搜索结果页面如下所示: 编辑:图像主机可能已阻止热链接。请参见本页上的图像: 我可以使用此XPath选择器选择表示航班的每一行: //*[@class="servicecode "]/ancestor::tr[1] //*[contains(@class, "datarow")][.//input] //*[contains(@class, "datarow")][.//input] 但每一排航班都不是一次独立的旅程;这些航班实际上被

我正试图从我最喜欢的航空公司提取旅程和价格信息

我的搜索结果页面如下所示:

编辑:图像主机可能已阻止热链接。请参见本页上的图像:

我可以使用此XPath选择器选择表示航班的每一行:

//*[@class="servicecode "]/ancestor::tr[1]
//*[contains(@class, "datarow")][.//input]
//*[contains(@class, "datarow")][.//input]
但每一排航班都不是一次独立的旅程;这些航班实际上被分成了几段,这就是我想要选择的

row类为每个新分支交替使用:第一分支的行具有类“datarow”,下一分支的行具有“datarow alt”。在Python中,我可以使用
itertools.groupby
对上面表达式选择的节点进行分组,但是如果有一种方法可以完全在XPath中实现这一点,我更喜欢它

这个问题的扩展:我的选择器选择所有行,无论航班是否售罄。我可以使用此选择器选择每个可预订旅程的第一个航班:

//*[@class="servicecode "]/ancestor::tr[1]
//*[contains(@class, "datarow")][.//input]
//*[contains(@class, "datarow")][.//input]
但是,如果分支有多个航班,那么我将不得不使用另一个XPath查询查找具有相同类的以下兄弟

是否有一个XPath查询将每个可预订的分支作为节点集返回给我

注意:我使用的是Python lxml库,以防万一

使用

//tr[@class='datarow'][.//*[@class='servicecode']]
  (//tr[@class='datarow'])[1]//input 
| 
  (//tr[@class='datarow'])[1]
         //following-sibling::tr[@class='datarow altrow']
                   [count(preceding-sibling::tr[@class='datarow'])=1]
                         //input
这个问题的延伸:我的 选择器选择所有行,无论 航班是否售完。我可以 选择每个航班的第一个航班 使用此选择器可预订旅程:

//*[@class="servicecode "]/ancestor::tr[1]
//*[contains(@class, "datarow")][.//input]
//*[contains(@class, "datarow")][.//input]
但是如果腿不止一个 航班,那我就得找了 跟随同一类的兄弟姐妹 使用另一个XPath查询

是否有一个XPath查询 将每个可预订的支腿作为 诺德塞特

//tr[@class='datarow'][.//*[@class='servicecode']]
  (//tr[@class='datarow'])[1]//input 
| 
  (//tr[@class='datarow'])[1]
         //following-sibling::tr[@class='datarow altrow']
                   [count(preceding-sibling::tr[@class='datarow'])=1]
                         //input
此XPath表达式选择表示第一次旅程的每个可预订段(在本例中为3段)的所有
tr
元素

要获取第二次行程的所有行程,请将上述表达式中的
1
替换为
2

要获得第k次行程的所有航段,请将上述表达式中的
1
替换为
k
的实际值

使用

//tr[@class='datarow'][.//*[@class='servicecode']]
  (//tr[@class='datarow'])[1]//input 
| 
  (//tr[@class='datarow'])[1]
         //following-sibling::tr[@class='datarow altrow']
                   [count(preceding-sibling::tr[@class='datarow'])=1]
                         //input
这个问题的延伸:我的 选择器选择所有行,无论 航班是否售完。我可以 选择每个航班的第一个航班 使用此选择器可预订旅程:

//*[@class="servicecode "]/ancestor::tr[1]
//*[contains(@class, "datarow")][.//input]
//*[contains(@class, "datarow")][.//input]
但是如果腿不止一个 航班,那我就得找了 跟随同一类的兄弟姐妹 使用另一个XPath查询

是否有一个XPath查询 将每个可预订的支腿作为 诺德塞特

//tr[@class='datarow'][.//*[@class='servicecode']]
  (//tr[@class='datarow'])[1]//input 
| 
  (//tr[@class='datarow'])[1]
         //following-sibling::tr[@class='datarow altrow']
                   [count(preceding-sibling::tr[@class='datarow'])=1]
                         //input
此XPath表达式选择表示第一次旅程的每个可预订段(在本例中为3段)的所有
tr
元素

要获取第二次行程的所有行程,请将上述表达式中的
1
替换为
2


要获得第k次行程的所有航段,请将上述表达式中的
1
替换为
k
的实际值

这正是我想要的。但是有更优雅的解决方案吗

//*[contains(@class, "columns")]//tr[contains(@class, "datarow")][1]
|
//*[contains(@class, "columns")]//tr[not(contains(@class, "altrow"))]
       [preceding-sibling::tr[1]
           [contains(@class, "altrow")]]
|
//*[contains(@class, "columns")]//tr[contains(@class,"altrow")]
       [preceding-sibling::tr[1]
           [not(contains(@class, "altrow"))]]
第二部分选择类不包含“altrow”的每组连续行作为单个节点集

第三部分选择包含“altrow”类的每组连续行作为单个节点集


第一部分选择类不包含“altrow”的第一组连续行,因为第二部分没有选择它。

这就是我想要的。但是有更优雅的解决方案吗

//*[contains(@class, "columns")]//tr[contains(@class, "datarow")][1]
|
//*[contains(@class, "columns")]//tr[not(contains(@class, "altrow"))]
       [preceding-sibling::tr[1]
           [contains(@class, "altrow")]]
|
//*[contains(@class, "columns")]//tr[contains(@class,"altrow")]
       [preceding-sibling::tr[1]
           [not(contains(@class, "altrow"))]]
第二部分选择类不包含“altrow”的每组连续行作为单个节点集

第三部分选择包含“altrow”类的每组连续行作为单个节点集


第一部分选择类不包含“altrow”的第一组连续行,因为第二部分没有选择它。

好问题,+1。请参阅我的答案,了解您两个问题的解决方案。:)好问题,+1。请参阅我的答案,了解您两个问题的解决方案。:)谢谢你的回复,迪米特!恐怕我为第二个示例提供了错误的XPath选择器(我从第一个示例复制了相同的选择器)。我现在编辑了这个;你能更新你的答案吗?谢谢,也很抱歉给你带来困惑。+1让你很快理解这个问题:在兄弟姐妹之间分组选择。对不起,迪米特,我想你可能误解了我。也许我没有解释清楚。但根据你的回答,我拼凑出了一些有用的东西;请看我的答案。我不明白它为什么会起作用,我也不知道这是否是获得我想要的结果的最佳方式。@isme:添加新信息作为你自己问题的答案是不好的。想想为什么你需要两次来解释越来越多的问题——这意味着你不能很好地定义你的问题。因此,不要急于再次修改问题。也许现在你了解了你最初的问题及其解决方案,但一个新的问题已经解决了。在这种情况下,将新问题作为新问题提问。最后,根据SO的good ettiquette,如果一个答案对找到解决方案有重大贡献,你应该接受这个答案,并对其进行投票。谢谢你的回复,Dimitre!恐怕我为第二个示例提供了错误的XPath选择器(我从第一个示例复制了相同的选择器)。我现在编辑了这个;你能更新你的答案吗?谢谢,也很抱歉给你带来困惑。+1让你很快理解这个问题:在兄弟姐妹之间分组选择。对不起,迪米特,我想你可能误解了我。也许我没有解释清楚。但根据你的回答,我拼凑出了一些有用的东西;请看我的答案。我不明白它为什么会起作用,我也不知道这是否是获得我想要的结果的最佳方式。@isme:添加新信息作为你自己问题的答案是不好的。想想为什么哟