2025年4月2日 星期三 乙巳(蛇)年 正月初三 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Python

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

时间:10-12来源:作者:点击数:38

1、目 标 场 景

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

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

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

2、准 备 工 作

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

  • # 安装 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()

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

图片

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

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

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

图片

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

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

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

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

图片

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

  • for indeximage_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.80.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 爬某个你特别关心的人的历年发表的所有动态,然后进行数据分析,获取到一个人的兴趣、爱好等。

图片

已经将全部源码上传:https://github.com/xingag/app_spider/tree/master/%E5%BE%AE%E4%BF%A1%E6%9C%8B%E5%8F%8B%E5%9C%88。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐