Macaca 分享 Macaca 通过 xpath 获取坐标实现滑动操作

Michael_Wang · 2016年12月19日 · 最后由 达峰的夏天 回复于 2018年03月11日 · 2202 次阅读

更新

macaca 自带了获取控件坐标的功能

element = driver.element_by_xxx(xxx)
rect = element.rect
x = rect['x']
y = rect['y']
width = rect['width']
height = rect['height']
目的

为了不在 case 当中写死坐标, 研究了一下怎样获取控件坐标, 从而通过获取到的坐标实现滑动

用到的模块:

pip install lxml
pip install beautifulsoup4
思路

webdriver 中有一个获取页面 xml 的方法: xml = driver.source 但问题是, 这个 xml 的所有节点名字都是 node, 不太容易通过简单的 xpath 去获取里面的内容. 通过 app-inspector 发现每个节点的名字和 class 是相同的. 因此想到通过 beautifulsoup 把 xml 中的 node 都用 class 的内容替换, 然后在用 lxml 模块去读取其中的 bounds 坐标属性.

代码实现
from bs4 import BeautifulSoup
from lxml import etree

def getElementBounds(xml, xpath):
    '''
    xml: 通过 driver.source 获取
    '''
    soup = BeautifulSoup(xml, 'lxml')
    while soup.node is not None:
        soup.node.name = soup.node['class'][0]

    final_xml = str(soup).replace('$', '')
    # logging.info(final_xml)
    selector = etree.XML(final_xml)
    logging.info(selector.xpath(xpath))
    element = selector.xpath(xpath)[0]
    location_str = element.attrib['bounds'] # [0,1266][1080,1641]
    location_str = location_str[1:-1].replace('][', ',') # 0,1266,1080,1641
    location_list = location_str.split(',') # ['0', '1266', '1080', '1641']
    logging.info(location_list)
    for i in xrange(len(location_list)):
        location_list[i] = int(location_list[i])
    # logging.info(location_list) # [0, 1266, 1080, 1641]
    return location_list

def move(from_xpath, to_xpath):
    xml = driver.source
    from_location = getElementBounds(xml, from_xpath)
    to_location = getElementBounds(xml, to_xpath)
    actions = {}
    actions.update({'fromX': int(from_location[2] / 2), 'fromY': from_location[1]}) # 起点控件的上边缘的中间位置
    actions.update({'toX': int(to_location[2] / 2), 'toY': to_location[3]}) # 终点控件的下边缘的中间位置
    actions.update({'steps': 50})
    driver.touch('drag', actions)
上面代码实现的是从起点控件的上边缘, 移动到终点控件的下边缘, 大家可以根据自己的情况控制起始点位置.
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 5 条回复 时间 点赞

谢谢分享。左右滑动呢?

actions.update({'fromX': int(from_location[2] / 2), 'fromY': from_location[1]}) # 起点控件的上边缘的中间位置
actions.update({'toX': int(to_location[2] / 2), 'toY': to_location[3]}) # 终点控件的下边缘的中间位置

上下左右, 四个方向的移动都可以通过这两行进行控制.

@michael_wang 你写的这个支持手机端吗?还是只针对 web 端的。

strive 回复

这个就是手机端的

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册