上一篇 文章 使用 Airtest 實現自動看新聞薅羊毛這一操做,其實 Airtest 功能遠不止此。android
App 上的幾乎全部的操做均可以經過 Airtest 進行模擬。spring
本文的目標,繼續使用「Airtest」模擬查看朋友圈的操做,並把以前 24 小時內朋友圈發生的一切事情,包含圖片、視頻全都爬取到本地。 shell
準備工做上篇文章已經介紹過了。一樣須要提早配置好 adb 環境,而後利用 pip/pip3 安裝 airtest 和 pocoui 兩個依賴庫。bash
# 安裝 airtest
pip3 install aritest
# 安裝pocoui
pip3 install pocoui複製代碼
咱們須要實例化「AndroidUiautomationPoco」 對象,而後使用第三方工具獲取到微信客戶端的包名和初始 Activity 以後,就可使用使用 adb 命令打開微信客戶端。微信
# 微信客戶端的應用包名
package_name = 'com.tencent.mm'
# 微信客戶端的啓動 Activity
activity = 'com.tencent.mm.ui.LauncherUI'
poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)
# 回到手機主界面
home()
# 殺死微信App
stop_app(package_name)
# 打開微信App
start_my_app(package_name, activity)
# 進入朋友圈的入口
poco(text='發現').click()
poco(text='朋友圈').click()複製代碼
進入朋友圈主界面以後須要等待幾秒,待第一頁的元素所有加載完畢,就能夠獲取咱們須要的數據信息了。app
首先咱們獲取到第一頁能夠看見的列表元素,經過遍歷,對其中咱們須要的數據,包含圖片、視頻、文字進行存儲。ide
# 朋友圈動態列表元素
head_dynamic_moods = poco("com.tencent.mm:id/ebi").child(name='com.tencent.mm:id/efo')
for head_dynamic_mood in head_dynamic_moods:
# 暱稱
nickname_element = head_dynamic_mood.offspring('com.tencent.mm:id/b4o')
# 動態
dynamic_mood_element = head_dynamic_mood.offspring('com.tencent.mm:id/efs')
# 發佈時間
# 注意:若是發佈時間元素尚未拖動上來,這裏可能就爲空
pub_time_element = head_dynamic_mood.offspring('com.tencent.mm:id/eay')
# 圖片【能夠有多個】
image_element = head_dynamic_mood.offspring('com.tencent.mm:id/efe')
# 視頻【只能有一個】
video_element = head_dynamic_mood.offspring('com.tencent.mm:id/ao4')複製代碼
若是圖片元素存在,那麼就表示這條數據是一條包含圖片的動態數據。工具
咱們須要從「圖片父元素」中獲取到全部圖片子元素。ui
if image_element.exists():
# 這是一條圖片動態
# 全部圖片子元素
image_children = image_element.child()
image_size = len(image_children)
print('共有%d張圖片' % image_size)複製代碼
接下來就是遍歷全部圖片元素,而後點擊第一個圖片子元素進入到圖片預覽界面。spa
而後使用「long_click」方法實現長按屏幕的操做,彈出保存圖片的彈出框。
最後獲取到「保存圖片」按鈕,執行點擊操做,這樣圖片就保存微信默認的存儲目錄下了。
for index, image_child in enumerate(image_children):
poco("android.widget.LinearLayout").offspring('com.tencent.mm:id/j7').long_click()
poco(text="保存圖片").click()複製代碼
因爲 adb 命令無法按照修改時間對文件進行排序,因此每次保存圖片以前都須要刪除微信文件夾,而後利用「adb pull」命令將圖片下載到 PC 端。
# 微信文件保存目錄
WEI_XIN_FILE_PATH = '/storage/emulated/0/tencent/MicroMsg/WeiXin/'
# 刪除手機端微信文件夾目錄
os.popen('adb shell rm -r %s*' % path)
# 拷貝文件夾內的文件到pc端
copy_last_pic_to_local(WEI_XIN_FILE_PATH, adjunct_path)
# 注意:使用adb無法排序文件,爲了準確獲取文件,下載文件以前,須要提早刪除微信文件夾
def copy_last_pic_to_local(path, folder):
""" 從移動端獲取到最新的一個圖片 :param path: 手機上的文件目錄 :param folder:PC端文件保存的目錄 :return: """
# 讀取目錄下的全部文件
r = os.popen('adb shell ls %s' % path)
# 讀取命令行的輸出到一個list
infos = r.readlines()
# 文件名稱
last_file_name = infos[0].strip('\r\n')
print(path + last_file_name)
print(folder)
if not os.path.exists(folder):
os.makedirs(folder)
# 加上絕對路徑,把文件複製到本地文件夾中
os.popen('adb pull %s %s' % (path + last_file_name, folder))複製代碼
ps:另外因爲 adb 無法對文件按修改時間進行排序,爲了保證獲取的圖片的準確性,須要提早備份好微信文件夾的內容。
一張圖片保存成功後,須要判斷這張圖片元素的索引,若是不是最後一張圖片,就須要向左滑動,切換到下一個圖片元素界面;不然,直接返回到動態列表頁面。
# 若是是最後一張圖片元素,直接返回到動態列表頁面
if index == image_size - 1:
keyevent("BACK")
else:
# 若是不是最後一張圖片元素,須要向左滑動,切換到下一張圖片
poco.swipe([0.8, 0.5], [0.2, 0.5], duration=0.5)
sleep(1)複製代碼
同理,遇到視頻的動態元素的時候,也是須要點擊進入視頻播放界面。
長按視頻播放界面上點擊「保存視頻」按鈕,將視頻文件保存到微信默認的文件夾內,最後使用 adb 命令將視頻文件拷貝到 PC 端。
另外,因爲一條動態只能發送一條視頻,保存完視頻文件以後,直接返回到動態列表界面。
if video_element.exists():
# 點擊查看視頻
video_element.click()
# 長按彈出保存視頻的對話框
poco('com.tencent.mm:id/ae5').long_click()
# 刪除微信默認的文件夾目錄
del_files(WEI_XIN_FILE_PATH)
# 保存視頻
poco(text='保存視頻').click()
# 複製到PC端文件夾內
copy_last_pic_to_local(WEI_XIN_FILE_PATH, adjunct_path)
# 直接返回到動態列表頁面
keyevent('BACK')複製代碼
遍歷完某頁的動態以後,須要滑動到下一頁,直達獲取到的一條動態的發佈時間是昨天,就中止爬取。
# 動態發佈時間pub_time = pub_time_element.get_text()if pub_time == '昨天': print('這是一條昨天的動態,中止爬取。。。') return False複製代碼
爬取數據的過程當中,動態列表中可能包含微信放置的廣告,須要經過元素特有的標識進行過濾。
# 廣告標識
advertising_tips_element = head_dynamic_mood.offspring('com.tencent.mm:id/e_f')
# 廣告動態篩除掉、沒有加載徹底的元素篩除掉
if advertising_tips_element.exists() or not pub_time_element.exists() or not nickname_element.exists():
continue複製代碼
等全部的動態信息都爬取以後,將爬取的文字信息,包含暱稱、內容、發表時間寫入到 csv 文件中。
def write_to_csv(first, format_values):
""" 寫入到csv文件中 :return: """
with open('firends_circle.csv', 'a', encoding='utf-8-sig', newline='') as fp:
# 1.建立一個dictwriter對象
writer_dict = csv.DictWriter(fp, headers)
# 2.手動寫入標題
if first:
writer_dict.writeheader()
else:
# 3.寫入數據
writer_dict.writerows(format_values)複製代碼
運行程序後,微信會自動打開,進入到朋友圈主界面,而後對朋友圈內的每一條動態進行數據採集,自動滑動手機屏幕直至採集完今天朋友圈的全部動態數據。
固然,也能夠利用 Airtest 爬某個你特別關心的人的歷年發表的全部動態,而後進行數據分析,獲取到一我的的興趣、愛好等。
我本文首發於公衆號「 AirPython 」,後臺回覆「 朋友圈 」便可獲取完整代碼。
推薦閱讀: