python爬虫之Appium 的使用

Appium 是一个跨平台移动端自动化测试工具,可以非常便捷地为 iOS 和 Android 平台创建自动化测试用例。它可以模拟 App 内部的各种操作,如点击、滑动、文本输入等,只要我们手工操作的动作 Appium 都可以完成。在前面我们了解过 Selenium,它是一个网页端的自动化测试工具。Appium 实际上继承了 Selenium,Appium 也是利用 WebDriver 来实现 App 的自动化测试。对 iOS 设备来说,Appium 使用 UIAutomation 来实现驱动。对于 Android 来说,它使用 UiAutomator 和 Selendroid 来实现驱动。

Appium 相当于一个服务器,我们可以向 Appium 发送一些操作指令,Appium 就会根据不同的指令对移动设备进行驱动,完成不同的动作。

对于爬虫来说,我们用 Selenium 来抓取 JavaScript 渲染的页面,可见即可爬。Appium 同样也可以,用 Appium 来做 App 爬虫不失为一个好的选择。

下面我们来了解 Appium 的基本使用方法。

1. 本节目标

我们以 Android 平台的微信为例来演示 Appium 启动和操作 App 的方法,主要目的是了解利用 Appium 进行自动化测试的流程以及相关 API 的用法。

2. 准备工作

请确保 PC 已经安装好 Appium、Android 开发环境和 Python 版本的 Appium API,安装方法可以参考第 1 章。另外,Android 手机安装好微信 App。

3. 启动 APP

Appium 启动 App 的方式有两种:一种是用 Appium 内置的驱动器来打开 App,另一种是利用 Python 程序实现此操作。下面我们分别进行说明。

首先打开 Appium,启动界面如图。

直接点击 Start Server 按钮即可启动 Appium 的服务,相当于开启了一个 Appium 服务器。我们可以通过 Appium 内置的驱动或 Python 代码向 Appium 的服务器发送一系列操作指令,Appium 就会根据不同的指令对移动设备进行驱动,完成不同的动作。启动后运行界面如图。

Appium 运行之后正在监听 4723 端口。我们可以向此端口对应的服务接口发送操作指令,此页面就会显示这个过程的操作日志。

将 Android 手机通过数据线和运行 Appium 的 PC 相连,同时打开 USB 调试功能,确保 PC 可以连接到手机。

可以输入 adb 命令来测试连接情况,如下所示:

adb devices -l

如果出现类似如下结果,这就说明 PC 已经正确连接手机。

List of devices attached
2da42ac0 device usb:336592896X product:leo model:MI_NOTE_Pro device:leo

model 是设备的名称,就是后文需要用到的 deviceName 变量。我使用的是小米 Note 顶配版,所以此处名称为 MI_NOTE_Pro。

如果提示找不到 adb 命令,请检查 Android 开发环境和环境变量是否配置成功。如果可以成功调用 adb 命令但不显示设备信息,请检查手机和 PC 的连接情况。

接下来用 Appium 内置的驱动器打开 App,点击 Appium 中的 Start New Session 按钮。

这时会出现一个配置页面。

需要配置启动 App 时的 Desired Capabilities 参数,它们分别是 platformName、deviceName、appPackage、appActivity。

  • platformName,平台名称,需要区分是 Android 还是 iOS,此处填写 Android。

  • deviceName,设备名称,是手机的具体类型。

  • appPackage,APP 程序包名。

  • appActivity,入口 Activity 名,这里通常需要以。开头。

在当前配置页面的左下角也有配置参数的相关说明,链接是 https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md。

我们在 Appium 中加入上面 4 个配置。

点击保存按钮,保存下来,我们以后可以继续使用这个配置。

点击右下角的 Start Session 按钮,即可启动 Android 手机上的微信 App 并进入到启动页面。同时 PC 上会弹出一个调试窗口,从这个窗口我们可以预览当前手机页面,并可以查看页面的源码。

点击左栏中屏幕的某个元素,如选中登录按钮,它就会高亮显示。这时中间栏就显示了当前选中的按钮对应的源代码,右栏则显示了该元素的基本信息,如元素的 id、class、text 等,以及可以执行的操作,如 Tap、Send Keys、Clear。

点击中间栏最上方的第三个录制按钮,Appium 会开始录制操作动作,这时我们在窗口中操作 App 的行为都会被记录下来,Recorder 处可以自动生成对应语言的代码。例如,我们点击录制按钮,然后选中 App 中的登录按钮,点击 Tap 操作,即模拟了按钮点击功能,这时手机和窗口的 App 都会跳转到登录页面,同时中间栏会显示此动作对应的代码。

接下来选中左侧的手机号文本框,点击 Send Keys,对话框就会弹出。输入手机号,点击 Send Keys,即可完成文本的输入。

我们可以在此页面点击不同的动作按钮,即可实现对 App 的控制,同时 Recorder 部分也可以生成对应的 Python 代码。

下面我们看看使用 Python 代码驱动 App 的方法。首先需要在代码中指定一个 Appium Server,而这个 Server 在刚才打开 Appium 的时候就已经开启了,是在 4723 端口上运行的,配置如下所示:

server = 'http://localhost:4723/wd/hub'

用字典来配置 Desired Capabilities 参数,代码如下所示:

desired_caps = {'platformName': 'Android','deviceName': 'MI_NOTE_Pro','appPackage': 'com.tencent.mm','appActivity': '.ui.LauncherUI'
}

新建一个 Session,这类似点击 Appium 内置驱动的 Start Session 按钮相同的功能,代码实现如下所示:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
​
driver = webdriver.Remote(server, desired_caps)

配置完成后运行,就可以启动微信 App 了。但是现在仅仅是可以启动 App,还没有做任何动作。

再用代码来模拟刚才演示的两个动作:一个是点击 “登录” 按钮,一个是输入手机号。

看看刚才 Appium 内置驱动器内的 Recorder 录制生成的 Python 代码,自动生成的代码非常累赘,例如点击 “登录” 按钮的代码如下所示:

el1 = driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.View/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.Button[1]")
el1.click()

这段代码的 XPath 选择器路径太长,选择方式没有那么科学,获取元素时也没有设置等待,很可能会有超时异常。所以我们修改一下,将其修改为通过 ID 查找元素,设置延时等待,两次操作的代码改写如下所示:

wait = WebDriverWait(driver, 30)
login = wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/cjk')))
login.click()
phone = wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/h2')))
phone.set_text('18888888888')

综上所述,完整的代码如下所示:

from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
​
server = 'http://localhost:4723/wd/hub'
desired_caps = {'platformName': 'Android','deviceName': 'MI_NOTE_Pro','appPackage': 'com.tencent.mm','appActivity': '.ui.LauncherUI'
}
driver = webdriver.Remote(server, desired_caps)
wait = WebDriverWait(driver, 30)
login = wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/cjk')))
login.click()
phone = wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/h2')))
phone.set_text('18888888888')

一定要重新连接手机,再运行此代码,这时即可观察到手机上首先弹出了微信欢迎页面,然后模拟点击登录按钮、输入手机号,操作完成。这样我们就成功使用 Python 代码实现了 App 的操作。

4. API

接下来看看使用代码如何操作 App、总结相关 API 的用法。这里使用的 Python 库为 AppiumPythonClient,其 GitHub 地址为 GitHub - appium/python-client: Python language bindings for Appium,此库继承自 Selenium,使用方法与 Selenium 有很多共同之处。

初始化

需要配置 Desired Capabilities 参数,完整的配置说明可以参考 https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md,一般来说我们我们配置几个基本参数即可:

from appium import webdriver
​
server = 'http://localhost:4723/wd/hub'
desired_caps = {'platformName': 'Android','deviceName': 'MI_NOTE_Pro','appPackage': 'com.tencent.mm','appActivity': '.ui.LauncherUI'
}
driver = webdriver.Remote(server, desired_caps)

这里配置了启动微信 App 的 Desired Capabilities,这样 Appnium 就会自动查找手机上的包名和入口类,然后将其启动。包名和入口类的名称可以在安装包中的 AndroidManifest.xml 文件获取。

如果要打开的 App 没有事先在手机上安装,我们可以直接指定 App 参数为安装包所在路径,这样程序启动时就会自动向手机安装并启动 App,如下所示:

from appium import webdriver
​
server = 'http://localhost:4723/wd/hub'
desired_caps = {'platformName': 'Android','deviceName': 'MI_NOTE_Pro','app': './weixin.apk'
}
driver = webdriver.Remote(server, desired_caps)

程序启动的时候就会寻找 PC 当前路径下的 APK 安装包,然后将其安装到手机中并启动。

查找元素

我们可以使用 Selenium 中通用的查找方法来实现元素的查找,如下所示:

el = driver.find_element_by_id('com.tencent.mm:id/cjk')

在 Selenium 中,其他查找元素的方法同样适用,在此不再赘述。

在 Android 平台上,我们还可以使用 UIAutomator 来进行元素选择,如下所示:

el = self.driver.find_element_by_android_uiautomator('new UiSelector().description("Animation")')
els = self.driver.find_elements_by_android_uiautomator('new UiSelector().clickable(true)')

在 iOS 平台上,我们可以使用 UIAutomation 来进行元素选择,如下所示:

el = self.driver.find_element_by_ios_uiautomation('.elements()[0]')
els = self.driver.find_elements_by_ios_uiautomation('.elements()')

还可以使用 iOS Predicates 来进行元素选择,如下所示:

el = self.driver.find_element_by_ios_predicate('wdName == "Buttons"')
els = self.driver.find_elements_by_ios_predicate('wdValue == "SearchBar" AND isWDDivisible == 1')

也可以使用 iOS Class Chain 来进行选择,如下所示:

el = self.driver.find_element_by_ios_class_chain('XCUIElementTypeWindow/XCUIElementTypeButton[3]')
els = self.driver.find_elements_by_ios_class_chain('XCUIElementTypeWindow/XCUIElementTypeButton')

但是此种方法只适用于 XCUITest 驱动,具体可以参考:https://github.com/appium/appium-xcuitest- driver。

点击

点击可以使用 tap() 方法,该方法可以模拟手指点击(最多五个手指),可设置按时长短(毫秒),代码如下所示:

tap(self, positions, duration=None)

参数:

  • positions,点击的位置组成的列表。

  • duration,点击持续时间。

实例如下:

driver.tap([(100, 20), (100, 60), (100, 100)], 500)

这样就可以模拟点击屏幕的某几个点。

另外对于某个元素如按钮来说,我们可以直接调用 cilck() 方法实现模拟点击,实例如下所示:

button = find_element_by_id('com.tencent.mm:id/btn')
button.click()

这样获取元素之后,然后调用 click() 方法即可实现该元素的模拟点击。

屏幕拖动

可以使用 scroll() 方法模拟屏幕滚动,用法如下所示:

scroll(self, origin_el, destination_el)

可以实现从元素 origin_el 滚动至元素 destination_el。

参数:

  • original_el,被操作的元素

  • destination_el,目标元素

实例如下:

driver.scroll(el1,el2)

我们还可以使用 swipe() 模拟从 A 点滑动到 B 点,用法如下:

swipe(self, start_x, start_y, end_x, end_y, duration=None)

参数:

  • start_x,开始位置的横坐标

  • start_y,开始位置的纵坐标

  • end_x,终止位置的横坐标

  • end_y,终止位置的纵坐标

  • duration,持续时间,毫秒

实例如下:

driver.swipe(100, 100, 100, 400, 5000)

这样可以实现在 5s 由 (100, 100) 滑动到 (100, 400)。

另外可以使用 flick() 方法模拟从 A 点快速滑动到 B 点,用法如下:

flick(self, start_x, start_y, end_x, end_y)

参数:

  • start_x,开始位置的横坐标

  • start_y,开始位置的纵坐标

  • end_x,终止位置的横坐标

  • end_y,终止位置的纵坐标

实例如下:

driver.flick(100, 100, 100, 400)
拖拽

可以使用 drag_and_drop() 实现某个元素拖动到另一个目标元素上。

用法如下:

drag_and_drop(self, origin_el, destination_el)

可以实现元素 origin_el 拖拽至元素 destination_el。

参数:

  • original_el,被拖拽的元素

  • destination_el,目标元素

实例如下所示:

driver.drag_and_drop(el1, el2)
文本输入

可以使用 set_text() 方法实现文本输入,如下所示:

el = find_element_by_id('com.tencent.mm:id/cjk')
el.set_text('Hello')

我们选中一个文本框元素之后,然后调用 set_text() 方法即可实现文本输入。

动作链

与 Selenium 中的 ActionChains 类似,Appium 中的 TouchAction 可支持的方法有 tap()、press()、long_press()、release()、move_to()、wait()、cancel() 等,实例如下所示:

el = self.driver.find_element_by_accessibility_id('Animation')
action = TouchAction(self.driver)
action.tap(el).perform()

首先选中一个元素,然后利用 TouchAction 实现点击操作。

如果想要实现拖动操作,可以用如下方式:

els = self.driver.find_elements_by_class_name('listView')
a1 = TouchAction()
a1.press(els[0]).move_to(x=10, y=0).move_to(x=10, y=-75).move_to(x=10, y=-600).release()
a2 = TouchAction()
a2.press(els[1]).move_to(x=10, y=10).move_to(x=10, y=-300).move_to(x=10, y=-600).release()

利用以上 API,我们就可以完成绝大部分操作。更多的 API 操作可以参考 Appium Python API 中文版 By-HZJ · TesterHome。

5. 结语

本节中,我们主要了解了 Appium 的操作 App 的基本用法,以及常用 API 的用法。在下一节我们会用一个实例来演示 Appium 的使用方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/722730.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Docker 设置 PySpark Notebook

使用 Docker 设置 PySpark Notebook 第 1 步:拉取 Docker 镜像 首先拉取jupyter/all-spark-notebook包含 Spark 3.5.0 的镜像。 docker pull jupyter/all-spark-notebook:spark-3.5.0 第 2 步:设置您的工作区 在运行 Docker 映像之前,我们…

开源大数据集群部署(十四)Ranger集成Hbase

作者:櫰木 在hd1.dtstack.com主机上执行 在hmaster和back master上进行安装和执行 解压ranger-2.3.0-hbase-plugin [roothd1.dtstack.com ranger-plugin]# cd /root/bigdata [roothd1.dtstack.com ranger-plugin]# tar -zvxf ranger-2.3.0-hbase-plugin -C /opt配…

Unity编辑器功能Inspector快捷自动填充数据和可视化调试

我们有时候可能需要在面板增加一些引用,可能添加脚本后要手动拖动,这样如果有大量的脚本拖动也是不小的工作量 实例 例如:我的脚本需要添加一个Bone的列表,一个个拖动很麻烦。 实现脚本 我们可以用这样的脚本来实现。 public…

小程序API能力集成指南——画布API汇总(一)

RJS Canvas Canvas Canvas 实例, 在 RJS 中可通过 getCanvasById 获取。 属性 number width:画布宽度 number height:画布高度 方法 如下。 1、getContext Canvas.getContext(string contextType) RenderingContext Canvas.getContext(string c…

利用 Redis 和 Lua 实现高效的限流功能

简介 在现代系统中,限流是一种重要的机制,用于控制服务端的流量并保护系统免受恶意攻击或请求泛滥的影响。本文将介绍如何利用 Redis 和 Lua 结合实现高效的限流功能。 一、什么是限流 限流指的是对系统中的请求进行控制和调节,确保系统在…

Cluade3干货:超越GPT,模型特点分析+使用教程|2024年3月更新

就在刚刚,Claude 发布了最新的大模型 Claude3,并且一次性发布了三个模型,分别是 Claude 3 Haiku:(日本俳句 )Claude 3 Sonnet(英文十四行诗)Claude 3 Opus(古典乐作品集…

docker-compose Install rustdesk

RustDesk RustDesk 是一款开源的远程支持和远程桌面工具,它旨在为用户提供便捷的远程协助和远程访问功能。 默认情况下,hbbs 监听21115(tcp), 21116(tcp/udp), 21118(tcp),hbbr 监听21117(tcp), 21119(tcp)。务必在防火墙开启这几个端口, 请注意21116同时要开启TCP和UDP。…

streamlit初学-用streamlit实现云台控制界面

用streamlit实现云台控制界面 效果图PC上的效果手机上的效果 源码: 本文演示了,如何用streamlit做一个云台控制界面。功能包括:用户登录,事件的处理,图片的更新 版本信息: streamlit_authenticator: 下载链接streamlit : 1.31.1python: 3.11 修改点: streamlit_authenticato…

AndroidStudio安装Android模拟器AVD及遇到的问题解决

打开DeiviceManager 创建虚拟机 选个常规的1080*1920分辨率 这里就遇到一个报错: Android SDK is up to date. Running Android Emulator hypervisor driver installer [SC] ControlService 失败 1062: 服务尚未启动。 [SC] DeleteService 成功 [SC] 由于发生错误…

在线部署ubuntu20.04服务器,安装jdk、mysql、redis、nginx、minio

查看服务器版本为20.04 lsb_release -a服务器初始账号密码 sxd / 123456 首先,更改自身密码都输入123456 sudo passwd 创建最高权限root账号,密码为 123456 su root 更新源列表 sudo apt-get update 安装 openssh-server和vim,途中输入y sudo ap…

Python爬虫:设置随机 User-Agent

Python爬虫:设置随机 User-Agent 在Python中编写爬虫时,为了模拟真实用户的行为并防止被服务器识别为爬虫,通常需要设置随机的User-Agent。你可以使用fake-useragent库来实现这一功能。首先,你需要安装fake-useragent库&#xff…

通过Apple Configurator 2导出iOS ipa包

通过Apple Configurator 2导出iOS ipa包 安装Apple Configurator 2 从Mac AppStore安装Apple Configurator 2 下载ipa 准备工作: 1、 电脑已经安装了Apple Configurator 2 2、 手机已经安装了目标软件 3、 Apple 账号已经下载过目标软件 打开后连接设备&#xf…

如何快速分析OB集群日志,敏捷诊断工具obdiag分析能力实践——《OceanBase诊断系列》之四

1. 前言 obdiag是OceanBase的敏捷诊断工具。1.2版本中,obdiag支持快速收集诊断信息,但仅有收集能力是不够的,还需要有分析能力。因此在obdiag的1.3.0版本中,我们加入了OB集群的日志分析功能。用户可以一键进行集群的OB日志的分析…

Redis核心数据结构之SDS(二)

SDS与C字符串的区别 杜绝缓冲区溢出 除了获取字符串长度的复杂度高之外&#xff0c;C字符串不记录自身长度带来的另一个问题是 容易造成缓冲区溢出(buffer overflow).例如<string.h>/strcat函数可以将src字符串 中的内容拼接到dest字符串的末尾: char *strcat(char *d…

c++中多种类型sort()排序的用法(数组、结构体、pair、vector)

c中多种类型sort排序的用法 一、对数组排序1、默认排序2、自定义排序 二、对结构体进行排序三、对pair进行排序1、默认排序2、自定义排序 四、对vector进行排序1、默认排序2、去重排序3、自定义排序 一、对数组排序 1、默认排序 默认从小到大进行排序 #include <bits/std…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:拖拽控制)

设置组件是否可以响应拖拽事件。 说明&#xff1a; 从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 ArkUI框架对以下组件实现了默认的拖拽能力&#xff0c;支持对数据的拖出或拖入响应&#xff0c;开发者只需要将这些组件…

Xcode 15 适配 MonkeyDev

升级到Xcode15后,使用Xcode创建MonkeyApp后,运行会报错,本篇文章主要讲述此过程遇到的错误和解决办法。 问题1:找不到libc++.dylib文件 问题描述: Build input files cannot be found: /usr/lib/libstdc++.dylib, /usr/lib/libc++.dylib. Did you forget to declare th…

DHCP自动获取IP地址实验(华为)

思科设备参考&#xff1a;DHCP自动获取IP地址实验&#xff08;思科&#xff09; 一&#xff0c;实验目的 路由器搭载DHCP&#xff0c;让PC通过DHCP自动获取IP地址 二&#xff0c;不划分vlan--全局地址池 实验拓扑 配置命令 Router <Huawei>system-view [Huawei]ip po…

瑞_Redis_短信登录(一)

文章目录 项目介绍1 短信登录1.1 项目准备1.1.1 导入SQL1.1.2 导入后端项目1.1.3 导入前端项目 &#x1f64a; 前言&#xff1a;本文章为瑞_系列专栏之《Redis》的实战篇的短信登录章节的项目准备小节。由于博主是从B站黑马程序员的《Redis》学习其相关知识&#xff0c;所以本系…

LLM春招,搜广推,nlp(2)

Encoder和Decoder怎么交互的 decoder里面的K&#xff0c;V输入用的是encoder的输出&#xff0c;并不是共享了K, V参数&#xff0c;decoder每层的参数都是独立的。Decoder每层是有两块Attention的&#xff1a;一块是正常的Self-Attention&#xff0c;QKV的输入都来自Decoder上一…