以前的24小時內朋友圈發生了什麼,Python告訴你


1  目 標 場 景

上一篇 文章 使用 Airtest 實現自動看新聞薅羊毛這一操做,其實 Airtest 功能遠不止此。android


App 上的幾乎全部的操做均可以經過 Airtest 進行模擬。spring


本文的目標,繼續使用「Airtest」模擬查看朋友圈的操做,並把以前 24 小時內朋友圈發生的一切事情,包含圖片、視頻全都爬取到本地。 shell



2  準 備 工 做

準備工做上篇文章已經介紹過了。一樣須要提早配置好 adb 環境,而後利用 pip/pip3 安裝 airtest 和 pocoui 兩個依賴庫。bash


# 安裝 airtest
pip3 install aritest

# 安裝pocoui
pip3 install pocoui複製代碼



3  分 析 思 路

咱們須要實例化「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)複製代碼



4  結 果 結 論


運行程序後,微信會自動打開,進入到朋友圈主界面,而後對朋友圈內的每一條動態進行數據採集,自動滑動手機屏幕直至採集完今天朋友圈的全部動態數據。


固然,也能夠利用 Airtest 爬某個你特別關心的人的歷年發表的全部動態,而後進行數據分析,獲取到一我的的興趣、愛好等。



我本文首發於公衆號「 AirPython 」,後臺回覆「 朋友圈 」便可獲取完整代碼。



推薦閱讀:

薅羊毛 | 讓Python天天幫你薅一個早餐錢

要搶紅包?Python來幫你~

相關文章
相關標籤/搜索