對於python這塊有任何不懂的問題可以隨時來問我,我對於學習方法,系統學習規劃,還有學習效率這些知道一些,希望可以幫助大家少走彎路。文末附送會送給大家一份系統性的python資料
說起 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 查看窗中,還可以將它保存在指定的文檔中,這個大家可以嘗試着自己實現一下。
https://shimo.im/docs/QvG8JqxGKvcrXQhH/ 《python基礎到進階學習資料》,可複製鏈接後用石墨文檔 App 或小程序打開