折腾:
【未解决】Mac中用uiautomator2自动操作安卓手机浏览器实现百度搜索
期间,此处已用uiautomator2模拟了安卓手机中自带浏览器中,百度首页的百度搜索,看到了搜索结果。
接下来,就想办法看看,然后获取搜索的结果。
先去打印页面源码结构看看:
curPageXml = d.dump_hierarchy(compressed=False, pretty=False) # print("curPageXml=%s" % curPageXml) with open("baidu_search_%s_result_pageSource.xml" % searchStr, "w") as fp: fp.write(curPageXml)
输出的xml中,找不到搜索结果:
【已解决】uiautomator2中dump_hierarchy获取到的xml源码不是最新的
然后再去尝试解析内容
不过好像有2种思路:
- 从返回的页面源码xml中解析
- 从页面中直接搜索对应元素,再获取其属性值
先试试第二种:
从页面中直接搜索对应元素,再获取其属性值
不过发现,从weditor中看元素,很难直接看清,如何定位到

对应xpath是:
//*[@resource-id="results"]/android.view.View[1]/android.view.View[1]/android.view.View[1]
代码是:
d.xpath('//*[@resource-id="results"]/android.view.View[1]/android.view.View[1]/android.view.View[1]')
显得:很不够突出
再看了xml源码:

<node index="1" text="" resource-id="results" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[0,672][1080,2126]"> <node index="0" text="" resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[0,672][1080,1332]"> <node index="0" text="" resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[22,672][1061,1332]"> <node index="1" text="" resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[55,710][1025,795]"> <node index="0" text="" resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[55,710][1025,795]"> <node index="0" text="在路上on the way - 走别人没走过的路,让别人有路可走" resource-id="" class="android.widget.Button" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[55,710][1025,795]" /> </node> </node> <node index="2" text="" resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[55,809][1025,1293]"> <node index="0" text="" resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[55,809][1025,1219]"> <node index="0" text="" resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[55,809][1025,1219]"> <node index="0" text="" resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[55,809][1025,963]"> <node index="0" text="" resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[41,809][1039,963]"> <node index="0" text="crifan 4周前 (03-09) 177浏览 0评论 google 收录查询谷歌收录查询,如何让Google收录网站 – 云..." resource-id="" class="android.view.View" package="com.android.browser" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" visible-to-user="true" bounds="[57,809][1023,938]" /> </node> </node> 。。。
后,从weditor中找到对应元素了:

其中:貌似只能获取搜索结果的标题title和描述,没有url地址
去写代码看看,至少先去获取标题列表再说
目前思路是

先找到这个 results,再去找其下的
clickable=true的button

先去解析title
其中涉及到
发现等了1秒,uiautomator2服务没好
所以要先去等待页面搜索结果能找到:
d(resourceId="results").exists(timeout=10)
即可进行后续搜索。
以及:
【已解决】uiautomator2中用xpath如何查找某元素下面的某层级的子元素
接着写代码提取title
代码:
# Note: following syntax can NOT find elements # resultsSelector = d.xpath("//*[@resource-id='results']") # titleButtonSelectorList = resultsSelector.xpath("//android.widget.Button[@clickable='true']").all() # Xpath chain search can find elements titleButtonSelectorList = d.xpath("//*[@resource-id='results']//android.widget.Button[@clickable='true']").all() titleButtonNum = len(titleButtonSelectorList) print("Found %s search result:" % titleButtonNum) for curIdx, eachTitleButtonElement in enumerate(titleButtonSelectorList): curNum = curIdx + 1 print("%s [%d/%d] %s" % ("-"*20, curNum, titleButtonNum, "-"*20)) eachTitleButtonElemAttrib = eachTitleButtonElement.attrib # print("title attrib: %s" % eachTitleButtonElemAttrib) curTitle = eachTitleButtonElemAttrib["text"] print("title=%s" % curTitle)
调试效果:

以及再去:
【基本解决】uiautomator2中查找和定位安卓浏览器中百度搜索结果中描述文字和来源网站
【总结】
至此,用代码:
################################################################################ # Extract search result content ################################################################################ # Special: for fixbug of get page xml is not latest, so using following code to refresh to get latest page source xml d.service("uiautomator").stop() d.service("uiautomator").start() # time.sleep(1) # for debug # get page source xml # curPageXml = d.dump_hierarchy(compressed=False, pretty=False) # print("curPageXml=%s" % curPageXml) # with open("baidu_search_%s_result_pageSource_reloaded.xml" % searchStr, "w") as fp: # fp.write(curPageXml) d(resourceId="results").exists(timeout=10) # Note: following syntax can NOT find elements # resultsSelector = d.xpath("//*[@resource-id='results']") # titleButtonSelectorList = resultsSelector.xpath("//android.widget.Button[@clickable='true']").all() # titleButtonSelectorList = resultsSelector.xpath(".//android.widget.Button[@clickable='true']").all() # Xpath chain search can find elements titleButtonElementList = d.xpath("//*[@resource-id='results']//android.widget.Button[@clickable='true']").all() titleButtonNum = len(titleButtonElementList) print("Found %s search result title" % titleButtonNum) # descriptionElementList = d.xpath("//*[@resource-id='results']/android.view.View[1]/android.view.View[1]/android.view.View[2]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]").all() descriptionElementList = d.xpath("//*[@resource-id='results']/android.view.View/android.view.View[1]/android.view.View[2]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]/android.view.View[1]").all() descriptionNum = len(descriptionElementList) print("Found %s description" % descriptionNum) # # sourceWebsiteElementList = d.xpath('//*[@resource-id="results"]/android.view.View/android.view.View[1]/android.view.View[2]/android.view.View[1]').all() # sourceWebsiteElementList = d.xpath('//*[@resource-id="results"]/android.view.View/android.view.View[1]/android.view.View[2]/android.view.View[2]').all() # sourceWebsiteNum = len(sourceWebsiteElementList) # print("Found %s source website" % sourceWebsiteNum) for curIdx, eachTitleButtonElement in enumerate(titleButtonElementList): curNum = curIdx + 1 print("%s [%d/%d] %s" % ("-"*20, curNum, titleButtonNum, "-"*20)) # eachTitleButtonElemAttrib = eachTitleButtonElement.attrib # print("title attrib: %s" % eachTitleButtonElemAttrib) # curTitle = eachTitleButtonElemAttrib["text"] curTitle = eachTitleButtonElement.text print("title=%s" % curTitle) curDescriptionElem = descriptionElementList[curIdx] curDescription = curDescriptionElem.text print("description=%s" % curDescription) # curSourceWebsiteElem = sourceWebsiteElementList[curIdx] # curSourceWebsite = curSourceWebsiteElem.text # print("curSourceWebsite=%s" % curSourceWebsite)
实现了:
先去用重启uiautomator2的服务,实现了规避uiautomator2的bug:页面内容变化,获取不到最新内容。
使得可以获取到页面最新内容。
然后先后获取了
title
description
的内容,并打印输出
输出内容是:
[D 210409 22:49:03 __init__:764] restart-uiautomator since "UiAutomation not connected" [D 210409 22:49:03 __init__:817] Device: Redmi, orga4pmzee4ts47t [D 210409 22:49:03 __init__:823] stop app: com.github.uiautomator [D 210409 22:49:03 __init__:827] kill process(ps): uiautomator [D 210409 22:49:04 __init__:840] uiautomator-v2 is starting ... left: 40.0s [D 210409 22:49:05 __init__:840] uiautomator-v2 is starting ... left: 39.0s [D 210409 22:49:06 __init__:840] uiautomator-v2 is starting ... left: 38.0s [D 210409 22:49:07 __init__:840] uiautomator-v2 is starting ... left: 36.9s [D 210409 22:49:08 __init__:840] uiautomator-v2 is starting ... left: 35.9s [D 210409 22:49:09 __init__:840] uiautomator-v2 is starting ... left: 34.9s [D 210409 22:49:10 __init__:840] uiautomator-v2 is starting ... left: 33.8s [I 210409 22:49:10 __init__:784] uiautomator back to normal Found 3 search result title Found 3 description -------------------- [1/3] -------------------- title=在路上on the way - 走别人没走过的路,让别人有路可走 description=crifan 4周前 (03-09) 177浏览 0评论 google 收录查询谷歌收录查询,如何让Google收录网站 – 云... -------------------- [2/3] -------------------- title=crifan简介 - crifan的专栏 - CSDN博客 - crifan description=2020年2月15日crifan简介 各种计算机语言简介和总结 v1.0 08-03 本文主要介绍了各种计算机语言的分类和关系,以及记录了笔者对其中部分语言,如Word VBA,Excel... -------------------- [3/3] -------------------- title=crifan - Bing 词典 - 必应 description=crifan网络目录;下午;我个人 网络释义 1. 目录 如何实现Linux下的U盘驱动 v0.4 -... ... Specification 规范 crifan 目录 Mass Storage ...
效果:
