不懂抓包也能做APP爬蟲?Airtest爬取抖音流行歌名!

轉自Airtest公衆號


前言

說起APP爬蟲,相信大家會很容易聯想到一些抓包工具:Fiddler、Charles、mitmproxy和anyproxy等等。藉助這些抓包工具,我們可以知道APP在運行過程中具體發起了什麼請求,之後我們就可以詳細分析這些請求,再 用程序模擬這些請求最終實現爬蟲 。然而,在爬蟲的實操中,APP的各種反爬措施也是不容小覷的,比如抓包失敗、參數加密、代碼被編譯等等,都增加了我們爬取APP數據的難度。那麼作爲一名不懂抓包的小白,是不是就無緣爬蟲了呢?不要慌,今天我們就帶大家 用airtest來實現1個模擬抓取的過程 ,把網易雲音樂中抖音排行榜的100首歌曲名稱爬取下來!

 

準備工作

爲了 爬取抖音排行榜100首歌曲的名稱 ,首先我們需要編寫1個自動化腳本,在APP內打開這個排行榜,步驟如下:

  • 1.連接測試設備
  • 2.打開網易雲音樂的APP
  • 3.初始化poco
  • 4.同意首頁的服務條款彈窗
  • 5.勾選用戶協議並點擊立即體驗
  • 6.點擊輸入按鈕並輸入“抖音”
  • 7.點擊搜索關鍵詞並等待排行榜加載
  • 8.點擊進入抖音排行榜

圖片

代碼實現如下:

# -*- encoding=utf8 -*-
__author__ = "AirtestProject"
from airtest.core.api import *
auto_setup(__file__,devices=["Android://127.0.0.1:5037/emulator-5554"])

clear_app("com.netease.cloudmusic")
start_app("com.netease.cloudmusic")
sleep(1.0)

from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)

# 同意服務條款
poco("com.netease.cloudmusic:id/agree").click()

wait(Template(r"tpl1595916981414.png", record_pos=(0.004, -0.452), resolution=(900, 1600)))
sleep(2.0)

# 勾選用戶協議並點擊立即體驗
poco("com.netease.cloudmusic:id/agreeCheckbox").click()
poco("com.netease.cloudmusic:id/trial").click()
sleep(2.0)

poco("搜索").wait_for_appearance()
sleep(1.0)
# 點擊搜索按鈕並輸入“抖音”
poco("搜索").click()
sleep(1.0)

poco("com.netease.cloudmusic:id/search_src_text").click()
poco("com.netease.cloudmusic:id/search_src_text").set_text("抖音")
sleep(1.0)
poco.click([0.14,0.13])

assert_exists(Template(r"tpl1595821867472.png", record_pos=(-0.283, -0.489), resolution=(900, 1600)), "找到抖音排行榜")

# 點擊進入抖音排行榜
poco("com.netease.cloudmusic:id/title").click()

其中需要注意的是poco的初始化順序,先連接設備,再打開APP,最後才初始化poco,可以有效避免一些奇奇怪怪的錯誤。

 

爬取歌名

 

進入抖音排行榜的歌曲列表之後,我們先來觀察下此刻的UI樹結構:

圖片

從UI樹中我們可以知道,歌曲名稱這個控件,都在 musicListItemContainer 這個控件裏面,所以爲了獲取歌曲名稱,首先我們需要 遍歷 所有加載出來的 musicListItemContainer ,再定位到歌曲名稱的控件,依此來獲取控件的 text 屬性:

for title in poco("com.netease.cloudmusic:id/musicInfoList").child("com.netease.cloudmusic:id/musicListItemContainer"):
a = title.offspring("com.netease.cloudmusic:id/songName")
name = a.get_text()
print(a)

獲取完當前頁面加載的所有歌曲名稱之後,我們可以通過向上滑動列表,來不斷加載新的歌曲控件。但這時候,我們還需要解決2個問題:① 我們單次向上滑動歌曲列表,並不能保證當前加載出來的歌曲控件都是新的控件,有可能某些控件裏面的歌曲名稱我們已經獲取到了,那麼 如何解決獲取歌名重複的問題呢 ?我們可以事先定義好1個空的數組,將獲取到的歌曲名稱放到數組裏面,在放入歌曲名稱之前,做1個判斷,放入數組的歌名不能與數組已經存在的歌名相同,這樣子就能夠保證我們每次放入的都是新的歌名;② 多次滑動列表之後,我們 如何判斷所有歌曲名稱已經獲取完畢呢 ?很簡單,我們可以設置1個數組長度的計數器,當數組長度不再增加,即沒有新的名字被添加到數組的時候,既可以認爲我們已經把排行榜的歌曲名稱獲取完了。最終實現的效果如下:

圖片

# 定義1個空數組用於存放排行榜的歌名
titles = []
# 定義數組目前的長度和最終的長度
current_count, last_count = len(titles), len(titles)

while True:
last_count = len(titles)
for title in poco("com.netease.cloudmusic:id/musicInfoList").child("com.netease.cloudmusic:id/musicListItemContainer"):
a = title.offspring("com.netease.cloudmusic:id/songName")
if not a.exists():
continue
name = a.get_text()
if not name in titles:
titles.append(name)
print(name)

current_count = len(titles)
poco.swipe([0.5,0.7],[0.5,0.1],duration=2)
sleep(1.0)

# 當倆者數值相等,即current_count不再增加時,表明爬取完畢
if current_count == last_count:
print("總共爬取"+str(last_count)+"首歌曲的名稱")
break

 

小結

上述就是利用airtest實現模擬爬取的全部過程。當然,我們不僅可以把爬取的歌曲名稱打印在log查看窗中,還可以將它保存在指定的文檔中,這個大家可以嘗試着自己實現一下。

 

---------------------------------------------------------------------------------

關注微信公衆號即可在手機上查閱,並可接收更多測試分享~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章