1. 程式人生 > 其它 >使用appium採集國家藥監局手機端資訊

使用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')