XPath介绍
XPath(XML Path Language)是一门解析XML文档的语言,可在XML文档中对元素和属性进行遍历。因为XML和HTML语法类似,所以,XPath广泛用于解析HTML文档数据,HTML页面由标签构成,这些标签就像家族里的族谱一样,有明确的层级关系,正是基于这种层级关系,XPath语法才能选中所需的数据,在HTML文档中XPath通过元素(即HTML标签)和属性(即HTML标签的属性)进行定位。XPath常用于Selenium自动化测试中的元素定位和数据爬虫定位,使用路径表达式来选取XML和HTML文档中的节点或节点集
XPath语法
XPath语法大致可以分为四大类:层级、属性、函数和其它
-
层级
/
后面直接跟子节点,在linux系统中很常见,如/html/body/div/div[2]/div[5]/div[1]/div/form/span[1]/input
//
全局查找,可以是任意位置,如//div//input
,双斜杠可视为相对路径,单斜杠可视为绝对路径parent
选取当前节点的父节点child
选取当前节点的所有子节点preceding
选取当前节点的开始标签之前的所有节点following
选取当前节点的结束标签之后的所有节点ancestor
选取当前节点的所有先辈节点 (父、祖父等)descendant
选取当前节点的所有后代节点 (子、孙等)descendant-or-self
选取当前节点的所有后代节点及当前节点本身.
和在linux系统中一个意思,表示当前目录,即当前节点..
同样和在linux系统中一个意思,表示上一级目录,即当前节点的父节点 -
属性
@ 属性访问,选择带有某个属性的节点,如
//input[@name]
,选取带有name属性的input标签;//input[@*]
,选取所有带属性的input标签,可以直接通过元素的id、name和class属性定位,如//input[@id="kw"]
,选取id="kw"属性的input标签;//input[@class="s_ipt"]
,选取class="s_ipt"属性的input标签,若id/name/class都没有,可以通过其它属性进行定位,但要确保此属性是不变的,不能是下次请求时属性就消失或者有变化了,如:class="xh-highlight"
,高亮属性在选中时才会出现 -
函数
text()
文本定位,常和contains()函数一起使用,//div/a[contains(text(),"学")]last()
返回被处理节点的最后一个元素,//div[@id="s-top-left"]/a[last()]position()
匹配返回节点的索引位置,//div[@id="s-top-left"]/a[position()=1]contains()
匹配一个属性值中包含的字符串,用于模糊定位,//div[contains(@id,"s-t")]/a[last()]starts-with()
匹配一个属性值开始位置的关键字,用于模糊定位,//div[starts-with(@id,"s-t")]/a[last()] -
其它
=、!=、<、>、<=、>=、or、and
运算符,一目了然,不再做解释*
通配符,匹配任意字符,如//div/*
,选取div标签下的所有标签|
与或符,双方条件都满足时都显示,否则只显示满足条件的一方,如://input|//title
[]
谓语和索引需要用[]括起来,谓语是用来查找某个特定节点或包含指定值的节点,如://input[position()<2]
,选择最前面的input标签;//div[@id="s-top-left"]/a[1]
,选择id="s-top-left"的div标签下的第一个a标签
示例
下面以百度首页为例,在百度页面按F12
打开开发工具,在开发工具页面按住Ctrl + F
,在搜索框内输入XPath语法即可定位元素,如下三种浏览器页面所示,注意输入框右侧的分数值,1/1、1of1
才表示定位到唯一的元素,1of2
表示定位到2个,目前选中的是第一个,一般情况下,使用Selenium做自动化时定位元素基本上都是要唯一,在进行数据爬虫时1of10
之类的多元素定位使用较多
以下XPath语法都可在百度页面定位到唯一值,此处不再符百度HTML文档
以下XPath语法都可定位到“百度一下”按钮
//*[@id=‘su‘] # 在HTML文档中查找所有id=‘su‘的标签
//input[@id=‘su‘] # 在HTML文档中查找id=‘su‘的input标签
//input[@type=‘submit‘] # 在HTML文档中查找type=‘submit‘的input标签
//input[@value=‘百度一下‘] # 在HTML文档中查找value=‘百度一下‘的input标签
……
以下XPath语法都可定位到百度输入框
//*[@id=‘kw‘] # 在HTML文档中查找所有id=‘kw‘的标签
//input[@type=‘text‘] # 在HTML文档中查找type=‘text‘的input标签
//input[@class=‘s_ipt‘] # 在HTML文档中查找class=‘s_ipt‘的input标签
//input[@name=‘wd‘] # 在HTML文档中查找name=‘wd‘的input标签
//input[@id=‘kw‘] # 在HTML文档中查找id=‘kw‘的input标签
//input[starts-with(@class,‘s‘)] # 在HTML文档中查找class属性值包含“s”的input标签
……
以下XPath语法都可定位到百度首页左上角“学术”链接按钮
//*[@id=‘s-top-left‘]/a[7] # 在HTML文档中查找所有id=‘s-top-left‘的标签下的第7个a标签
//div[@id=‘s-top-left‘]/a[7] # 在HTML文档中查找id=‘s-top-left‘的div标签下的第7个a标签
//div[@id=‘s-top-left‘]/a[position()=7] # 在HTML文档中查找id=‘s-top-left‘的div标签下的索引值等于7的a标签
//div[@id=‘s-top-left‘]/a[position()>6] # 在HTML文档中查找id=‘s-top-left‘的div标签下的索引值大于6的a标签
//div[@id=‘s-top-left‘]/a[last()] # 在HTML文档中查找id=‘s-top-left‘的div标签下的最后一个a标签
//div[@id=‘s-top-left‘]/a[1]/@href # 获取页面中“新闻”的链接地址
//a[contains(text(),‘学‘)] # 在HTML文档中查找文本信息包含“学”的a标签
……
以下XPath语法都可定位到百度首页左上角“新闻”链接按钮
//*[@id=‘s-top-left‘]/a[1] # 在HTML文档中查找所有id=‘s-top-left‘的标签下的第1个a标签
//div[@id=‘s-top-left‘]/child::a[1] # 在HTML文档中查找id=‘s-top-left‘的div标签下子标签的第1个a标签
//div[@id=‘s-top-left‘]/descendant::a[1] # 在HTML文档中查找id=‘s-top-left‘的div标签后代中的第1个a标签
//div[@id=‘s_top_wrap‘]/following::a[1] # 在HTML文档中查找id=‘s_top_wrap‘的div标签后的第1个a标签
//div[@class=‘mnav s-top-more-btn‘]/preceding::a[7] # 查找class=‘mnav s-top-more-btn‘的div标签之前的第7个a标签
//a[contains(text(),‘h‘)]/parent::*/a[position()=1] # 查找包含h的文本的a标签的父标签下索引值为1的a标签
//a[contains(text(),‘h‘)]/ancestor::*/a[position()<2] # 查找包含h的文本的a标签的先辈标签下索引值小于2的a标签
……
对于如下图所示的情况,所需信息并没有在标签对中
可以使用下面的语法进行定位
//span[@class=‘pl‘][3]/following::text()[1] # 获取class=‘pl‘的第三个span标签后的第1个文本内容
//span[./text()=‘语言:‘]/following::text()[1] # 获取当前节点包含文本“语言:”的span标签后的第1个文本内容
还可以下载个Xpath Helper插件,如下图,//p[@class=‘lh‘][position()<5]/a
得到4个结果并在页面高亮显示
以上只是学习XPath语法,了解XPath定位的一种方式
最为简单的方法还是选择元素后右键选择复制XPath,只是对于复杂页面复制出的语法可读性不太好
之后就可以在代码中使用啦,代码中注意引号的使用,内外不能同时使用单引或双引号
find_element_by_xpath("//input[@id=‘kw‘]").clear()
find_element_by_xpath(‘//*[@id="kw"]‘).send_keys("XPath")
find_element_by_xpath(‘//*[@id="su"]‘).click()
find_element(By.XPATH, ‘//a[@class="toindex"]‘).click()