self::div 是 XPath 里的 轴语法,意思是:
当前节点自己是不是 div 标签
比如这个 XPath:
//*[self::div and contains(@class, 'title')]
可以拆开理解:
//*
先找页面上所有元素。
[self::div and contains(@class, 'title')]
然后筛选:当前这个元素本身必须是 div,并且 class 包含 title。
所以它基本等价于:
//div[contains(@class, 'title')]
你看到的这段:
//*[self::div and (contains(@class, 'title') or contains(@class, 'desc_block'))]
意思是:
找所有元素里,当前元素本身是 div,并且 class 包含 title 或 desc_block 的元素
等价于更普通的写法:
//div[contains(@class, 'title') or contains(@class, 'desc_block')]
那为什么有时候用 self::div?
主要是为了方便兼容多个标签类型。比如你不确定弹框文案是在 div、span、p 哪个标签里,可以写:
//*[self::div or self::span or self::p]
意思是:
当前元素可以是 div,也可以是 span,也可以是 p
例如:
//*[self::div or self::span or self::p]
[contains(translate(normalize-space(.), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'your verification')]
[contains(translate(normalize-space(.), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'under review')]
如果你这里只想匹配 div,可以不用 self::div,直接写:
String xpath =
"//div[(contains(@class, 'title') or contains(@class, 'desc_block')) "
+ "and contains(translate(normalize-space(.), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'your verification') "
+ "and contains(translate(normalize-space(.), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'under review')]";
这个更直观。
如果你想更通用,兼容 div/span/p,就用 self:::
String xpath =
"//*[(self::div or self::span or self::p) "
+ "and (contains(@class, 'title') or contains(@class, 'desc_block')) "
+ "and contains(translate(normalize-space(.), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'your verification') "
+ "and contains(translate(normalize-space(.), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'under review')]";
简单记:
self::div
就是:
当前节点自己是 div
self::span
就是:
当前节点自己是 span
self::div or self::span
就是:
当前节点可以是 div 或 span
你这个场景,如果 DOM 里确定就是 div,直接用 //div[...] 就行;如果前端标签可能变,用 //*[self::div or self::span or self::p ...] 更稳。