以前的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来帮你~

相关文章
相关标签/搜索