使用appium采集国家药监局手机端信息
一、环境安装
1.概述
appium是一个开源的自动化测试工具,类似selenium,支持IOS与安卓平台的原生的,基于移动浏览器的,混合的应用
可以用代码驱动Appium去驱动移动端的程序
架构:
- Node.js编写的HTTP server,创建并管理多个文本driver session来和不同的平台交互
环境:
Node.js——可以开发服务端程序(https://nodejs.org/zh-cn/) - JAVA JDK——JAVA环境(https://www.oracle.com/java/technologies/javase-jdk16-downloads.html)
- Android SDK——Android专属的软件开发工具包(https://www.androiddevtools.cn/)
- Appium(https://github.com/appium/appium-desktop/releases/tag/v1.21.0)
2.JavaJDK/Android SDK环境配置
Java JDK:
下载:

安装:
下一步下一步即可,路径可修改
环境变量:
添加JAVA_HOME环境变量,再将JAVA_HOME的bin目录添加至Path



Android SDK:
下载:


安装:
以下四个工具必选


环境变量:
和Android SDK的环境添加是相似的,最后在Path中添加platform-tools和tools目录



测试是否安装成功:



.
二、测试步骤
1.移动端
手机:需要开启USB调试模式
模拟器:逍遥模拟器/夜神模拟器/雷电模拟器
可能出现的报错:adb server version(36) doesn’t match this client(41)
原因:手机模拟器与Android SDK的adb工具不匹配,需要把Android SDK的adb.exe复制,放入模拟机的安装目录中,替换nox_adb.exe。
2.CMD命令
adb version 查看版本
adb devices 查看已连接的设备,如果无设备信息,尝试上一步替换adb.exe
C:\Users\Administrator>adb devices
List of devices attached
127.0.0.1:21503 device
3.调试
需要编写自动化程序,首先就需要能够定位元素
使用appium
Desired Capabilities:发送给Appium服务器的键值对集合(可以理解成发送HTTP请求)
Saved Capability sets:可以保存键值对配置信息,方便下次打开
{
"platformName": "Android", #操作系统类型
"platformVersion": "7", #操作系统版本
"deviceName": "127.0.0.1:21513", #连接的手机信息
"appPackage": "com.hxzk.android.hxzksyjg_xj", #应用的包名
"appActivity": ".ui.activity.MainActivity", #activity
"udid": '127.0.0.1:21513' #指定哪一台设备(如果仅连接一台设备,可不带此参数)
}

"appPackage"和"appActivity"通过以下指令查看,在这之前关闭模拟器其他app,只打开需要测试的app:
C:\Users\Administrator>adb shell
MI 9:/ # dumpsys activity | grep mFocusedActivity
mFocusedActivity: ActivityRecord{bdbddca u0 com.hxzk.android.hxzksyjg_xj/.ui.activity.QueryActivity t294}
MI 9:/ #
可以拿到当前运行手机应用的package和activity
"appPackage": "com.hxzk.android.hxzksyjg_xj", #应用的包名
"appActivity": ".ui.activity.MainActivity", #activity
start session


滑动标错了,是左边的 ...

三、python操作
pip install Appium-Python-Client
1.配置信息:
from appium import webdriver #这一项是appium特有的,其余和selenium类似
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from industry_templete import RFPDupeFilter, ItemToPG
##################################
class Appium_yjj():
def __init__(self, tb_name="industry_info.国家药监局_国产药品"):
'''appium配置信息'''
#设置表名
self.tb_name = tb_name
# 配置要控制的设备和里面的应用键值对信息
self.caps={
"platformName": "Android",
"platformVersion": "7",
"deviceName": "127.0.0.1:21503",
"appPackage": "com.hxzk.android.hxzksyjg_xj",
"appActivity": ".ui.activity.MainActivity",
"udid": '127.0.0.1:21513'
}
# 驱动对象,Appium,ip地址和端口
self.driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', self.caps)
# 显示等待
self.wait = WebDriverWait(self.driver, 20)
2.点击确认:
通过appium启动session,确认点击项的id或xpath

移植到python中来:
def skip(self):
'''权限申请、隐私'''
# 关闭权限申请,如果有
try:
close_1 = self.driver.find_element_by_id("com.hxzk.android.hxzksyjg_xj:id/dialog_confirm_btn")
except:
close_1 = None
if close_1:
close_1.click()
# 关闭隐私确认,如果有
try:
close_2 = self.driver.find_element_by_id("com.hxzk.android.hxzksyjg_xj:id/dialog_confirm_btn")
except:
close_2 = None
if close_2:
close_2.click()
3.列表页解析
- 点击操作和上一步是类似的,区别在wait.上一步操作不需要wait,没有就没有,而这里的“查询”,“国产药品”,是必须点击的按钮,"值得"等待。
def select_dir(self,num):
'''选择条目'''
#点击查询
self.wait.until(EC.element_to_be_clickable((By.ID, 'com.hxzk.android.hxzksyjg_xj:id/tab_query'))).click()
#sleep(3)
#选择一级目录:国产药品,点击
self.wait.until(EC.element_to_be_clickable((By.ID, 'com.hxzk.android.hxzksyjg_xj:id/tv_item_queryitem'))).click()
sleep(3)
#选择二级目录:药品名称,点击进入
for i in range(num):
#二级目录去重,已采集则不点击进入
xpath = '/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.LinearLayout[2]/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.widget.LinearLayout[{}]/android.widget.TextView'
first = self.driver.find_element_by_xpath(xpath.format(1))
while True:
def all_page():
'''整页筛选去重,12个标签如果都重复则整个翻页,否则逐条'''
for p in range(1, 12):
all_text = self.driver.find_element_by_xpath(xpath.format(p))
all_text = all_text.get_attribute('text')
rf_filter = RFPDupeFilter(tb_name=self.tb_name)
not_repet = rf_filter.add_title(all_text)
if p==11 and not not_repet:
last = self.driver.find_element_by_xpath(xpath.format(p))
self.driver.swipe(331, 377, 331, 278, 0)
return False, p
elif not_repet:
return True, p
else:
pass
a, b = all_page()
if a:
break
title = self.driver.find_element_by_xpath(xpath.format(b))
title_text = title.get_attribute('text')
title.click()
#解析字段
try:
self.parse2()
except Exception as e:
logger.info(title_text)
logger.info(e)
sleep(0.3)
#返回上一级
self.driver.back()
sleep(0.3)
#滑动一格
self.driver.swipe(331, 377, 331, 278, 0)
四、动作链录制
appium可录制动作链,如滑动操作(不仅限于滑动),可按如下步骤录制,即可得到动作链代码:
-
TouchAction(driver).press(x=322, y=1148).move_to(x=322, y=777).release().perform()




五、appium解析

如上图所示,appium获取的左边,为当前页面的xml代码,右边为解析代码
右侧解析代码分为两部分,Find By 和 Attribute
1.Find By
find by 即为定位方式,从python代码可以粗略观察:

故,可根据实际情况进行选择,一般来说常用xpath,id,class_name,当然得看该元素有什么定位方式,xpath一般很长。
title = self.driver.find_element_by_xpath('/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.LinearLayout[2]/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.widget.LinearLayout[1]/android.widget.TextView')
close_2 = self.driver.find_element_by_id("com.hxzk.android.hxzksyjg_xj:id/dialog_confirm_btn")
2.Attribute
通过定位后的element,再通过get_attribute()方法,即可获取该键值对信息

title_text = title.get_attribute('text')

浙公网安备 33010602011771号