python-appium自动化操作微信

appium介绍

Appium是一个免费分发的开源移动应用UI测试框架。

Appium的设计理念

Appium是使用Node.js平台编写的“HTTP Server”,并使用Webdriver JSON线协议驱动iOS和Android会话。 因此,在初始化Appium Server之前,必须在系统上预先安装Node.js 当Appium被下载并安装时,在我们的机器上设置一个暴露REST API的服务器
Appium支持任何支持HTTP请求的语言,如Java,JavaScript与Node.js,Python,Ruby,PHP,Perl等。

编写Appium测试的基本要求

驱动程序客户端:Appium驱动移动应用程序,就像它是用户一样。 使用客户端库编写您的Appium测试,其中包含您的测试步骤,并通过HTTP发送到Appium服务器。
应用会话:您必须首先初始化一个会话,因为这样的测试会在会话中进行。 一旦自动化完成一个会话,它可以结束并等待另一个会话
所需功能:要初始化Appium会话,您需要定义名为“所需功能”的某些参数,如PlatformName,PlatformVersion,设备名称等。 它指定了从Appium服务器需要的自动化类型。
驱动程序命令:您可以使用大型和表达式的命令词汇编写测试步骤。

使用Appium可能遇到的错误

错误1:需要以下所需的功能,但不提供:设备名称,platformName
错误2:找不到adb。请使用Android SDK根目录路径设置ANDROID_HOME环境变量
错误3:openqa.selenium.SessionNotCreatedException:无法创建新的会话
错误4:如何在移动应用程序中查找DOM元素或XPath?

区分Appium和Selenium

Selenium: Selenium 是一个开源(免费)自动化测试框架,用于跨多个浏览器和平台验证 Web 应用程序。Selenium 测试脚本可以用多种编程语言编写,包括 Java、C#、Python 等。

以下是 Appium 和 Selenium 之间的区别:-

基于使用:

  • Appium - Appium 是一种流行的自动化测试开源软件,尤其是在原生应用程序(如 Android 和 iOS 应用程序)中。它还可以用于在 Android 和 iOS 环境中运行的混合应用程序中。这种类型的自动化测试可确保一旦应用程序投入生产,任何特定补丁安装都不会出现系统性问题。它确保了完整的集成测试,并避免了测试人员的大量体力劳动。通过使用 Appium,用户可以轻松避免每次手动测试整个应用程序的每个功能。
  • Selenium - Selenium 是一种通用的自动化测试工具,专为任何类型的 Web 应用程序构建。它兼容当前所有流行的浏览器和操作系统,如 Windows、Linux 和 MACOS。

基于设计:

  • Appium - Appium 主要用作 HTTP 服务器,因为它将处理任何类型的移动应用程序。但是,它主要是在 node JS 中遵循或开发相同的,而不是使用标准的 Java 或 JS 代码。因此,想要在任何类型的移动应用程序中使用 Appium 进行自动化测试的开发人员必须先在他们的系统上安装 Node JS,然后才能使用 Appium 工具。
  • Selenium - Selenium 主要用于维护 Web 应用程序或网页上的自动化逻辑。它的创建方式使其可以通过使用浏览器活动快速轻松地与应用程序交互。

1.准备工作

java-jdk安装(appium启动必须要求安装Java)

appium安装

adb安装

appium 模块Appium-Python-Client安装

2.各个应用安装说明

java-jdk

这个安装,需要注意环境变量的配置

配置jdk,新建环境变量(系统变量) JAVA_HOME,如图所示:

 

系统变量->找到 Path 变量->编辑->在变量值的末尾添加;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin

 

如果在你下载的文件里面找不到jre/bin的文件,即下面这个目录,一定要以管理员模式打开cmd,进入java的jdk安装目录,输入

bin\jlink.exe --module-path jmods --add-modules java.desktop --output jre  回车即可。

 

 检验方式

输入java -version,查看版本。

 

参考链接:https://zhuanlan.zhihu.com/p/360519888

 

Appium

是一个开源工具,用于自动化 iOS 手机、 Android 手机和 Windows 桌面平台上的原生、移动 Web 和混合应用。连接手机,启动安装后界面如下

下载链接:https://appium.io/

 

adb安装

这个目的是为了下发手机相关命令,下载后注意手动去配置环境变量。

下载链接:https://developer.android.google.cn/studio?hl=zh-cn

 

Appium-Python-Client

这个强烈建议不要下载最新版本,后续自动化测试,会导致和appium某些功能不适配,建议下载Appium-Python-Client版本在1.3.0或1.3.0以下。

(过程中可能会出现Method has not yet been implemented的报错,此错误是因为appium sever的版本和Appium-Python-Client  的版本不一致)

下载链接:http://appium.io/downloads.html

 

3.appium连接手机配置

我的p40pro手机,配置如下:

 

启动后效果:

 

 

 python启动,基本参数配置如下

from appium import webdriver
from selenium.webdriver.common.by import By

desired_caps = {
    "platformName": "Android",  # 操作系统
    "deviceName": "UQG5T20610006585",  # 设备 ID adb devices
    "platformVersion": "10",  # 设备版本号
    "appPackage": "com.tencent.mm",  # app 包名
    "appActivity": "com.tencent.mm.ui.LauncherUI",  # app 启动时主 Activity
    'noReset': True,  # 是否保留 session 信息,可以避免重新登录
    'autoLaunch Appium': True,
    'automationName': 'UiAutomator1',
    'unicodeKeyboard': True,  # 使用 unicodeKeyboard 的编码方式来发送字符串
    'resetKeyboard': False  # 将键盘给隐藏起来
}
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
print("微信启动")

这里需要注意其中的automationName这两个参数,如果这个参数报错,那么可能是UiAutomator2,以报错说明为准

 

以下是参考网上,微信对删除自己的人的清除操作的代码,有一下几个注意点:

1. find_element_by_id方法的废弃,现在统一为了find_element

2.手机上滑,坐标系的取值,即driver.swipe(x1, y1, x1, y2, duration=500)方法,y2与y1之间尽量差距小一点,滑动点小一点,这样获取微信好友不容易漏掉

3.代码中所有的定位元素id参数修改,如driver.find_elements(By.ID, 'com.tencent.mm:id/hga')中的com.tencent.mm:id/hga。

微信版本变化,它的id值可能都会变化。我拿过来这段代码,当中所有的定位元素基本都做了修改

4.微信好友名称的特殊化处理,有的微信名称里面,有花花草草猫猫狗狗,特殊表情符号这些。虽然都能获取到,但是逐个取值,搜索栏搜索定位过程可能导致搜索不到最终报错

以下是代码,对下面代码基本吃透,appium算是上手了

import time
from appium import webdriver
from selenium.webdriver.common.by import By


# 判断元素是否存在
def is_element_exist(element, timeout=3):
    count = 0
    while count < timeout:
        souce = driver.page_source
        if element in souce:
            return True
        else:
            count += 1
            time.sleep(1)
    return False


desired_caps = {
    "platformName": "Android",  # 操作系统
    "deviceName": "UQG5T20610006585",  # 设备 ID adb devices
    "platformVersion": "10",  # 设备版本号
    "appPackage": "com.tencent.mm",  # app 包名
    "appActivity": "com.tencent.mm.ui.LauncherUI",  # app 启动时主 Activity
    'noReset': True,  # 是否保留 session 信息,可以避免重新登录
    'autoLaunch Appium': True,
    'automationName': 'UiAutomator1',
    'unicodeKeyboard': True,  # 使用 unicodeKeyboard 的编码方式来发送字符串
    'resetKeyboard': False  # 将键盘给隐藏起来
}
driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
print("微信启动")


# 上拉方法
def swipe_up(distance):  # distance为滑动距离,time为滑动时间
    size = driver.get_window_size()
    # print(size)
    x1 = 0.5 * size['width']
    y1 = 0.8 * size['height']
    y2 = (0.8 - distance) * size['height']
    driver.swipe(x1, y1, x1, y2, duration=500)


    # 获取通讯录列表
def get_address_list(flag):
    if flag == True:
        driver.find_elements(By.ID, 'com.tencent.mm:id/f2i')[1].click()
        # 上滑  时间越短,划得屏幕越大
        swipe_up(0.2)
    else:
        swipe_up(0.21)
    # 获取昵称(备注)
    address_list = driver.find_elements(By.ID, 'com.tencent.mm:id/hga')
    remarks = []
    for address in address_list:
        remark = address.get_attribute("text")
        # 白名单
        if remark != '个人微信名字' and ("微信团队" not in remark) and ("文件传输助手" not in remark):
            remarks.append(remark)
    return remarks


# 判断是否被删
def is_delete(remark, count):
    if count == "1":
        time.sleep(0.2)
        print('点击微信搜索框')
        driver.find_element(By.ID, 'com.tencent.mm:id/gss').click()
    time.sleep(0.1)
    print('在搜索框输入搜索信息')
    driver.find_element(By.ID, 'com.tencent.mm:id/cd6').send_keys(remark)
    time.sleep(0.1)
    print('点击搜索到的好友')
    driver.find_element(By.ID, 'com.tencent.mm:id/kpx').click()
    time.sleep(0.1)

    print('功能按钮展开')
    driver.find_element(By.ID, 'com.tencent.mm:id/b3q').click()
    time.sleep(0.1)

    print('点击转账按钮')
    driver.find_elements(By.ID, 'com.tencent.mm:id/ve')[5].click()
    time.sleep(0.1)

    print('跳转,开始转钱')
    driver.find_element(By.ID, 'com.tencent.mm:id/ffn').click()
    time.sleep(0.1)
    print('确认')
    driver.find_element(By.ID, 'com.tencent.mm:id/ffw').click()
    time.sleep(0.1)
    # 判断是否被删
    is_exist = is_element_exist('com.tencent.mm:id/guv')
    if is_exist is True:
        return remark
    else:
        return False


# 返回搜索框
def search_back():
    time.sleep(0.1)
    driver.find_element(By.ID, 'com.tencent.mm:id/fz').click()
    time.sleep(0.1)
    driver.find_element(By.ID, 'com.tencent.mm:id/fz').click()
    time.sleep(0.1)
    # 清除搜索框,输入下一个
    driver.find_element(By.ID, 'com.tencent.mm:id/k1h').click()


# 删除把自己删除的人
def del_person(nicks):
    print('点击微信搜索框')
    driver.find_element(By.ID, 'com.tencent.mm:id/gss').click()
    for inx, val in enumerate(nicks):
        time.sleep(0.5)
        if inx == 0:
            print('在搜索框输入搜索信息')
            driver.find_element(By.ID, 'com.tencent.mm:id/cd6').send_keys(val)
        else:
            time.sleep(1)
            print('点击微信搜索框')
            driver.find_element(By.ID, 'com.tencent.mm:id/gss').click()
            print('在搜索框输入搜索信息')
            time.sleep(0.5)
            driver.find_element(By.ID, 'com.tencent.mm:id/cd6').send_keys(val)
        time.sleep(0.5)
        print('点击搜索到的人')
        driver.find_element(By.ID, 'com.tencent.mm:id/kpx').click()
        time.sleep(0.5)
        print('点击聊天对话框右上角...')
        driver.find_element(By.ID, 'com.tencent.mm:id/en').click()
        time.sleep(1)
        print('点击头像')
        driver.find_element(By.ID, 'com.tencent.mm:id/iwj').click()
        time.sleep(1)
        print('点击联系人右上角...')
        driver.find_element(By.ID, 'com.tencent.mm:id/en').click()
        time.sleep(1)
        print('点击删除按钮')
        driver.find_element(By.ID, 'com.tencent.mm:id/khu').click()
        time.sleep(1)
        print('点击弹出框中的删除')
        driver.find_element(By.ID, 'com.tencent.mm:id/gv3').click()


if __name__ == '__main__':
    remarks = []
    driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)
    # 打开微信需要时间
    time.sleep(5)
    remarks1 = get_address_list(True)
    remarks.extend(remarks1)
    while True:
        # 是否到了通讯录末尾
        is_end = is_element_exist('com.tencent.mm:id/bml')
        # time.sleep(0.2)
        remarks2 = get_address_list(False)
        remarks.extend(remarks2)
        if is_end == True:
            break
    remarks = set(remarks)
    print("通讯录昵称列表:", remarks)
    print("好友数目:", len(remarks))
    time.sleep(1)
    dels = []
    for inx, val in enumerate(remarks):
        rt = ""
        if inx == 0:
            rt = is_delete(val, "1")
        else:
            rt = is_delete(val, "")
        if rt is False:
            # 返回搜索框
            driver.keyevent(4)
            search_back()
        # 被删除
        else:
            dels.append(rt)
            time.sleep(0.1)
            driver.find_element(By.ID, 'com.tencent.mm:id/gv3').click()
            search_back()
    print("删除我的人:", dels)
    # 删除删了自己的人
    del_person(dels)

 

posted @ 2022-03-27 17:27  -Learning-  阅读(1641)  评论(1编辑  收藏  举报