用 Python 告诉你!最近 24 小时内朋友圈发生了什么
點(diǎn)擊“小詹學(xué)Python”,選擇“置頂公眾號”
第一時(shí)間獲取 Python 技術(shù)干貨!
本文授權(quán)轉(zhuǎn)載自:AirPython
閱讀文本大概需要 10 分鐘。
1
目 標(biāo) 場 景
之前有一篇?文章?使用 Airtest 實(shí)現(xiàn)自動看新聞薅羊毛這一操作,其實(shí) Airtest 功能遠(yuǎn)不止此。
App 上的幾乎所有的操作都可以通過 Airtest 進(jìn)行模擬。
本文的目標(biāo),繼續(xù)使用「Airtest」模擬查看朋友圈的操作,并把之前 24 小時(shí)內(nèi)朋友圈發(fā)生的一切事情,包含圖片、視頻全都爬取到本地。?
2
準(zhǔn) 備 工 作
準(zhǔn)備工作上篇文章已經(jīng)介紹過了。同樣需要提前配置好 adb 環(huán)境,然后利用 pip/pip3 安裝 airtest 和 pocoui 兩個(gè)依賴庫。
pip3?install?aritest
#?安裝pocoui
pip3?install?pocoui
3
分 析 思 路
我們需要實(shí)例化「AndroidUiautomationPoco」?對象,然后使用第三方工具獲取到微信客戶端的包名和初始 Activity 之后,就可以使用使用 adb 命令打開微信客戶端。
package_name?=?'com.tencent.mm'
activity?=?'com.tencent.mm.ui.LauncherUI'
poco?=?AndroidUiautomationPoco(use_airtest_input=True,?screenshot_each_action=False)
home()
stop_app(package_name)
start_my_app(package_name,?activity)
poco(text='發(fā)現(xiàn)').click()
poco(text='朋友圈').click()
進(jìn)入朋友圈主界面之后需要等待幾秒,待第一頁的元素全部加載完畢,就可以獲取我們需要的數(shù)據(jù)信息了。
首先我們獲取到第一頁可以看見的列表元素,通過遍歷,對其中我們需要的數(shù)據(jù),包含圖片、視頻、文字進(jìn)行存儲。
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')
?? #?動態(tài)
?? dynamic_mood_element?=?head_dynamic_mood.offspring('com.tencent.mm:id/efs')
?? #?發(fā)布時(shí)間
?? #?注意:如果發(fā)布時(shí)間元素還沒有拖動上來,這里可能就為空
?? pub_time_element?=?head_dynamic_mood.offspring('com.tencent.mm:id/eay')
??
?? #?圖片【可以有多個(gè)】
?? image_element?=?head_dynamic_mood.offspring('com.tencent.mm:id/efe')
?? #?視頻【只能有一個(gè)】
?? video_element?=?head_dynamic_mood.offspring('com.tencent.mm:id/ao4')
如果圖片元素存在,那么就表示這條數(shù)據(jù)是一條包含圖片的動態(tài)數(shù)據(jù)。
我們需要從「圖片父元素」中獲取到所有圖片子元素。
??????#?這是一條圖片動態(tài)
??????#?所有圖片子元素
??????image_children?=?image_element.child()
??????image_size?=?len(image_children)
??????print('共有%d張圖片'?%?image_size)
接下來就是遍歷所有圖片元素,然后點(diǎn)擊第一個(gè)圖片子元素進(jìn)入到圖片預(yù)覽界面。
然后使用「long_click」方法實(shí)現(xiàn)長按屏幕的操作,彈出保存圖片的彈出框。
最后獲取到「保存圖片」按鈕,執(zhí)行點(diǎn)擊操作,這樣圖片就保存微信默認(rèn)的存儲目錄下了。
???poco("android.widget.LinearLayout").offspring('com.tencent.mm:id/j7').long_click()
???poco(text="保存圖片").click()
由于 adb 命令沒法按照修改時(shí)間對文件進(jìn)行排序,所以每次保存圖片之前都需要刪除微信文件夾,然后利用「adb pull」命令將圖片下載到 PC 端。
WEI_XIN_FILE_PATH?=?'/storage/emulated/0/tencent/MicroMsg/WeiXin/'
#?刪除手機(jī)端微信文件夾目錄
os.popen('adb?shell?rm?-r?%s*'?%?path)
#?拷貝文件夾內(nèi)的文件到pc端
copy_last_pic_to_local(WEI_XIN_FILE_PATH,?adjunct_path)
#?注意:使用adb沒法排序文件,為了準(zhǔn)確獲取文件,下載文件之前,需要提前刪除微信文件夾
def?copy_last_pic_to_local(path,?folder):
????"""
?????從移動端獲取到最新的一個(gè)圖片
????:param?path:?手機(jī)上的文件目錄
????:param?folder:PC端文件保存的目錄
????:return:
????"""
????#?讀取目錄下的所有文件
????r?=?os.popen('adb?shell?ls?%s'?%?path)
????#?讀取命令行的輸出到一個(gè)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)
????#?加上絕對路徑,把文件復(fù)制到本地文件夾中
????os.popen('adb?pull?%s?%s'?%?(path?+?last_file_name,?folder))
ps:另外由于 adb 沒法對文件按修改時(shí)間進(jìn)行排序,為了保證獲取的圖片的準(zhǔn)確性,需要提前備份好微信文件夾的內(nèi)容。
一張圖片保存成功后,需要判斷這張圖片元素的索引,如果不是最后一張圖片,就需要向左滑動,切換到下一個(gè)圖片元素界面;否則,直接返回到動態(tài)列表頁面。
if?index?==?image_size?-?1:
???????keyevent("BACK")
else:
???????#?如果不是最后一張圖片元素,需要向左滑動,切換到下一張圖片
???????poco.swipe([0.8,?0.5],?[0.2,?0.5],?duration=0.5)
???????sleep(1)
同理,遇到視頻的動態(tài)元素的時(shí)候,也是需要點(diǎn)擊進(jìn)入視頻播放界面。
長按視頻播放界面上點(diǎn)擊「保存視頻」按鈕,將視頻文件保存到微信默認(rèn)的文件夾內(nèi),最后使用 adb 命令將視頻文件拷貝到 PC 端。
另外,由于一條動態(tài)只能發(fā)送一條視頻,保存完視頻文件之后,直接返回到動態(tài)列表界面。
?????
?????video_element.click()
?????
?????poco('com.tencent.mm:id/ae5').long_click()
?????
?????del_files(WEI_XIN_FILE_PATH)
?????
?????poco(text='保存視頻').click()
?????
?????copy_last_pic_to_local(WEI_XIN_FILE_PATH,?adjunct_path)
?????
?????keyevent('BACK')
遍歷完某頁的動態(tài)之后,需要滑動到下一頁,直達(dá)獲取到的一條動態(tài)的發(fā)布時(shí)間是昨天,就停止爬取。
pub_time?=?pub_time_element.get_text()
if?pub_time?==?'昨天':
??????print('這是一條昨天的動態(tài),停止爬取。。。')
??????return?False
爬取數(shù)據(jù)的過程中,動態(tài)列表中可能包含微信放置的廣告,需要通過元素特有的標(biāo)識進(jìn)行過濾。
advertising_tips_element?=?head_dynamic_mood.offspring('com.tencent.mm:id/e_f')
?#?廣告動態(tài)篩除掉、沒有加載完全的元素篩除掉
if?advertising_tips_element.exists()?or?not?pub_time_element.exists()?or?not?nickname_element.exists():
??????continue
等所有的動態(tài)信息都爬取之后,將爬取的文字信息,包含昵稱、內(nèi)容、發(fā)表時(shí)間寫入到 csv 文件中。
????"""
????寫入到csv文件中
????:return:?
????"""
????with?open('firends_circle.csv',?'a',?encoding='utf-8-sig',?newline='')?as?fp:
????????#?1.創(chuàng)建一個(gè)dictwriter對象
????????writer_dict?=?csv.DictWriter(fp,?headers)
????????#?2.手動寫入標(biāo)題
????????if?first:
????????????writer_dict.writeheader()
????????else:
????????????#?3.寫入數(shù)據(jù)
????????????writer_dict.writerows(format_values)
4
結(jié) 果 結(jié) 論
運(yùn)行程序后,微信會自動打開,進(jìn)入到朋友圈主界面,然后對朋友圈內(nèi)的每一條動態(tài)進(jìn)行數(shù)據(jù)采集,自動滑動手機(jī)屏幕直至采集完今天朋友圈的所有動態(tài)數(shù)據(jù)。
當(dāng)然,也可以利用 Airtest 爬某個(gè)你特別關(guān)心的人的歷年發(fā)表的所有動態(tài),然后進(jìn)行數(shù)據(jù)分析,獲取到一個(gè)人的興趣、愛好等。
我已經(jīng)將全部源碼上傳到后臺上,公眾號后臺回復(fù)「?朋友圈?」即可獲得。
推薦閱讀:
我拿 12 年 36 套四級真題做了什么 ?
Python | 擁有選擇權(quán) ,才擁有概率 。
總結(jié)
以上是生活随笔為你收集整理的用 Python 告诉你!最近 24 小时内朋友圈发生了什么的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nature:压榨学生,论资排辈,现行论
- 下一篇: 这个库厉害了,自动补全Python代码,