Web、App XPath层级定位方法
Web
假设目前我们需要定位到B站鬼畜区排行榜第二的这个元素
当然可以直接通过直接在开发者工具里直接右键copy xpath获取xpath地址,为了搞懂层级定位方法,接下来开始进行一步步地定位。
目标元素处于id="bili_kichiku"
鬼畜区的这一节点下,那么第一步便是定位到鬼畜区,//*[@id="bili_kichiku"]
(通过下一层级的id="bili_report_kichiku"也可以进行定位,此处以id="bili_kichiku"为例)
<div id="bili_kichiku">
的下一层级只有一个<div>
元素,路径可直接写为//*[@id="bili_kichiku"]/div
,
写//*[@id="bili_kichiku"]/div[1]
也没有问题,此处注意XPath列表的第一个索引为1,而不是0。
再下一层有两个元素,同样可直接通过索引的方式定位,子元素的索引可能发生改变,更可靠的方式是通过子元素的属性来定位。
鬼畜区排行榜的路径可写为//*[@id="bili_kichiku"]/div/div[@class="rank-list"]
因为目标是定位排行榜第二的元素,所以直接通过定位索引为2的子元素即可找到。
有一个更花里胡哨的方法,通过排行榜中视频的BV号来定位,不过使用此方法的前提条件是已经知道排行榜中视频的BV号,所以此处仅作方法引导。
//*[contains(@href, "BV1h64y1Z7dc")]
使用contains方法可通过属性包含的字符定位到元素。因为//
的定位不考虑元素的位置,所以可直接使用该路径查找到符合属性的元素,不需要先定位到鬼畜区排行榜节点。
App
App的Xpath定位方法与Web基本一致,属性与节点的命名方式会有所不同。
Web与App元素定位中一个明显的区别是,Web中已加载完成的位于同一页面的元素,即使没有显示在浏览器页面中,也可以定位到,而App不行。
依旧以B站鬼畜区为例,直接通过以下代码是无法定位到该元素的,因为刚进入网页时鬼畜区没有被加载。
def test_kichiku():
driver.get("https://www.bilibili.com/")
# 鬼畜区排行第二元素
driver.find_element_by_xpath('//*[@id="bili_kichiku"]/div/div[@class="rank-list"]/div[2]')
下方代码使得页面先将鬼畜区元素加载完成,然后跳转至页面顶部(此时浏览器页面中未显示鬼畜区,但鬼畜区元素已被加载),仍可定位到鬼畜区元素。
def test_kichiku():
driver.get("https://www.bilibili.com/")
# 通过导航栏跳转到首页鬼畜区
driver.find_element_by_xpath('//*[@id="elevator"]/div[2]/div[1]/div[14]').click()
# 存储鬼畜区排行第二元素
kichiku_rank2 = self.driver.find_element_by_xpath('//*[@id="bili_kichiku"]/div/div[2]/div[2]/a')
# 通过导航栏跳转到首页顶部
driver.find_element_by_xpath('//*[@class="item back-top"]').click()
# 点击鬼畜区排行第二元素
kichiku_rank2.click()
而App则有所不同,以下以Appium为例
def test_app():
# 下滑到页面直至鬼畜区可见,将元素存为element变量
driver.find_element(MobileBy.ANDROID_UIAUTOMATOR, 'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("鬼畜").instance(0));')
element = driver.find_element_by_xpath('//*[@text="鬼畜"]')
# action = TouchAction(self.driver)
# width = self.driver.get_window_rect()['width']
# height = self.driver.get_window_rect()['height']
# 上滑页面,使鬼畜不可见
action.press(x=width / 2, y=height * 0.2).wait(200).move_to(x=width / 2, y=height * 0.8).release().perform()
# 点击定位到的元素
element.click()
此方法会在执行element.click()这一步报错,报错信息“The element 'By.xpath: //*[@text="鬼畜"]' does not exist in DOM anymore”。证明在App端,即使元素已经被加载过,仍需要在当前页面可见才能被点击。