跳转至

内嵌网页自动化

大家在我的百度网盘中,下载一款本文教学用的App: wv.apk 。安装到你的手机上。

链接:https://pan.baidu.com/s/19C9fGmoXne8DgfXhrTB2TQ

提取码:kgwb

内嵌网页的混合App

很多移动App 都是 Hybrid(混合) 应用。

混合应用主要是指 它的一部分是原生界面和代码,而另一部分是内嵌网页 。

现在基本上需要打开网页浏览的app都是 混合app,比如微信、支付宝等。

微信的sms界面是原生代码实现的,而打开某个朋友圈,或者别人发来的的链接部分则是 web部分。

App中的内嵌的展示网页内容的模块,我们称之为 webview

我们自动化的时候如果需要操作内嵌webview中的网页内容,该怎么做呢?

修改编译App

前面讲过,Appium 的原则是不修改应用本身,就可以对应用进行自动化。

但是,这里要违背一下 appium的原则。

要对App内嵌网页进行自动化,首先要请 开发人员修改源代码,保证对webview 对象加入setWebContentsDebuggingEnabled 的调用。

安卓应用,修改java代码,如下所示:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // 找到 webview 对象
    WebView myWebView = (WebView) findViewById(R.id.jcywebview);
    // 添加打开 webview内容debug开关
    myWebView.setWebContentsDebuggingEnabled(true);
};

然后,编译出一个支持自动化的版本。

否则无法对webview中的内容进行自动化操作。

用Chrome查看App内嵌网页

编译产生了 支持自动化 的App,接下来我们就可以安装到手机上,进行内嵌网页的自动化了。

App内嵌网页的自动化,也是使用 Selenium。 和电脑上自动化Chrome浏览器本质是一样的。

因为 安卓手机内嵌webview 基本上就是 手机版的 Chrome浏览器 。

如果大家没有学习过 Selenium自动化网页,先点击这里,学习一下

但是,因为网页内容在手机中呈现,不能像电脑浏览器那样,打开开发者工具,查看元素内容。

那我们怎么查看元素的属性特征,来定位选择元素呢?

这里面要分两种情况:

webview不依赖App环境

这种情况:App的内嵌 webview 和 native部分没有交互 的。

webview 只是打开一个固定的网址(一般是该公司的手机网址)而已。

这种情况,我们要查看webview内容非常简单。

因为其实和手机没有关系。

直接用Chrome浏览器F12里面的手机模式打开对应的网页,即可。

如下所示

image

webview依赖App环境

这种情况:App的内嵌 webview 和 native部分有交互 的, 它必须在app中才能运行。

这种情况,我们直接打开网页url 运行不起来(或者说运行结果和在app中不同), 甚至,我们根本就不知道网页的url。怎么办?

这时候,我们可以通过Chrome浏览器 的远程调试功能

注意:这种方法,一定要你的网络环境能访问谷歌!!!

怎么确保能连接上 不存在的网站 谷歌 ?你自己去了解哦。你懂的:)

下文假设你的网络环境是可以连接谷歌的。


首先,确保我们的应用运行,

然后,打开chrome浏览器,地址栏输入 chrome://inspect ,出现如下所示界面

image

注意:上图红框内是webview版本。有的手机比较老 ,webview版本也比较老的,就会有问题, 尽量使用新手机进行自动化。

点击 inspect即可查看,如下图所示

image


具体操作,大家还可以参考这里官方文档

自动化代码

请大家运行前文下载的 wvtest App,界面如下

image

这个App内置了一个 webview,这个webview 缺省就是打开 百度的网址,和native代码没有交互, 完全可以用 浏览器直接以手机模式查看 网页元素。

我们假设要做的就是 在这个应用,进入webview里面的百度,搜索关键字 白月黑羽 , 我们看看代码怎么实现。

前面已经说过,webview自动化代码 和 电脑上浏览器的自动化 基本差不多。

但是有一点要注意:

手机App中 webview里面的网页内容, 是在一个独立于应用native部分的环境里面的。

而缺省情况下,find_element_by_xxx 这样的代码选择元素, Appium 只会在 native 部分的界面寻找元素。 肯定找不到元素。

Appium 把一个界面环境 称之为一个 context

native 部分的 context 名字为 NATIVE_APP , 而webview部分的context则为 WEBVIEW_XXX (XXX部分是 应用的 app package名)

我们怎么查看当前有哪些context呢?

我们的代码通过 driver 对象的 contexts 属性来获取,也就是 driver.contexts

driver 对象的 current_context 属性对应当前的 context 对象。

大家可以打开自动化代码, 添加如下内容

print(driver.contexts)

执行一下,解释一下,可以发现结果如下。

[
'NATIVE_APP', 
'WEBVIEW_com.example.jcy.wvtest'
]

我们的应用中, webview 的 context 就是 WEBVIEW_com.example.jcy.wvtest。

而当前的context 是'NATIVE_APP', 所以当前的自动操作都是在native context里面的进行的。

要对该webview里面的网页内容进行自动化操作,必须先将当前的context切换为 webview的context,怎么切呢?

使用 switch_to.context

driver.switch_to.context('WEBVIEW_com.example.jcy.wvtest')

好,现在我们修改代码,如下所示

from selenium.webdriver.common.by import By

driver.switch_to.context('WEBVIEW_com.example.jcy.wvtest')

driver.find_element(By.ID, 'index-kw').send_keys('白月黑羽')

driver.find_element(By.ID, 'index-bn').click()

执行一下,发现可以自动化了。


那么怎么切换回 native app 进行自动化呢?

当然是 继续使用 switch_to.context ,如下

driver.switch_to.context('NATIVE_APP')


大家可以查看一下,app界面上 B站QQ 的 id 分别为:navigation_bili 和 navigation_qq

如果我们想再切换回native部分,分别点击底部导航栏 B站 按钮, 和 QQ 按钮,就可以修改代码如下

from selenium.webdriver.common.by import By

driver.switch_to.context('NATIVE_APP')
driver.find_element(By.ID, 'navigation_bili').click()
time.sleep(2)
driver.find_element(By.ID, 'navigation_qq').click()

注意点

现在新版本的appium ,对webview这种类型的自动化,desired_caps需要加上

'chromeOptions':{'w3c':False}

如下

desired_caps = {
  'platformName': 'Android', 
  'platformVersion': '10', 
  'deviceName': 'xxx', 
  'appPackage': 'com.example.jcy.wvtest',
  'appActivity': '.MainActivity', 
  'unicodeKeyboard': True, 
  'resetKeyboard': True, 
  'noReset': True,      
  'newCommandTimeout': 8000, 
  'automationName' : 'UiAutomator2',

   # 加上这行
  'chromeOptions':{'w3c':False} 
}

否则,可能出现webview里面find_element 选择元素,出现 invalid locator 的问题

手机浏览器网页自动化

有的公司开发了手机版网站,直接用手机浏览器打开的,比如,xiaomi 京东等。

并不是 手机App

这种手机网页,我们怎么 程序自动化呢?

首先,必须在手机上安装谷歌浏览器。

以百度为例,

首先启动 Appium Desktop。

然后,我们的自动化程序代码如下所示:

from appium import webdriver
from selenium.webdriver.common.by import By
from appium.options.android import UiAutomator2Options

desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '14'
desired_caps['deviceName'] = 'test'
desired_caps['browserName'] = 'Chrome'
desired_caps['newCommandTimeout'] = 6000

driver = webdriver.Remote('http://localhost:4723/wd/hub', 
  options=UiAutomator2Options().load_capabilities(desired_caps))


driver.implicitly_wait(10)
try:

    driver.get('http://www.baidu.com')

    driver.find_element(By.ID, 'index-kw').send_keys('白月黑羽')

    driver.find_element(By.ID, 'index-bn').click()

except:
    print(traceback.format_exc())

webview、驱动 版本配套

问题

大家知道,基于 appium 的 安卓应用自动化时,如果要自动化的app 里面 内嵌网页内容, appium会使用 基于selenium的自动化机制。

安卓app里面的网页,基本上都是使用手机系统上的webview 去显示的。

安卓 webview 可以看成是 手机上的 chrome 浏览器精简版。

我们知道 selenium 自动化 chrome浏览器,需要使用 相应版本的浏览器驱动。

chromedriver 2.46 以后的版本 和 匹配的 Chrome浏览器 版本号保持一致,

而在这之前的对应关系如下,参考的是这个链接

chromedriver    chrome
2.46            71-73
2.45            70-72
2.44            69-71
2.43            69-71
2.42            68-70
2.41            67-69
2.40            66-68
2.39            66-68
2.38            65-67
2.37            64-66
2.36            63-65
2.35            62-64
2.34            61-63
2.33            60-62
---------------------
2.28            57+
2.25            54+
2.24            53+
2.22            51+
2.19            44+
2.15            42+


appium desktop 里面内置了 用于 webview 自动化的 chromedriver。 比较新的appium server, 内置chromedriver也是比较新的。

而我自动化的手机如果比较老, 那么手机里面的 webview 版本也会比较老,这是就会出现和新版本的appium desktop里面的 chromedriver 不匹配的问题。 自动化程序运行时, appium 会报类似如下错误

default

上面的错误,就是说你的手机webview 版本是 58, 而你的 appium desktop里面的 chromedriver 版本又是比较新的, 对这个老版本的webview 就不匹配了。


解决方案

这时,我们可以根据配套表,

default

下载对应的老版本的chromedriver 2.31 。

然后设置 appium desktop 使用 这个版本的 chromedriver。

如下图所示,先点击 Advanced 设置项

default

然后在 下图位置 写上你的 老版本的 chromedriver 的路径

default

您需要高效学习,找工作? 点击咨询 报名实战班

点击查看学员就业情况