之前的24小时内朋友圈发生了什么,Python告诉你

640?wx_fmt=png

1

目 标 场 景


上一篇 文章 使用 Airtest 实现自动看新闻薅羊毛这一操作,其实 Airtest 功能远不止此。


App 上的几乎所有的操作都可以通过 Airtest 进行模拟。


本文的目标,继续使用Airtest模拟查看朋友圈的操作,并把之前 24 小时内朋友圈发生的一切事情,包含图片、视频全都爬取到本地。 



2

准 备 工 作


准备工作上篇文章已经介绍过了。同样需要提前配置好 adb 环境,然后利用 pip/pip3 安装 airtest 和 pocoui 两个依赖库。



 
# 安装 airtestpip3 install aritest# 安装pocouipip3 install pocoui
pip3 install aritest

# 安装pocoui
pip3 install pocoui



3

分 析 思 路


我们需要实例化AndroidUiautomationPoco 对象,然后使用第三方工具获取到微信客户端的包名和初始 Activity 之后,就可以使用使用 adb 命令打开微信客户端。



 
# 微信客户端的应用包名package_name = 'com.tencent.mm'# 微信客户端的启动 Activityactivity = 'com.tencent.mm.ui.LauncherUI'poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False)# 回到手机主界面home()# 杀死微信Appstop_app(package_name)# 打开微信Appstart_my_app(package_name, activity)# 进入朋友圈的入口poco(text='发现').click()poco(text='朋友圈').click()
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()


进入朋友圈主界面之后需要等待几秒,待第一页的元素全部加载完毕,就可以获取我们需要的数据信息了。


640?wx_fmt=png


首先我们获取到第一页可以看见的列表元素,通过遍历,对其中我们需要的数据,包含图片、视频、文字进行存储。



 
# 朋友圈动态列表元素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')
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')


如果图片元素存在,那么就表示这条数据是一条包含图片的动态数据。


640?wx_fmt=png


我们需要从图片父元素中获取到所有图片子元素。


640?wx_fmt=png



 
if image_element.exists():      # 这是一条图片动态      # 所有图片子元素      image_children = image_element.child()      image_size = len(image_children)      print('共有%d张图片' % image_size)
      # 这是一条图片动态
      # 所有图片子元素
      image_children = image_element.child()

      image_size = len(image_children)
      print('共有%d张图片' % image_size)


接下来就是遍历所有图片元素,然后点击第一个图片子元素进入到图片预览界面。


然后使用long_click」方法实现长按屏幕的操作,弹出保存图片的弹出框。


640?wx_fmt=png


最后获取到「保存图片」按钮,执行点击操作,这样图片就保存微信默认的存储目录下了。



 
for index, image_child in enumerate(image_children):      poco("android.widget.LinearLayout").offspring('com.tencent.mm:id/j7').long_click()   poco(text="保存图片").click()
   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))
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)
if index == image_size - 1:
       keyevent("BACK")
else:
       # 如果不是最后一张图片元素,需要向左滑动,切换到下一张图片
       poco.swipe([0.80.5], [0.20.5], duration=0.5)
       sleep(1)


同理,遇到视频的动态元素的时候,也是需要点击进入视频播放界面。


长按视频播放界面上点击保存视频按钮,将视频文件保存到微信默认的文件夹内,最后使用 adb 命令将视频文件拷贝到 PC 端。


640?wx_fmt=png


另外,由于一条动态只能发送一条视频,保存完视频文件之后,直接返回到动态列表界面。



 
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')
     # 点击查看视频
     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
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
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)
    """
    写入到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 爬某个你特别关心的人的历年发表的所有动态,然后进行数据分析,获取到一个人的兴趣、爱好等。


640?wx_fmt=png


往期热门:

值得收藏|菜鸟学Python【入门文章大全】


学习群:

小密圈人气很高的两个实战项目

小密圈的趣味实战-微信主题

3个月还没入门Python,看这100名小密圈的同学3周学Python的杰作


本源码来自公众号 Airpython。

需要源码,后台输入:【朋友圈】


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值