欧美vvv,亚洲第一成人在线,亚洲成人欧美日韩在线观看,日本猛少妇猛色XXXXX猛叫

新聞資訊

    很早以前,我用uiautomator+java實踐過Android APP自動化測試,不過今天要提的不是uiautomator,而是uiautomator2。聽起來uiautomator2像是uiautomator的升級版,但是這兩款框架僅僅是名字上比較相似,實際上沒有任何關聯。

    一、uiautomator/uiautomator2的前生今世

    項目地址:https://github.com/openatx/uiautomator2

    1.官方文檔介紹

    2.梳理一下脈絡

    • 先有的谷歌uiautomator,但是只支持java;
    • 后來一個名為hexiaocong的開發者基于uiautomator封裝了python版本,支持python代碼運行;
    • 而受其啟發,uiautomator2作者開發了uiautomator2。所以它們的誕生順序應該是:uiautomator(谷歌版)-->uiautomator(python版)-->uiautomator2

    3.三款框架對比

    框架

    支持語言

    特點

    uiautomator

    java

    谷歌開源,僅支持Android

    xiaocong/uiautomator

    python

    開源,僅支持Android

    uiautomator2

    python

    開源,僅支持Android

    二、uiautomator2簡介

    1.項目組成

    • uiautomator-server:主服務
    • minicap:實現實時屏幕投屏,以及實時截圖
    • minitouch:用于精確實時控制設備
    • atx-agent:運行在設備上的駐守程序,go開發,用于保活設備上相關的服務
    • weditor:類似于uiautomatorviewer,專門為本項目開發的輔助編輯器

    2.工作原理

    1)各部分職責

    • Python:編寫腳本,向移動設備發起http請求;
    • 移動設備:運行了封裝了uiautomator2的http服務,解析python腳本發起的請求,并轉化成uiautomator2可識別的代碼;

    2)運行過程

    1. 移動設備上運行atx-agent守護進程,隨后atx-agent啟動uiautomator2服務,默認7912端口進行監聽;
    2. 在PC上編寫python腳本并執行(相當于發送 HTTP 請求到移動設備的 server 端);
    3. 移動設備通過 WIFI 或 USB 接收到 PC 上發來的 HTTP 請求,執行指定的操作,從而操作移動設備;

    三、環境搭建

    1.安裝uiautomator2

    pip install uiautomator2
    pip install -U weditor  # 安裝weditor

    2.初始化設備

    python -m uiautomator2 init

    初始化成功會出現如下提示

    當PC或Linux服務器連接了多臺adb device的情況下,“python -m uiautomator2 init”默認初始化的是所有設備,若指定設備初始化,則需使用“--serial”參數:

    python -m uiautomator2 init --serial $SERIAL  # $SERIAL為手機序列號,可通過adb devices查看

    3.init時都干了啥?

    執行“python -m uiautomator2 init”命令,會自動往手機上安裝一堆東西:

    • app-uiautomator.apk
    • app-uiautomator-test.apk
    • atx-agent
    • minicap
    • minitouch

    更多信息詳見:https://github.com/openatx/uiautomator2/wiki/Manual-Init

    四、基礎操作

    1.連接設備

    uiautomator2提供了3種連接方式

    1)通過WiFi連接

    import uiautomator2 as u2
    
    d=u2.connect('10.0.0.1') # alias for u2.connect_wifi('10.0.0.1')
    print(d.info)

    2)通過USB連接

    import uiautomator2 as u2
    
    d=u2.connect('123456f') # alias for u2.connect_usb('123456f')
    print(d.info)

    3)通過ADB WiFi連接

    import uiautomator2 as u2
    
    d=u2.connect_adb_wifi("10.0.0.1:5555")
    
    # 等同于
    # + Shell: adb connect 10.0.0.1:5555
    # + Python: u2.connect_usb("10.0.0.1:5555")

    2.命令行工具

    1)截圖

    uiautomator2 screenshot test.jpg

    2)獲取當前APP報名及Activity

    uiautomator2 current

    3)卸載應用

    uiautomator2 uninstall <package-name> # 卸載一個包
    uiautomator2 uninstall <package-name-1> <package-name-2> # 卸載多個包
    uiautomator2 uninstall --all # 全部卸載

    4)停止應用

    $ uiautomator2 stop com.example.app # 停止一個app
    $ uiautomator2 stop --all # 停止所有的app

    3.元素定位

    1)常見定位方式

    ui2支持 android 中 UiSelector 類中的所有定位方式,詳細可以查看官網:https://developer.android.com/reference/android/support/test/uiautomator/UiSelector,以下僅列出幾種常見的定位方式:

    定位方式

    描述

    text

    通過文本定位

    textMatches

    通過文本正則匹配定位

    className

    通過類名定位

    classNameMatches

    通過類名正則匹配定位

    description

    通過desc屬性定位

    descriptionMatches

    通過desc屬性正則匹配定位

    resourceId

    通過resourceId定位

    resourceIdMatches

    通過resourceId正則匹配定位

    2)子元素定位及兄弟元素定位

    ① 子元素定位-child

    #查找類名為android.widget.ListView下的Bluetooth元素
    d(className="android.widget.ListView").child(text="Bluetooth")
    # 下面這兩種方式定位有點不準確,不建議使用
    d(className="android.widget.ListView")\
    .child_by_text("Bluetooth",allow_scroll_search=True)
    d(className="android.widget.ListView").child_by_description("Bluetooth")

    ② 兄弟元素定位-sibiling

    #查找與google同一級別,類名為android.widget.ImageView的元素
    d(text="Google").sibling(className="android.widget.ImageView")

    ③ 鏈式調用

    d(className="android.widget.ListView", resourceId="android:id/list") \
      .child_by_text("Wi?Fi", className="android.widget.LinearLayout") \
      .child(className="android.widget.Switch") \
      .click()

    3)相對定位

    d(A).left(B),# 選擇A左邊的B
    d(A).right(B),# 選擇A右邊的B
    d(A).up(B), #選擇A上邊的B
    d(A).down(B),# 選擇A下邊的B
    #選擇 WIFI 右邊的開關按鈕
    d(text='Wi?Fi').right(resourceId='android:id/widget_frame')

    4) Xpath定位

    Java uiautoamtor中默認不支持xpath,這是屬于ui2的擴展功能,速度會相比其它定位方式慢一些。在xpath定位中,ui2中的description 定位需要替換為content-desc,resourceId 需要替換為resource-id

    # 只會返回一個元素,如果找不到元素,則會報XPathElementNotFoundError錯誤
    # 如果找到多個元素,默認會返回第0個
    d.xpath('//*[@resource-id="com.android.launcher3:id/icon"]')
    
    # 如果返回的元素有多個,需要使用all()方法返回列表
    # 使用all方法,當未找到元素時,不會報錯,會返回一個空列表
    d.xpath('//*[@resource-id="com.android.launcher3:id/icon"]').all()

    4.元素常用API

    方法

    描述

    返回值

    備注

    exists()

    判斷元素是否存在

    True,Flase

    @property

    info()

    返回元素的所有信息

    字典

    @property

    get_text()

    返回元素文本

    字符串


    set_text(text)

    設置元素文本

    None


    clear_text()

    清空元素文本

    None


    center()

    返回元素的中心點位置

    (x,y)

    基于整個屏幕的點

    send_keys()

    發送文本



    用法示例:

    d(test="Settings").exists
    d.exists(text='Wi?Fi',timeout=5)

    5.設備交互

    1)單擊/雙擊

    d(text='Settings').click()  # 單擊
    d.double_click(x, y)
    d.double_click(x, y, 0.1) # 雙擊默認時間間隔0.1s

    2)長按

    d(text='Settings').longclick()  # 長按

    3)滑動

    # "left", "right", "up", "down"
    d(text="Settings").swipe("up", steps=20)  # 元素向上滑動,步長20
    d(text="Settings").swipe("down", steps=20)  # 元素向下滑動
    d(text="Settings").swipe("left", steps=20)  # 元素向左滑動
    d(text="Settings").swipe("right", steps=20)  # 元素向右滑動

    4)拖動

    d(text="Settings").drag_to(text="Clock", duration=0.25)  # 拖動到某個元素,時長0.25秒
    d(text="Settings").drag_to(877,733)  # 拖動到屏幕某個坐標點,duration時長默認0.5秒

    5)雙指操作(元素放大/縮小)

    d(text="Settings").pinch_in()  # 縮小
    d(text="Settings").pinch_out()  # 放大

    6)等待元素出現/消失

    d(text="Settings").wait(timeout=3.0)  # 等待元素出現
    d(text='Settings').wait_gone(timeout=20)  # 等待元素消失,返回True False,timout默認為全局設置的等待時間

    7)屏幕滾動

    # 垂直滾動到頁面頂部/橫向滾動到最左側
    d(scrollable=True).scroll.toBeginning()
    d(scrollable=True).scroll.horiz.toBeginning()
    # 垂直滾動到頁面最底部/橫向滾動到最右側
    d(scrollable=True).scroll.toEnd()
    d(scrollable=True).scroll.horiz.toEnd()
    # 垂直向后滾動到指定位置/橫向向右滾動到指定位置
    d(scrollable=True).scroll.to(description="指定位置")
    d(scrollable=True).scroll.horiz.to(description="指定位置")
    # 垂直向前滾動(橫向同理)
    d(scrollable=True).scroll.forward()
    # 垂直向前滾動到指定位置(橫向同理)
    d(scrollable=True).scroll.forward.to(description="指定位置")
    # 滾動直到System元素出現
    d(scrollable=True).scroll.to(text="System")

    8)文本框操作

    d.send_keys("test")
    d.clear_text()  # 清空輸入框

    9)toast操作

    # 獲取toast,當沒有找到toast消息時,返回default內容
    d.toast.get_message(timout=5,default='no toast')
    # 清空toast緩存
    d.toast.reset()

    10)監控操作

    # 移除ANR的監控
    d.watcher.remove("ANR")
    
    # 移除所有的監控
    d.watcher.remove()
    
    # 開始后臺監控
    d.watcher.start()
    d.watcher.start(2.0) # 默認監控間隔2.0s
    
    # 強制運行所有監控
    d.watcher.run()
    
    # 停止監控
    d.watcher.stop()
    
    # 停止并移除所有的監控,常用于初始化
    d.watcher.reset()

    更多api詳見:https://github.com/openatx/uiautomator2

    五、weditor元素定位

    1.啟動weditor服務

    python -m weditor

    2.訪問weditor

    默認端口17310,訪問地址:http://localhost:17310/,手機連接PC(確保已開啟USB調試模式),點擊Connect連接設備,當Connect圖標變為綠色表示連接成功。

    3.界面調試

    weditor提供了所操作即所得式的元素定位方式,當雙擊屏幕上的圖標或按鈕,weditor界面右側的Coding框會同步展現元素操作的代碼,同時手機界面也會相應同步切換頁面。

    感謝

    部分內容參考以下:

    https://www.cnblogs.com/fnng/p/8486863.html

    https://testerhome.com/topics/11357

    https://blog.csdn.net/Master724/article/details/107962349?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163394586216780265448858%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163394586216780265448858&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-107962349.pc_search_ecpm_flag&utm_term=uiautomator2&spm=1018.2226.3001.4187

    感謝關注天善智能,走好數據之路↑↑↑

    歡迎關注天善智能,我們是專注于商業智能BI,大數據,數據分析領域的垂直社區,學習,問答、求職一站式搞定!

    前言

    這篇文章的下篇終于寫出來了,上篇(數據采集)在兩個月前寫出來的:

    Python數據采集分析告訴你為何上海二手房你都買不起(一)

    為何下篇現在才寫出來呢?

    有兩個原因:

    1.兩個月前對python數據分析掌握的很差,那時候天天學爬蟲,pandas,numpy了解的也不多

    2.人嘛,總是有惰性,喜歡一拖再拖

    注:python可視化才剛入門,最后的可視化以后還可以完善一篇

    環境

    Python3.X

    編輯器:Jupyter notebook

    導入鏈家網爬取的二手房數據

    import numpy as np

    import pandas as pd

    df=pd.read_excel('house_lianjia.xlsx')

    df

    。。。。。。

    一共2871條數據,其實上次爬了2w條數據,然后找不到了,那就拿測試爬的2871條作分析了

    數據初窺

    查看數據信息(包括每個字段數據類型),數據條數,文件大小等

    df.info()

    查看數據前五行:

    df.head()

    查看數據后五行:

    df.tail()

    我們可以看到‘梯戶比例’一欄好像都是暫無數據

    我們可以專門將這一欄數據拿出來查看:

    df['梯戶比例']

    。。。。。。

    顯示的都是暫無數據

    為了確定是否所有都是暫無數據,我們可以使用如下辦法:

    df[df['梯戶比例']=='暫無數據']#把暫無數據的數據提取出來

    。。。。。。

    取出了2871行,說明所有行的這欄都是暫無數據

    刪除無效的數據

    那么,這一欄對我們數據分析沒有意義,可以刪去:

    del df['梯戶比例']#移除一欄

    我們再次看一下最新的數據情況:

    df

    獲得數據描述性統計

    df.describe()

    我們可以看一下數據的簡單統計信息,從圖中可以看出每個欄位數據的個數,不重復數據個數,出現最多的數據及其出現的次數

    注意到最后一欄,進門朝向數據只有13個,這說明了數據缺失很嚴重,不考慮缺失值補齊,直接刪除該欄數據:

    del df['進門朝向'] #只有13個數據

    再看一下數據情況:

    df

    可以通過這種方式快速查看各欄位名稱:

    #查看列(字段)名稱

    df.columns

    專門查看各字段類型:

    #查看字段類型

    df.dtypes

    發現缺失值

    如果想看每個單元的缺失值,可以使用:

    df.isnull()#哪些包含了缺失值

    Flase表示沒有缺失

    當然,這樣看起來非常難受,而且不直觀

    查看各字段是否有缺失值:

    df.isnull().any()#是否有缺失值

    這樣,我們就能看到除了'房屋朝向'字段有缺失值,其他字段都沒有缺失值。

    我們想看看‘房屋朝向’字段有多少缺失值:

    df.isnull().sum()#每個里有多少個缺失值

    顯示有13個缺失值

    如果你對這個個數不敏感,我們可以看看缺失值的比例:

    df.isnull().sum() / df.count()#缺失值比例 

    ‘房屋朝向’的缺失值只有0.45%左右

    數據探索

    我們想看看數據分布是怎樣的

    例如看一下二手房所在區的情況:

    df['所在區'].value_counts()

    浦東的二手房在售的最多,可能是因為浦東新區地大

    看一下二手房房屋朝向的情況:

    df['房屋朝向'].value_counts()

    南和南北朝向的有很多,陽光充足

    看一下房屋戶型的情況:

    df['房屋戶型'].value_counts()

    可以看出在售的二手房多為2室1廳1衛

    看一下房屋類型的情況:

    df['房屋類型'].value_counts()

    說明公寓類型最多

    篩選房屋信息

    如果我們想看一下我們感興趣的房屋,例如我想找3室1廳1衛的房屋,并且只看部分:

    df[df['房屋戶型']=='3室1廳1衛'].head()

    當然你也可以使用and(&)和or(|)挑選你感興趣的房屋信息,這里不再贅述。

    舍棄有缺失值的行

    之前看到有包含13個含缺失值的行,我們將其舍棄:

    df=df.dropna()#舍棄含有任意缺失值的行,顯示的是剩下的

    df.head()

    小插曲:在jupyter notebook中,如果想要看一個方法的具體使用方法,我們可以:

    ?df.dropna()

    然后查看彈出的信息了解使用說明

    此時,我們再看看是否還有缺失值:

    df.isnull().any()#是否有缺失值

    顯示已經沒有缺失值了

    資料重整

    我們發現:

    房屋類型中,所有類型前面都顯示‘住宅-’,我們將其去除

    df['房屋類型']=df['房屋類型'].map(lambda e: e.split(' - ')[1].split())

    注:將該字段信息以‘-’為分隔符分成前后兩部分(兩部分都不包括-),然后索引取后面部分(如果是前面部分則是[0])

    然后在pandas里用map加載匿名函數lambda,返回的e即為‘-’后面的部分信息

    df

    處理完之后:

    正則表達式提取信息

    由于建筑面積的信息不是數值型,而且建筑面積里含有‘平’這個字,不能直接用于計算

    所以我們提取出其中的數字:

    df['建筑面積'].str.extract('(\d+\.\d+)平', expand=False)

    \d+:匹配0-9中一個及其以上數字

    \.:轉義,匹配點

    (\d+\.\d+)用括號括起來,提取括號中的信息

    提取的結果如下:

    我們將提取的結果反饋回dataframe表格:

    df['建筑面積']=df['建筑面積'].str.extract('(\d+\.\d+)平', expand=False)
    df.head(5)

    看來已經完成這一步驟

    同理,使用正則提取‘總價’欄位中的數字:

    df['總價'].str.extract('(\d+)萬', expand=False)

    df['總價']=df['總價'].str.extract('(\d+)萬', expand=False)

    df.head()

    轉換數據類型

    提取出來的數字是字符類型,我們需要將其轉化為數字類型,例如float浮點數,int整型等

    df[['總價']]=df[['總價']].astype(int)
    df[['建筑面積']]=df[['建筑面積']].astype(float)
    df.info()

    轉換完成后,可以看出‘建筑面積’和‘總價’已經是數值型的了

    屬性構造

    我們構造一個屬性叫做‘均價’

    df['均價']=df['總價']/df['建筑面積']
    df.head()

    建立數據透視表

    df2=df.pivot_table(index='位置', 
    columns='裝修情況',
    values='均價',
    fill_value='0')#默認均價,比較出各個地區價格

    df2.head()#位置作為索引,裝修情況作為欄位,均價作為值

    df2=df.pivot_table(index='所在區', 
    columns='裝修情況',
    values='均價',
    fill_value='0')#默認均價,比較出各個地區價格

    df2#所在區作為索引,裝修情況作為欄位,均價作為值

    這樣的數據透視表,可以讓我們一目了然的看出各區不同裝修情況在售的不同二手房價格(均價單位是萬元/每平方米,取的是平均值)

    我們注意到,上面的數據透視表中有很多0,當然,這里的0不是說房價為0,而是fill_value='0',即缺失值用0填充了

    無意義的值轉為缺失值

    我們看到,裝修情況欄位中有著'暫無數據'的字樣情況:

    我們將其變為缺失值:

    df['裝修情況']=df['裝修情況'].replace('暫無數據',np.NaN)

    然后刪去這些含缺失值的行:

    df.dropna()

    我們注意到行數確實減少了

    我們再次制作數據透視表:

    df2=df.pivot_table(index='所在區', 
    columns='裝修情況',
    values='均價',
    fill_value=np.NaN)#默認均價,比較出各個地區價格

    df2#位置作為索引,裝修情況作為欄位,均價作為值

    NaN表示沒有信息:意思是沒有此類的房屋信息

    數據可視化

    做數據分析,數據展現的方法之一就是圖

    #-*- coding: utf-8 -*-

    %matplotlib inline

    以上是為了讓繪制的圖顯示出來

    from matplotlib.font_manager import FontProperties

    import matplotlib.pyplot as plt

    font=FontProperties(fname='C:\Windows\Fonts\simsun.ttc')

    以上是為了解決繪圖里中文字體顯示問題,可以參照如下鏈接設置顯示中文字體:

    https://www.joinquant.com/post/441

    繪制散點圖

    df.plot(x='建筑面積', y='總價', kind='scatter')

    plt.xlabel('建筑面積', fontproperties=font)

    可以看出,隨著建筑面積的增大,二手房的總價也在上升,并沒有出現特別異常的值

    但是有離群值出現,例如靠近右上角的,我們可以看一下這些房屋的信息:

    df[df['建筑面積']>250]

    繪制柱狀圖

    注:以下過程比較波折,在于我目前對可視化學習較少

    為了統計不同裝修情況,我進行了一大堆步驟:

    df1=pd.get_dummies(df['裝修情況'])#建立虛擬變量,是精裝則在精裝位置顯示1,以此類推

    df1.head()

    dec=df1.sum()
    type(dec)

    我想將Series轉為df:

    dec

    df2=pd.DataFrame(dec)#series轉為df

    df2

    發現索引不是我想要的,于是我刪除了索引:

    df2=df2.reset_index(drop=True)

    df2

    這繞了一圈差不多刪除完了,尷尬

    再手工加回去:

    df2['裝修情況']=['中裝','毛坯','簡裝','精裝','豪裝']

    df2

    這欄位名不太對,改一下:

    df2.columns=['個數', '裝修情況']

    df2

    走到這部不容易,我一定好好學數據可視化。。。

    df2.plot(x='裝修情況', y='個數', kind='bar')

    plt.xlabel('裝修情況', fontproperties=font)

    繪圖,通過圖形更加一目了然看出不同裝修情況的個數比較

    最后再看一下描述性統計:

    df.describe()

    因為數據缺失值處理了,數字轉為數值型了,所以此時的統計更有意義

    包括數量、均指、標準差、最小值、上四分位數等等。

    寫在文末

    這是我寫的比較久的一篇文章,就像在做一個簡單的項目一樣,從上文的爬取數據到這次的數據分析可視化,終于完整的做了一次數據分析。

    致謝

    在這篇文章的數據分析過程中,感謝秦路老師給我在技術上的答疑解惑!

    本文來源自天善智能社區,作者:王大偉,

    博客:https://www.hellobi.com/u/wangdawei/articles

    天善學院svip正火爆報名中!包含Excel BI、Python3爬蟲案例、Python機器學習、Python數據科學家、大數據體系、數據分析報告、數據分析師體系、深度學習、R語言案例共10套課程,其他課程只需五折即可,歡迎大家關注報名!

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有