一、基本操作
1、点击操作
示例:element.click() 针对元素进行点击操作
2、初始化:输入中文的处理
说明:如果连接的是虚拟机(真机无需加这两个参数,加上可能会影响手工输入),在初始化配置中增加两个参数:
- "resetKeyboard": True, # 重置设备的输入键盘
- "unicodeKeyboard": True # 采用unicode编码输入
"resetKeyboard": True, # 重置设备的输入键盘
"unicodeKeyboard": True # 采用unicode编码输入
3、清空和输入操作
- element.clear() 针对元素进行清空操作
- element.send_keys("value") 针对元素进行输入操作
输入的封装:
def input_text(element, text):
# 清除元素中的文本内容(为了保证代码的健壮性,在输入内容之前需要做一次清除操作。)
element.clear()
# 输入文本内容
element.send_keys(text)
4、获取元素的信息
- 获取元素的文本内容(获取的是元素text属性的内容)
element.text - 获取元素的位置
element.location 返回的值是一个字典,字典中包含x和y , x和y表示的是元素在手机屏幕左上角的点的坐标 - 获取取元素的大小
element.size 返回值是一个字典,字典中会包含 width和height, width表示的宽度,height表示的高度 - 获取元素的属性值
element.get_attribute("attribute") # attribute表示的是属性名称
获取ID值时, attribute= “resourceId”
获取的是class的值 , attribute="className"
如果attribute = "name"时,获取的是text或者content-desc(text优先,找不到text值,再去找content-desc的值)
代码示例:
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as EC
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
# 定义desired_caps 字典,初始化app的配置信息
desired_caps = {
"platformName": "android", # 表示的是android
"platformVersion": "10", # 表示的是设备系统的版本号
"deviceName": "DWV6R19A10002101", # 表示的是设备的ID名称
"appPackage": app_package, # 表示的是app的包名
"appActivity": app_activity, # 表示的是app的界面名
"newCommandTimeout": 100000,
"noReset": True, # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
"resetKeyboard": True, # 重置设备的输入键盘
"unicodeKeyboard": True # 采用unicode编码输入
}
# 创建 Appium 驱动实例
options = UiAutomator2Options().load_capabilities(desired_caps)
driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
# 启动应用程序
driver.wait_activity(desired_caps, 5)
return driver
# 定义一个获取元素的方法
def get_element_new(driver, element):
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located(element))
return element
# 定义一个输入的封装方法
def input_text(element, text):
# 清除元素中的文本内容(为了保证代码的健壮性,在输入内容之前需要做一次清除操作。)
element.clear()
# 输入文本内容
element.send_keys(text)
if __name__ == "__main__":
# 本次启动的应用程序包名和活动名(作业帮)
app_package_zyb = "com.baidu.homework"
app_activity_zyb = ".activity.index.IndexActivity"
# 启动应用程序
driver_zyb = start_app(app_package_zyb, app_activity_zyb)
# 定位到首页顶部搜索框并点击
element = (By.ID, 'com.baidu.homework:id/tv_homepage_search_item')
search_element = get_element_new(driver_zyb, element)
search_element.click()
# 定位到输入框并输入"英语学习"
element = (By.ID, 'com.baidu.homework:id/index_search_et_search_text')
input_element = get_element_new(driver_zyb, element)
input_text(input_element, '英语学习')
# 获取元素的文本内容(获取的是元素text属性的内容)
print(f"输入框元素的文本信息是: {input_element.text}")
# 获取元素的位置(返回的值是一个字典,字典中包含x和y , x和y表示的是元素在手机屏幕左上角的点的坐标)
print(f"输入框的元素的位置坐标是: {input_element.location}")
# 获取取元素的大小
print(f"输入框元素的文本信息是: {input_element.size}")
'''
获取元素的属性值
element.get_attribute("attribute") # attribute表示的是属性名称
获取ID值时, attribute = “resourceId”
获取的是class的值, attribute = "className"
如果attribute = "name"
时,获取的是text或者content - desc(text优先,找不到text值,再去找content - desc的值)
'''
print(f"输入框元素的ID属性信息是: {input_element.get_attribute('resourceId')}")
print(f"输入框元素的class属性信息是: {input_element.get_attribute('className')}")
print(f"输入框元素的name属性信息是: {input_element.get_attribute('name')}")
# 关闭驱动
time.sleep(3)
print("代码执行完毕")
driver_zyb.quit()
二、获取手机操作
1、获取手机分辨率
目的:保证脚本在不同机型上都能实现滑屏的操作。
示例:driver.get_window_size()
说明: 返回的值是字典类型, 包含 height 和 width 高度和宽度的值
2、获取手机截图
示例:driver.get_screenshot_as_file(filename)
说明:filename:1、路径必须手动创建 2、文件名称必须是以PNG结尾
3、设置/获取手机网络
目的:主要是为了实现视频类的app中,视频播放过程中网络切换时会有提示信息的操作。
示例:
- driver.set_network_connection(connectionType) # connectionType 网络类型的值
- driver.network_connection 获取手机网络
说明:在 Appium 中,网络类型通过driver.set_network_connection(connection type)方法进行设置。其中,connection type参数表示需要被设置的网络类型,常用的网络类型有以下几种:
- 飞行模式:1
- WiFi 流量:2
- 数据流量:4
- 数据和 WiFi 全部打开:6
4、模拟键盘操作
示例:driver.press_keycode(键值)
说明:常用的三个键值: 3 HOME键, 4 返回键 , 66 回车键
5、手机通知栏操作
示例:driver.open_notifications()
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as EC
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
# 定义desired_caps 字典,初始化app的配置信息
desired_caps = {
"platformName": "android", # 表示的是android
"platformVersion": "10", # 表示的是设备系统的版本号
"deviceName": "DWV6R19A10002101", # 表示的是设备的ID名称
"appPackage": app_package, # 表示的是app的包名
"appActivity": app_activity, # 表示的是app的界面名
"newCommandTimeout": 100000,
"noReset": True, # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
"resetKeyboard": True, # 重置设备的输入键盘
"unicodeKeyboard": True # 采用unicode编码输入
}
# 创建 Appium 驱动实例
options = UiAutomator2Options().load_capabilities(desired_caps)
driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
# 启动应用程序
driver.wait_activity(desired_caps, 5)
return driver
# 定义一个获取元素的方法
def get_element_new(driver, element):
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located(element))
return element
# 定义一个输入的封装方法
def input_text(element, text):
# 清除元素中的文本内容(为了保证代码的健壮性,在输入内容之前需要做一次清除操作。)
element.clear()
# 输入文本内容
element.send_keys(text)
if __name__ == "__main__":
# 本次启动的应用程序包名和活动名(作业帮)
app_package_zyb = "com.baidu.homework"
app_activity_zyb = ".activity.index.IndexActivity"
# 启动应用程序
driver_zyb = start_app(app_package_zyb, app_activity_zyb)
# 获取手机分辨率
print(driver_zyb.get_window_size())
# 获取手机截图
""" 1、路径必须手动创建
2、文件名称必须是以PNG结尾"""
current_time_file = "/error"+str(time.time()) # 通过文件名拼接当前时间戳的方式构造唯一文件名
filename = "/Users/work_related/image" + current_time_file + ".png" # 需要设置正确的路径
driver_zyb.get_screenshot_as_file(filename)
# 设置手机网络为Wi-Fi,然后获取当前手机的网络类型
"""飞行模式:1
WiFi 流量:2
数据流量:4
数据和 WiFi 全部打开:6"""
driver_zyb.set_network_connection(2) # 设置手机网络为Wi-Fi
print(f"当前手机的网络类型是:{driver_zyb.network_connection}") # 获取当前手机的网络类型
# 模拟键盘操作
'''常用的三个键值: 3 HOME键, 4 返回键 , 66 回车键'''
# 定位到首页顶部搜索框并点击
element = (By.ID, 'com.baidu.homework:id/tv_homepage_search_item')
search_element = get_element_new(driver_zyb, element)
search_element.click()
# 定位到输入框并输入"英语学习"
element = (By.ID, 'com.baidu.homework:id/index_search_et_search_text')
input_element = get_element_new(driver_zyb, element)
input_text(input_element, '英语学习')
# 返回到上一页
driver_zyb.press_keycode(4)
time.sleep(3)
# home键返回
driver_zyb.press_keycode(3)
time.sleep(3)
# 打开手机通知栏
driver_zyb.open_notifications()
# 关闭驱动
time.sleep(3)
print("代码执行完毕")
driver_zyb.quit()
三、滑动和拖拽事件
1、swipe滑动事件
示例:driver.swipe(startx, starty, endx, endy, duration=None)
说明:duration用来降低滑屏的速度及惯性, 单位是ms
2、swipe滑动事件封装
# 定义一个封装滑屏操作的方法
def slide_screen(driver, direction, count=1):
w = driver.get_window_size()["width"] # 获取手机屏幕的宽度
h = driver.get_window_size()["height"] # 获取手机屏幕的高度
# w=1080 h=1920
if direction == "up": # 往上滑
zb = (w/2, h*0.9, w/2, h*0.1)
elif direction == "down": # 往下滑
zb = (w/2, h*0.1, w/2, h*0.9)
elif direction == 'left': # 往左滑
zb = (w*0.9, h/2, w*0.1, h/2)
elif direction == 'right': # 往右滑
zb = (w*0.1, h/2, w*0.9, h/2)
else:
print("无法识别滑动方向,请重新输入!")
for i in range(count):
driver.swipe(*zb, duration=1200)
time.sleep(1)
3、swipe边滑动边查找封装
目的:针对频道类的元素进行滑动选择对应的频道。
# 封装一个边滑动边查找的方法
def search_while_sliding(driver, element, element_info):
ele_size = element.size # 获取元素大小
width = ele_size["width"] # 获取元素的宽度
height = ele_size["height"] # 获取元素的高度
# 获了element元素左上角点的坐标
ele_position = element.location
x = ele_position["x"] # 获取左上角点的x坐标值
y = ele_position["y"] # 获取左上角点的y坐标值
start_x = x + width*0.9 # 获取的是起始点X的值
y = y + height*0.5 # 获取的是起始及终止点的Y的值
end_x = x + width*0.1 # 获取的是终止点X的值
while True:
page = driver.page_source # 记录查找前的页面资源,通过对比页面资源来退出死循环
try:
driver.find_element(*element_info).click() # 如果有找到对应的元素那么点击并返回
return True
except Exception as e:
print("没有找到该元素!")
driver.swipe(start_x, y, end_x, y, duration=1000) # 没有找到元素,那么滑屏后再对比并重新查找
time.sleep(1)
if page == driver.page_source:
print("滑屏操作完成且没有找到元素信息")
return False
上述代码实现逻辑解释:
- while True:创建一个无限循环。
- page = driver.page_source:记录查找前的页面资源,用于后续对比以判断是否退出循环。
- driver.find_element(*element_info).click():尝试查找并点击指定元素,如果找到则返回True。
- except Exception as e:如果没有找到元素,打印提示信息。
- driver.swipe(start_x, y, end_x, y, duration=1000):没有找到元素时,执行滑屏操作。
- time.sleep(1):等待一段时间。
- if page == driver.page_source:如果滑屏操作完成后页面资源没有变化,说明没有找到元素,打印相关提示并返回False。
4、scroll滑动事件
示例:driver.scroll(source_element, target_element)
说明:scroll是通过元素来进行滑动的
- source_element表示原元素;target_element表示目标元素,滑动原理是由原元素拖动到目标元素的位置
- scroll无法设置滑动的持续时间,带有一定惯性。 主要用于IOS中,android高版本系统可以使用。
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as EC
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
# 定义desired_caps 字典,初始化app的配置信息
desired_caps = {
"platformName": "android", # 表示的是android
"platformVersion": "10", # 表示的是设备系统的版本号
"deviceName": "DWV6R19A10002101", # 表示的是设备的ID名称
"appPackage": app_package, # 表示的是app的包名
"appActivity": app_activity, # 表示的是app的界面名
"newCommandTimeout": 100000,
"noReset": True, # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
"resetKeyboard": True, # 重置设备的输入键盘
"unicodeKeyboard": True # 采用unicode编码输入
}
# 创建 Appium 驱动实例
options = UiAutomator2Options().load_capabilities(desired_caps)
driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
# 启动应用程序
driver.wait_activity(desired_caps, 5)
return driver
# 定义一个获取元素的方法
def get_element_new(driver, element):
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located(element))
return element
if __name__ == "__main__":
# 本次启动的应用程序包名和活动名(作业帮)
app_package_zyb = "com.baidu.homework"
app_activity_zyb = ".activity.index.IndexActivity"
# 启动应用程序
driver_zyb = start_app(app_package_zyb, app_activity_zyb)
# 进入「我的」tab
my_tab = (By.XPATH, '//android.widget.RelativeLayout[@resource-id="com.baidu.homework:id/tab_my_layout"]')
get_element_new(driver_zyb, my_tab).click()
# 找到「我的活动」元素
My_activities = (By.XPATH, '//android.widget.TextView[@resource-id='
'"com.baidu.homework:id/user_item_title" and @text="我的活动"]')
my_activities = get_element_new(driver_zyb, My_activities)
# 找到「我的订单」元素
my_order = (By.ID, 'com.baidu.homework:id/user_item_title')
my_order_element = get_element_new(driver_zyb, my_order)
# 滑动
driver_zyb.scroll(my_activities, my_order_element)
# 关闭驱动
time.sleep(3)
print("代码执行完毕")
driver_zyb.quit()
5、drag_and_drop拖拽事件
原理:从一个元素滑动到另外一个元素的位置, 同时也能实现将一个元素拖动另一个元素当中。
示例:driver.drag_and_drop(source_element, target_element)
说明:
- source_element 表示的是被拖动的元素对象
- target_element 表示的是目标元素对象
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as EC
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
# 定义desired_caps 字典,初始化app的配置信息
desired_caps = {
"platformName": "android", # 表示的是android
"platformVersion": "10", # 表示的是设备系统的版本号
"deviceName": "DWV6R19A10002101", # 表示的是设备的ID名称
"appPackage": app_package, # 表示的是app的包名
"appActivity": app_activity, # 表示的是app的界面名
"newCommandTimeout": 100000,
"noReset": True, # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
# "resetKeyboard": True, # 重置设备的输入键盘 (连接虚拟机时使用)
# "unicodeKeyboard": True # 采用unicode编码输入(连接虚拟机时使用)
}
# 创建 Appium 驱动实例
options = UiAutomator2Options().load_capabilities(desired_caps)
driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
# 启动应用程序
driver.wait_activity(desired_caps, 5)
return driver
# 定义一个获取元素的方法
def get_element_new(driver, element):
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located(element))
return element
if __name__ == "__main__":
# 本次启动的应用程序包名和活动名(作业帮)
app_package_zyb = "com.baidu.homework"
app_activity_zyb = ".activity.index.IndexActivity"
# 启动应用程序
driver_zyb = start_app(app_package_zyb, app_activity_zyb)
# 进入「我的」tab
my_tab = (By.XPATH, '//android.widget.RelativeLayout[@resource-id="com.baidu.homework:id/tab_my_layout"]')
get_element_new(driver_zyb, my_tab).click()
# 找到「我的活动」元素
My_activities = (By.XPATH, '//android.widget.TextView[@resource-id='
'"com.baidu.homework:id/user_item_title" and @text="我的活动"]')
my_activities = get_element_new(driver_zyb, My_activities)
# 找到「我的订单」元素
my_order = (By.ID, 'com.baidu.homework:id/user_item_title')
my_order_element = get_element_new(driver_zyb, my_order)
# 通过拖动来实现滑屏操作
driver_zyb.drag_and_drop(my_activities, my_order_element)
# 关闭驱动
time.sleep(3)
print("代码执行完毕")
driver_zyb.quit()
四、高级手势操作
实现步骤:
1、创建TouchAction对象
2、调用手势方法
3、调用perform() 执行操作
1、轻敲操作
示例说明:
- action = TouchAction(driver) # 创建建手势对象
- action.tap(element=None, x=None, y=None, count=1) # 调用轻敲手势方法,传入的是一个元素对象或者是一个坐标点
count表示的是轻敲的次数, 默认值为1. - action.perform() # 调用perform()执行轻敲操作
2、按下和抬起操作
示例说明:
- 按下:press(element, x, y)
- 抬起:release()
- TouchAction(driver).press(element=None, x=None, y=None).release().perform()
点击(原理):按下和抬起可以结合起来使用,达到点击的效果
3、等待操作
说明:模拟手指等待。 wait(ms=0) ms表示的是毫秒数
示例:TouchAction(driver).press(element=None, x=None, y=None).wait(3000).release().perform()
长按(原理):通过等待及按下和抬起实现长按的操作
4、长按操作
示例:long_press(element, x=None, y=None, duration=1000)
说明:
- element表示的是元素对象
- x, y表示的是坐标点
- duration表示的是长按的时长,单位是毫秒
实现:
TouchAction(driver).long_press(element=None, x=None, y=None, duration=1000).perform()
5、移动操作
原理:模拟手指在手机屏幕上移动的过程,此种方式可以实现手势验证码的解锁(把所有的点都连接起来)
示例:
TouchAction(driver).press(element=None, x=None, y=None).wait(500).move_to(element=None, x=None, y=None).wait(500)
.move_to(element=None, x=None, y=None).release().perform()
说明:
- move_to(element=None, x=None, y=None) element表示的是元素对象, x和y表示的是坐标点。二选其一。
- 移动的操作是需要结合press和release一起使用。
6、代码示例
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as EC
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
# 定义desired_caps 字典,初始化app的配置信息
desired_caps = {
"platformName": "android", # 表示的是android
"platformVersion": "10", # 表示的是设备系统的版本号
"deviceName": "DWV6R19A10002101", # 表示的是设备的ID名称
"appPackage": app_package, # 表示的是app的包名
"appActivity": app_activity, # 表示的是app的界面名
"newCommandTimeout": 100000,
"noReset": True, # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
# "resetKeyboard": True, # 重置设备的输入键盘 (连接虚拟机时使用)
# "unicodeKeyboard": True # 采用unicode编码输入(连接虚拟机时使用)
}
# 创建 Appium 驱动实例
options = UiAutomator2Options().load_capabilities(desired_caps)
driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
# 启动应用程序
driver.wait_activity(desired_caps, 5)
return driver
# 定义一个获取元素的方法
def get_element_new(driver, element):
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located(element))
return element
if __name__ == "__main__":
# 本次启动的应用程序包名和活动名(本机设置页面)
app_package = "com.android.settings"
app_activity = ".HWSettings"
# 启动应用程序
driver = start_app(app_package, app_activity)
'''
一、通过轻敲「WLAN」元素的方式进入WLAN设置页面
action.tap(element=None, x=None, y=None, count=1).perform()
'''
wlan = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="WLAN"]')
wlan_btn = get_element_new(driver, wlan)
TouchAction(driver).tap(wlan_btn).perform()
'''
二、通过「按下和抬起」的方式点击「更多WLAN设置」
TouchAction(driver).press(element=None, x=None, y=None).release().perform()
'''
more_wlan = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="更多 WLAN 设置"]')
more_wlan_btn = get_element_new(driver, more_wlan)
TouchAction(driver).press(more_wlan_btn).release().perform()
# 返回上一页面
time.sleep(1)
driver.press_keycode(4)
time.sleep(2)
'''
三、定位到Wi-Fi列表,通过「等待及按下和抬起」实现长按,展开删除网络/修改网络选项
TouchAction(driver).press(element=None, x=None, y=None).wait(3000).release().perform()
'''
wlan_list = (By.XPATH, '//android.widget.FrameLayout[@resource-id='
'"com.android.settings:id/drop_down_refresh_container"]/android.view.View')
wlan_list_1 = get_element_new(driver, wlan_list)
TouchAction(driver).press(wlan_list_1).wait(3000).release().perform()
# 返回
time.sleep(1)
driver.press_keycode(4)
time.sleep(3)
'''
四、定位到Wi-Fi列表,通过长按,展开删除网络/修改网络选项
TouchAction(driver).long_press(element=None, x=None, y=None, duration=1000).perform()
'''
wlan_list = (By.XPATH, '//android.widget.FrameLayout[@resource-id='
'"com.android.settings:id/drop_down_refresh_container"]/android.view.View')
wlan_list_1 = get_element_new(driver, wlan_list)
TouchAction(driver).long_press(wlan_list_1, duration=3000).perform()
# 返回
time.sleep(2)
driver.press_keycode(4)
'''
五、通过move_to(element, x=x, y=y) 从一个元素移动到另一个元素
此种方式可以实现手势验证码的解锁(把所有的点都连接起来)
TouchAction(driver).press(element=None, x=None, y=None).wait(500).move_to(element=None, x=None, y=None).wait(500)
.move_to(element=None, x=None, y=None).release().perform()
下图示例只为演示效果
'''
# 返回到设置页面
time.sleep(2)
driver.press_keycode(4)
# 找到「更多连接」元素信息
more_connections = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="更多连接"]')
more_connections_btn = get_element_new(driver, more_connections)
# 由「更多连接」元素移动到「WLAN」元素位置(实际工作中,可以通过此种方式实现点到点的连接,完成手势验证码的解锁)
TouchAction(driver).press(more_connections_btn).wait(500).move_to(wlan_btn).release().perform()
# 关闭驱动
time.sleep(3)
print("代码执行完毕")
driver.quit()
五、toast操作
Toast是Android中用来显示显示信息的一种机制,Toast的特点是没有焦点,而且显示的时间有限,过一定的时间就会自动消失。
定位方法:
- 初始化配置中需要增加一个配置项:"automationName": "UiAutomator2"
- toast 通用的class属性获取,通过xpath的方式://*[@class="android.widget.Toast"]
方法封装:
def get_toast(driver, timeout=3, poll_frequency=0.5):
try:
toast_loc = ("xpath", "//*[@class='android.widget.Toast']")
WebDriverWait(driver, timeout, poll_frequency).until(es.presence_of_element_located(toast_loc))
toast_text = driver.find_element(By.XPATH, "//*[@class='android.widget.Toast']").text
return toast_text
except:
return None
代码示例:
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as es
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
# 定义desired_caps 字典,初始化app的配置信息
desired_caps = {
"platformName": "android", # 表示的是android
"platformVersion": "10", # 表示的是设备系统的版本号
"deviceName": "DWV6R19A10002101", # 表示的是设备的ID名称
"appPackage": app_package, # 表示的是app的包名
"appActivity": app_activity, # 表示的是app的界面名
"newCommandTimeout": 100000,
"noReset": True, # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
# "resetKeyboard": True, # 重置设备的输入键盘 (连接虚拟机时使用)
# "unicodeKeyboard": True # 采用unicode编码输入(连接虚拟机时使用)
"automationName": "UiAutomator2" # 获取toast信息需要使用
}
# 创建 Appium 驱动实例
options = UiAutomator2Options().load_capabilities(desired_caps)
driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
# 启动应用程序
driver.wait_activity(desired_caps, 5)
return driver
# 定义一个获取元素的方法
def get_element_new(driver, element):
element = WebDriverWait(driver, 10).until(es.visibility_of_element_located(element))
return element
# 定义一个封装滑屏操作的方法
def slide_screen(driver, direction, count=1):
w = driver.get_window_size()["width"] # 获取手机屏幕的宽度
h = driver.get_window_size()["height"] # 获取手机屏幕的高度
# w=1080 h=1920
if direction == "up": # 往上滑
zb = (w/2, h*0.9, w/2, h*0.1)
elif direction == "down": # 往下滑
zb = (w/2, h*0.1, w/2, h*0.9)
elif direction == 'left': # 往左滑
zb = (w*0.9, h/2, w*0.1, h/2)
elif direction == 'right': # 往右滑
zb = (w*0.1, h/2, w*0.9, h/2)
else:
print("无法识别滑动方向,请重新输入!")
for i in range(count):
driver.swipe(*zb, duration=1200)
time.sleep(1)
# 定义一个获取toast的方法
def get_toast(driver, timeout=3, poll_frequency=0.5):
try:
toast_loc = ("xpath", "//*[@class='android.widget.Toast']")
WebDriverWait(driver, timeout, poll_frequency).until(es.presence_of_element_located(toast_loc))
toast_text = driver.find_element(By.XPATH, "//*[@class='android.widget.Toast']").text
return toast_text
except:
return None
if __name__ == "__main__":
# 本次启动的应用程序包名和活动名(本机设置页面)
app_package = "com.android.settings"
app_activity = ".HWSettings"
# 启动应用程序
driver = start_app(app_package, app_activity)
# 向上滑动页面两次到页面底部
slide_screen(driver, "up", 2)
time.sleep(2)
# 找到「关于本机」按钮并点击
about_this_machine = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="关于手机"]')
get_element_new(driver, about_this_machine).click()
# 获取版本号元素信息并点击(for循环进行多次点击)
version = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="HarmonyOS 版本"]')
version_btn = get_element_new(driver, version)
for i in range(1, 6):
if i <= 6:
version_btn.click()
i += 1
# 获取toast提示信息并打印
# toast_text = driver.find_element(By.XPATH, "//*[@class=\"android.widget.Toast\"]").text
# print(f"toast提示信息是:{toast_text}")
toast_text = get_toast(driver)
print(toast_text)
# 关闭驱动
time.sleep(3)
print("代码执行完毕")
driver.quit()
方法二:如果上述方法无法实现获取toast信息,可以通过截图记录toast信息
代码示例如下:
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as EC
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
# 定义desired_caps 字典,初始化app的配置信息
desired_caps = {
"platformName": "android", # 表示的是android
"platformVersion": "10", # 表示的是设备系统的版本号
"deviceName": "DWV6R19A10002101", # 表示的是设备的ID名称
"appPackage": app_package, # 表示的是app的包名
"appActivity": app_activity, # 表示的是app的界面名
"newCommandTimeout": 100000,
"noReset": True, # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
# "resetKeyboard": True, # 重置设备的输入键盘 (连接虚拟机时使用)
# "unicodeKeyboard": True # 采用unicode编码输入(连接虚拟机时使用)
"automationName": "Uiautomator2"
}
# 创建 Appium 驱动实例
options = UiAutomator2Options().load_capabilities(desired_caps)
driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
# 启动应用程序
driver.wait_activity(desired_caps, 5)
return driver
# 定义一个获取元素的方法
def get_element_new(driver, element):
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located(element))
return element
# 定义一个封装滑屏操作的方法
def slide_screen(driver, direction, count=1):
w = driver.get_window_size()["width"] # 获取手机屏幕的宽度
h = driver.get_window_size()["height"] # 获取手机屏幕的高度
# w=1080 h=1920
if direction == "up": # 往上滑
zb = (w/2, h*0.9, w/2, h*0.1)
elif direction == "down": # 往下滑
zb = (w/2, h*0.1, w/2, h*0.9)
elif direction == 'left': # 往左滑
zb = (w*0.9, h/2, w*0.1, h/2)
elif direction == 'right': # 往右滑
zb = (w*0.1, h/2, w*0.9, h/2)
else:
print("无法识别滑动方向,请重新输入!")
for i in range(count):
driver.swipe(*zb, duration=1200)
time.sleep(1)
if __name__ == "__main__":
# 本次启动的应用程序包名和活动名(本机设置页面)
app_package = "com.android.settings"
app_activity = ".HWSettings"
# 启动应用程序
driver = start_app(app_package, app_activity)
# 向上滑动页面两次到页面底部
slide_screen(driver, "up", 2)
time.sleep(2)
# 找到「关于本机」按钮并点击
about_this_machine = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="关于手机"]')
get_element_new(driver, about_this_machine).click()
# 获取版本号元素信息并点击(for循环进行多次点击)
version = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="HarmonyOS 版本"]')
version_btn = get_element_new(driver, version)
for i in range(1, 6):
if i <= 6:
version_btn.click()
i += 1
# 获取toast信息(截图)
# 获取手机截图
""" 1、路径必须手动创建
2、文件名称必须是以PNG结尾"""
current_time_file = "/error" + str(time.time()) # 通过文件名拼接当前时间戳的方式构造唯一文件名
filename = "/替换成自己正确的路径" + current_time_file + ".png"
time.sleep(0.5)
driver.get_screenshot_as_file(filename) # 获取toast信息截图
# 关闭驱动
time.sleep(3)
print("代码执行完毕")
driver.quit()
六、webview操作(H5)
说明:Appium Inspector 可以对 H5 页面元素直接进行操作。在操作混合 App 或 Android App 的 H5 页面时,常常需要定位 H5 页面中的元素,传统方式需要使用Chrome://inspect 来定位元素,环境准备相当繁琐,需要Android 设备安装 Google 框架以及手机版 Chrome 浏览器以及相应的 chromedriver。而使用 Appium Inspector 即可实现 H5 页面元素的定位,不需要额外安装任何软件。
示例:
如下图包含原生和H5页面(混合APP)['NATIVE_APP', 'WEBVIEW_com.huawei.browser'],可以通过Appium Inspector轻松实现定位操作:
代码示例:
import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as EC
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
# 定义desired_caps 字典,初始化app的配置信息
desired_caps = {
"platformName": "android", # 表示的是android
"platformVersion": "10", # 表示的是设备系统的版本号
"deviceName": "DWV6R19A10002101", # 表示的是设备的ID名称,标识测试设备
"appPackage": app_package, # 表示的是app的包名
"appActivity": app_activity, # 表示的是app的界面名
"newCommandTimeout": 100000,
"noReset": True, # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
# "resetKeyboard": True, # 重置设备的输入键盘 (连接虚拟机时使用)
# "unicodeKeyboard": True # 采用unicode编码输入(连接虚拟机时使用)
}
# 创建 Appium 驱动实例
options = UiAutomator2Options().load_capabilities(desired_caps)
driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
# 启动应用程序
driver.wait_activity(desired_caps, 5)
return driver
# 定义一个获取元素的方法
def get_element_new(driver, element):
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located(element))
return element
if __name__ == "__main__":
# 本次启动的应用程序包名和活动名(本机设置页面)
app_package = "com.baidu.homework"
app_activity = ".activity.index.IndexActivity"
# 启动应用程序
driver = start_app(app_package, app_activity)
# 定位h5页面中的一个元素并点击
h5_xpath = By.XPATH, '(//android.widget.ImageView[@resource-id="com.baidu.homework:id/image"])[1]'
get_element_new(driver, h5_xpath).click()
# 这里可以获取下上下文,可以发现这里包含原生和H5页面(混合APP)['NATIVE_APP', 'WEBVIEW_com.huawei.browser']
contexts = driver.contexts
print(contexts)
# 定位h5页面中的另一个元素并点击
h5_ = By.XPATH, '(//android.widget.Image[@text="zyb_e7dd291daa70ff318315b0b5dcc59989"])[1]'
get_element_new(driver, h5_).click()
# 关闭驱动
time.sleep(3)
print("代码执行完毕")
driver.quit()