目录

1.引入对象:TouchAction:触摸

A. 点击(轻敲)操作:

B. 多次滑屏:

C.长按

2.MultiAction ----- 多点触控 放大缩小操作

2.1 根据解析手势操作放大缩小

2.2 放大/缩小操作另一个方法:zoom/pinch

3.滑屏操作:

A. driver.swipe(x1, y1, x2, y2,duration)

B.driver.scroll

C. driver.drag_and_drop

**总结上述三种方法:


1.引入对象:TouchAction:触摸

from appium.webdriver.common.touch_action import TouchAction

TouchAction(driver)
- TouchAction对象包含(tab)、press(短按)、move_to(滑动到某个坐标)等方法
- 通过TouchAction对象,添加tap、move_to等操作,然后perform()执行,可以实现解锁屏幕等功能
规范中的可用事件有:

短按 (press)、释放 (release)、移动到 (moveTo)、点击 (tap)、等待 (wait)、
长按 (longPress)、取消 (cancel)、执行 (perform)

A. 点击(轻敲)操作

driver.tap(坐标x,坐标y, 持续点击时间/s) — 坐标定位建议少用 不到万不得已
除了定位到元素的点击外,也可以通过定位表达式实现坐标的点击

第一种:
TouchAction(driver).tap(x=155, y=706, count=1).perform()
第二种:
TouchAction(driver).tap(ele, count=1).perform()

B. 多次滑屏

建议少用坐标定位 下面只是举例子

from appium.webdriver.common.touch_action import TouchAction
# 短按之后要释放 长按之后也是需要释放的。
action=TouchAction(driver)
action.press(x=220,y=700).move_to(x=840, y=700).move_to(x=220, y=1530).move_to(x=840, y=1530).release().perform()

举例:解锁微信服务里面九宫格

import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.common.touch_action import TouchAction

desired_caps = {
    'platformName': 'Android',
    'platformVersion': '8.1',
    'deviceName': 'ye_shen_Android',
    'appPackage': 'com.tencent.mm',
    'appActivity': 'com.tencent.mm.ui.LauncherUI',
    'noReset': True,
    'autoAcceptAlerts': True,
    'newCommandTimeout': 240
}

driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
driver.implicitly_wait(10)

# 点击 微信 我的
loc = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().resourceId("com.tencent.mm:id/j5t")')
WebDriverWait(driver, 30).until(EC.visibility_of_element_located(loc))
TouchAction(driver).tap(x=540, y=1255).wait(200).perform()

# 点击 服务
locc = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("服务")')
WebDriverWait(driver, 30).until(EC.visibility_of_element_located(locc))
ele = driver.find_element(MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("服务")')
TouchAction(driver).tap(ele).wait(200).perform()

# 检查 请输入手势密码
loccs = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("请输入手势密码")')
WebDriverWait(driver, 30).until(EC.visibility_of_element_located(loccs))

# 获取起始坐标-九宫格左上顶点
loc = driver.find_element(MobileBy.ID, "com.tencent.mm:id/hrs").location
print(loc)
# 获取九宫格元素大小 height width 宽 和 高
loc_size = driver.find_element(MobileBy.ID, "com.tencent.mm:id/hrs").size
print(loc_size)

# 获取分割后的均值,即下面要用到的九宫格的步长
step = loc_size["width"] / 6
step_x = loc_size["width"] / 6
step_y = loc_size["height"] / 6

# 计算出每个点的坐标
point1 = (loc["x"] + step, loc["y"] + step * 5)
point2 = (point1[0], point1[1] - step * 2)
point3 = (point2[0], point2[1] - step * 2)
point4 = (point3[0] + step * 2, point3[1] + step * 2)
point5 = (point4[0] + step * 2, point4[1] + step * 2)
point6 = (point5[0], point5[1] - step * 2)
point7 = (point6[0], point6[1] - step * 2)


# 进行滑动操作
TouchAction(driver).press(x=point1[0], y=point1[1]).wait(500). \
    move_to(x=point2[0], y=point2[1]). \
    move_to(x=point3[0], y=point3[1]). \
    move_to(x=point4[0], y=point4[1]). \
    move_to(x=point5[0], y=point5[1]). \
    move_to(x=point6[0], y=point6[1]). \
    move_to(x=point7[0], y=point7[1]). \
    release().perform()

time.sleep(10)
driver.quit()

如图:

C.长按

例如:一个长按的例子:建议少用坐标定位 下面只是举例子

import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from appium.webdriver.webdriver import By

des = {
"platformName": "Android",
"platformVersion": "9",
"deviceName": "windwos虚拟机",
"appPackage": "com.android.settings",
"appActivity": "com.android.settings.Settings",
"udid": "192.168.0.101:5555",
"noReset": "True"
}

driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', des)
driver.implicitly_wait(10)


touch = TouchAction(driver)
#touch.press(x=720, y=1910).perform()
touch.long_press(x=720, y=1910).perform()

2.MultiAction ----- 多点触控 放大缩小操作

借鉴文章戳这里
背景:使用地图App、图片放大缩小场景中,我们经常需要对界面进行缩放操作来更加便利的查看位置或者图片放大操作。

2.1 根据解析手势操作放大缩小

  • (1)在 Appium 里面提供了 MultiAction 类来进行放大、缩小操作。模拟真实手指操作,如图:

  •  (2)MultiAction 是多点触控的类,可以模拟用户多点操作。主要包含 add() 和 perform() 两个方法, MultiAction可以结合前面所学的 ActionTouch可以模拟出用户的多个手指滑动的操作效果。

from appium.webdriver.common.multi_action import MultiAction
from appium.webdriver.common.touch_action import TouchAction

add 方法:touch_actions 就是 一个或多个TouchAction对象,描述一个手指要执行的动作

 def add(self, *touch_actions: 'TouchAction') -> None:
        """Add TouchAction objects to the MultiAction, to be performed later.

        Args:
            touch_actions: one or more TouchAction objects describing a chain of actions to be performed by one finger

        Usage:
            | a1 = TouchAction(driver)
            | a1.press(el1).move_to(el2).release()
            | a2 = TouchAction(driver)
            | a2.press(el2).move_to(el1).release()
            | MultiAction(driver).add(a1, a2)

        Returns:
            `MultiAction`: Self instance
        """
        for touch_action in touch_actions:
            if self._touch_actions is None:
                self._touch_actions = []

            self._touch_actions.append(copy.copy(touch_action))

perform 方法

 def perform(self: T) -> T:
        """Perform the actions stored in the object.

        Usage:
            | a1 = TouchAction(driver)
            | a1.press(el1).move_to(el2).release()
            | a2 = TouchAction(driver)
            | a2.press(el2).move_to(el1).release()
            | MultiAction(driver).add(a1, a2).perform()

        Returns:
            `MultiAction`: Self instance
        """
        self._driver.execute(Command.MULTI_ACTION, self.json_wire_gestures)

        # clean up and be ready for the next batch
        self._touch_actions = []

        return self

用法:

from appium.webdriver.common.multi_action import MultiAction
from appium.webdriver.common.touch_action import TouchAction

a1 = TouchAction(driver)
a1.press(el1).move_to(el2).release()

a2 = TouchAction(driver)
a2.press(el2).move_to(el1).release()

MultiAction(driver).add(a1, a2).perform()

代码实战:放大缩小微信中的地图

import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.common.touch_action import TouchAction
from appium.webdriver.common.multi_action import MultiAction


desired_caps = {
    'platformName': 'Android',
    'platformVersion': '8.1',
    'deviceName': 'ye_shen_Android',
    'appPackage': 'com.tencent.mm',
    'appActivity': 'com.tencent.mm.ui.LauncherUI',
    'noReset': True,
    'autoAcceptAlerts': True,
    'newCommandTimeout': 240,
    # 'automationName': 'uiautomator2'
}

driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
driver.implicitly_wait(10)

# 点击 微信 聊天框
loc = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("通讯录")')
WebDriverWait(driver, 30).until(EC.visibility_of_element_located(loc))
# el = driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,'new UiSelector().resourceId("com.tencent.mm:id/bth")')
TouchAction(driver).tap(x=152, y=315).wait(200).perform()

# 点击 里面的地图
locc = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().textContains("西乡")')
WebDriverWait(driver, 30).until(EC.visibility_of_element_located(locc))
ele = driver.find_element(MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().textContains("西乡")')
TouchAction(driver).tap(ele).wait(200).perform()

def getSize(driver):
    x = driver.get_window_size()['width']
    y = driver.get_window_size()['height']
    return x, y

# 放大
def narrow():
    x, y = getSize(driver)
    action1 = TouchAction(driver)
    action2 = TouchAction(driver)
    zoom_action = MultiAction(driver)
    action1.press(x=x*0.2, y=y*0.2).wait(1000).move_to(x=x*0.4, y=y*0.4).wait(1000).release()
    action2.press(x=x*0.8, y=y*0.8).wait(1000).move_to(x=x*0.6, y=y*0.6).wait(1000).release()
    zoom_action.add(action1, action2)
    zoom_action.perform()

# 缩小
def enlarge():
    x, y = getSize(driver)
    action1=TouchAction(driver)
    action2=TouchAction(driver)
    zoom_action=MultiAction(driver)
    action1.press(x=x*0.4,y=y*0.4).wait(1000).move_to(x=x*0.2,y=y*0.2).wait(1000).release()
    action2.press(x=x*0.6,y=y*0.6).wait(1000).move_to(x=x*0.8,y=y*0.8).wait(1000).release()
    zoom_action.add(action1,action2)
    zoom_action.perform()


if __name__ == '__main__':
    for i in range(5):
        narrow()

    for i in range(5):
        enlarge()

2.2 放大/缩小操作另一个方法:zoom/pinch

参数:percent:在某控件上执行放大操作,默认放大比例为200%,steps:表示 放大/缩小 动作分多少步完成,默认50

- zoom(self, element=None, percent=200, steps=50)
- pinch(self, element=None, percent=200, steps=50)

# 放大
driver.zoom(element)
# 缩小
driver.pinch(element)

3.滑屏操作:

借鉴文章戳这里

A. driver.swipe(x1, y1, x2, y2,duration)


swipe(起始X,起始Y, 结束X,结束Y)
起始X - 结束X:X滑动的距离
起始Y - 结束Y:Y滑动的距离

从坐标(x1,x2)滑动到坐标(x2,y2),duration:时长/毫秒,滑动时间(滑动的坐标不能超过屏幕的宽高)

size = driver.get_window_size()
print(driver.get_window_size())
返回的是:{'width': 1080, 'height': 1776}
利用 swipe(self, start_x, start_y, end_x, end_y, duration=0)方法:
start_x = size['width'] * 0.9  # 宽度
start_y = size['height'] * 0.5  # 高度
end_x = size['width'] * 0.1
end_y = size['height'] * 0.5

一个屏幕向上下左右活动的方法如下:

import time
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy

desired_caps = {
    'platformName': 'Android',
    'platformVersion': '8.1',
    'deviceName': 'ye_shen_Android',
    'appPackage': 'com.tencent.mm',
    'appActivity': 'com.tencent.mm.ui.LauncherUI',
    'noReset': True,
    'autoAcceptAlerts': True,
    'newCommandTimeout': 240
}

driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)

loc = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().resourceId("com.tencent.mm:id/cn_")')
WebDriverWait(driver, 10).until(EC.visibility_of_element_located(loc))



#获得屏幕大小宽和高
def getSize(driver):
    x = driver.get_window_size()['width']
    y = driver.get_window_size()['height']
    return (x, y)

#屏幕向上滑动
def swipeUp(driver,t=1000):
    l = getSize(driver)
    x1 = int(l[0] * 0.5)    #x坐标
    y1 = int(l[1] * 0.75)   #起始y坐标
    y2 = int(l[1] * 0.25)   #终点y坐标
    driver.swipe(x1, y1, x1, y2,t)

#屏幕向下滑动
def swipeDown(driver,t=1000):
    l = getSize(driver)
    x1 = int(l[0] * 0.5)  #x坐标
    y1 = int(l[1] * 0.25)   #起始y坐标
    y2 = int(l[1] * 0.75)   #终点y坐标
    driver.swipe(x1, y1, x1, y2,t)
#屏幕向左滑动
def swipLeft(driver,t):
    l=getSize(driver)
    x1=int(l[0]*0.75)
    y1=int(l[1]*0.5)
    x2=int(l[0]*0.05)
    driver.swipe(x1,y1,x2,y1,t)
#屏幕向右滑动
def swipRight(driver,t=1000):
    l=getSize(driver)
    x1=int(l[0]*0.05)
    y1=int(l[1]*0.5)
    x2=int(l[0]*0.75)
    driver.swipe(x1,y1,x2,y1,t)
 
#调用向下滑动的方法
swipeDown(driver) 

B.driver.scroll

  • 从一个元素滚动到另一个元素,只能是两个元素之间的滑动。
  • 第一幅图是下拉打开小程序,第二个图是桶装水代替订阅号消息位置

方法详情:

参数:origin_el - 要滚动的起始元素;destination_el - 要滚动到的结束元素;duration - 持续时间,单位毫秒,默认为 600 ms

def scroll(self: T, origin_el: WebElement, destination_el: WebElement, duration: Optional[int] = None) -> T:
    if self.w3c and duration is None:
            duration = 600

        action = TouchAction(self)
        if duration is None:
            action.press(origin_el).move_to(destination_el).release().perform()
        else:
            action.press(origin_el).wait(duration).move_to(destination_el).release().perform()
        return self

代码实战:

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy

desired_caps = {
    'platformName': 'Android',
    'platformVersion': '8.1',
    'deviceName': 'ye_shen_Android',
    'appPackage': 'com.tencent.mm',
    'appActivity': 'com.tencent.mm.ui.LauncherUI',
    'noReset': True,
    'autoAcceptAlerts': True,
    'newCommandTimeout': 240,
    # 'automationName': 'uiautomator2'
}

driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
driver.implicitly_wait(10)

#点击 微信
loc = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("通讯录")')
WebDriverWait(driver, 30).until(EC.visibility_of_element_located(loc))

# 订阅号消息
stop_element = driver.find_element(MobileBy.XPATH, '//*[@resource-id="com.tencent.mm:id/gkp"]/android.widget.LinearLayout[2]')

# 桶装水
start_element = driver.find_element(MobileBy.XPATH, '//*[@resource-id="com.tencent.mm:id/gkp"]/android.widget.LinearLayout[7]')

# 执⾏滑动操作 以下 二者选一执行
# 下拉微信的到小程序
driver.scroll(stop_element,start_element,3000)
# 桶装水代替订阅号消息
driver.scroll(start_element,stop_element,3000)

下拉至小程序

注意:操作过程有 惯性,需要添加duration参数,参数值越大,惯性越小

C. driver.drag_and_drop


从一个元素拖曳到另一个元素,第二个元素代替第一个元素原本屏幕上的位置。
方法:参数:origin_el - 要滑动页面的起始元素;destination_el - 要滑动页面到结束元素。

def drag_and_drop(self: T, origin_el: WebElement, destination_el: WebElement) -> T:
    action = TouchAction(self)
    action.long_press(origin_el).move_to(destination_el).release().perform()
    return self

代码实战:

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy

desired_caps = {
    'platformName': 'Android',
    'platformVersion': '8.1',
    'deviceName': 'ye_shen_Android',
    'appPackage': 'com.tencent.mm',
    'appActivity': 'com.tencent.mm.ui.LauncherUI',
    'noReset': True,
    'autoAcceptAlerts': True,
    'newCommandTimeout': 240,
    # 'automationName': 'uiautomator2'
}

driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
driver.implicitly_wait(10)

#点击 微信
loc = (MobileBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("通讯录")')
WebDriverWait(driver, 30).until(EC.visibility_of_element_located(loc))

# 订阅号消息
stop_element = driver.find_element(MobileBy.XPATH, '//*[@resource-id="com.tencent.mm:id/gkp"]/android.widget.LinearLayout[2]')

# 桶装水
start_element = driver.find_element(MobileBy.XPATH, '//*[@resource-id="com.tencent.mm:id/gkp"]/android.widget.LinearLayout[7]')

# 执⾏滑动操作 以下 二者选一执行
# 下拉微信的到小程序
driver.drag_and_drop(stop_element,start_element)
# 桶装水代替订阅号消息
driver.drag_and_drop(start_element,stop_element)

driver.drag_and_drop 方法说明:不能设置持续时间,没有惯性。

**总结上述三种方法

滑动和拖拽无非就是考虑是否具有“惯性”,以及传递的参数是“元素”还是“坐标”。
1)scroll:有 “惯性” ,传入 “元素”,可以通过设置duration参数来进行控制惯性大小
2)drag_and_drop:无 “惯性” ,传入 “元素”
3)swipe:有 “惯性” ,传入 “坐标”,可以通过设置duration参数来进行控制惯性大小

原文

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐