使用appium采集国家药监局手机端信息

一、环境安装

1.概述

appium是一个开源的自动化测试工具,类似selenium,支持IOS与安卓平台的原生的,基于移动浏览器的,混合的应用
可以用代码驱动Appium去驱动移动端的程序
架构:

  1. Node.js编写的HTTP server,创建并管理多个文本driver session来和不同的平台交互
    环境:
    Node.js——可以开发服务端程序(https://nodejs.org/zh-cn/)
  2. JAVA JDK——JAVA环境(https://www.oracle.com/java/technologies/javase-jdk16-downloads.html)
  3. Android SDK——Android专属的软件开发工具包(https://www.androiddevtools.cn/)
  4. 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')
posted @ 2021-10-09 15:37  Lemon_guess  阅读(637)  评论(0)    收藏  举报