如何使用XPath获取每组结构中首个仅含单个class的span元素文本?
price类的<span>元素 看起来你是想从每组容器里挑出那个只有price这一个class的<span>,而不是同时带其他类的那个。原XPath会把每组里的两个<span>都抓回来,确实没法精准过滤,给你几个实用的解决方案:
方案1:精确匹配class属性值(最推荐)
直接匹配class属性的完整值为"price",因为你要的目标元素class属性就只有这一个值,而另一个是"price red",完全不匹配:
//div/span[@class="price"]
如果你的实际结构是在span[@class="a-price"]下面(对应你原代码里的路径),就调整成:
//span[@class="a-price"]/span[@class="price"]
方案2:处理可能的空格问题
如果担心目标元素的class属性前后有多余空格(比如写的时候不小心加了空格),可以用normalize-space先清理再匹配:
//div/span[normalize-space(@class)="price"]
这个会把属性值里的首尾空格去掉,中间的多个空格换成单个,再和"price"对比,容错性更强一点。
方案3:结合位置过滤(确保是每组第一个)
如果你还需要确保选中的是每个容器下的第一个<span>,同时符合class条件,可以这么写:
//div/span[1][@class="price"]
它会先选出每个容器下的第一个<span>,再过滤出class为price的元素,刚好对应你要的目标。
方案4:排除带其他类的元素(应急用)
如果遇到特殊场景,需要排除带有特定额外类的元素(比如这里的red),可以用反向匹配:
//div/span[contains(@class,"price") and not(contains(@class,"red"))]
不过这个方案不如前几个精准,要是以后出现price-blue这类class的元素,也会被选中,所以优先用前面的精确匹配方案。
为什么原XPath不行?
你原来的//span[@class="a-price"]/span只是选中了所有a-price容器下的<span>,没有做任何class过滤,所以会把两个元素都抓回来。上面的方案都是通过精准匹配class属性,帮你筛选出唯一符合要求的那个。
内容的提问来源于stack exchange,提问作者Melissa Bean

