python爬取微信朋友圈数据

一、爬取微信朋友圈的多种方法总结

1.用itchat包实现PC端网页版微信登录爬取数据
->微信已经关闭网页版,方法无法使用

2.用pywinauto库在PC端微信爬取数据
-> 查看github发现Pywinauto库在19年之后没有再维护,很多模块已经不兼容win11,舍弃该方法

3.调用api
-> 这种最方便但是微信官方并不提供朋友圈数据接口,最后得到的数据只有通讯录内容

4.用Appnium自动化模拟操作爬数据
-> Appnium不是一个库,是一套软件,安装需要java环境等,还有配置,非常麻烦

5.用uiautomator2库自动化模拟人工操作
-> uiautomator2比Appnium简单易上手,但是目前相关代码较少

这里我们采取用uiautomator2库的方法爬取朋友圈数据。

二、准备操作

1. python3

2. pycharm或其他ide

3. 安卓手机或模拟器

4. uiautomator2库的使用方式(关于u2库的快速入门使用可以看我的上一篇博客python做手机端app自动化测试-CSDN博客

5. 数据库MySQL -> 用于朋友圈数据的导入,当然也可以选择导入到excel(关于MySQL的快速入门使用可以看MYSQL数据库操作-CSDN博客

6. xpath语法和lxml库的使用(关于其快速入门可以看xpath和lxml库的使用-CSDN博客

三、自动化流程

1. 获取微信朋友圈的必要控件信息

连接好手机之后打开weditor,将手机中微信app的包名、‘发现’控件、‘朋友圈’控件信息记录下来。

我的控件信息如下(仅参考):

# 微信包名
'com.tencent.mm'

# ‘发现’控件
resourceId="com.tencent.mm:id/icon_tv", text="发现"

# ‘朋友圈’控件
resourceId="com.tencent.mm:id/m38"

以及朋友圈页面个体项目、网名、文章内容、日期信息也记录下来。

我的控件信息如下(仅参考):

# 朋友圈页面个体
resourceId="com.tencent.mm:id/n9a"

# 网名
resourceId="com.tencent.mm:id/kbq"

# 文章内容
resourceId="com.tencent.mm:id/cut"

# 日期
resourceId="com.tencent.mm:id/n93"

这些数据会在u2库的调用时用到

2. 编写程序

① 首先,用u2库建立好手机与电脑的通信,设备id通过adb devices获取。

import uiautomator2 as u2

phone_id = input("phone id:")
d = u2.connect(phone_id)
print(d.device_info)

② 根据微信app控件信息尝试自动化打开微信朋友圈并刷新

# 打开微信app,等待界面加载完成
sess = d.app_start('com.tencent.mm', wait=True)  # start

d(resourceId="com.tencent.mm:id/icon_tv", text="发现").click()    # 点击‘发现’控件
d(resourceId="com.tencent.mm:id/m38").click()                    # 点击‘朋友圈’控件
d(resourceId="com.tencent.mm:id/n9a").exists()                   # 判断朋友圈界面是否存在

# 刷新朋友圈
if d(resourceId="com.tencent.mm:id/ef").exists():
    d.double_click(0.522, 0.066)
d.swipe_ext('down', 3)

③ 创建一个抓取朋友圈个体内容的类

# 创建Dxpath类,封装一些操作安卓app的lxl元素的方法
class Dxpath:
    # 初始化安卓设备信息
    def __init__(self, d):
        self.d = d

# 定义一个通过参数返回app界面特定元素的方法
    def dxpath(self, arg):
        # 捕获当前屏幕的所有UI元素及其属性,并以XML的形式输出
        xml_content = self.d.dump_hierarchy()
        # 将字符串形式的 XML 数据解析成一个ElementTree对象
        root = etree.fromstring(xml_content.encode('utf-8'))
        return root.xpath(arg)

# 定义一个通过元素其他参数返回元素文本内容的方法
    def dxpath_text(self, t, arg, one=True, time_out=False):
        # t为dxpath迭代的对象
        # 定义文本参数的xpath格式
        args = '{}/@text'.format(arg)
        text = []
        # 将t对象中所有符合args规则的文本导入到列表中
        for txt in t.xpath(args):
            text.append(str(txt))
        # one/time_out的布尔值是根据所需要的内容来的:网名、数据内容或朋友圈日期
        if one:
            return text[0]
        elif time_out:
            return text[2]
        else:
            return text

    # 判断输入的xpath路径下是否有元素
    def dxpath_exist(self, t, arg):
        element = self.dxpath(arg)
        return len(element) > 0

④ 进行朋友圈数据内容存储

# 创建一个类用来存储朋友圈的三个属性信息
class Item(object):
    name = None  # 更:网名
    comment = None  # 更:数据内容
    date = None  # 朋友圈日期


data_value = set()  # 记录已填入数据
items = []  # 数据汇总

⑤ 判断条件循环输出朋友圈数据,将个体项目、网名、文章内容、日期信息的属性写上,滑动操作可以让朋友圈数据爬取的内容不断刷新。

# 创建手机类对象(我是小米所以用的mi作为变量)
mi = Dxpath(d)

# 给予判断的初始布尔值
match = False

# 开始输出
while not match:
    # 循环每一个朋友圈个体内容
    for t in mi.dxpath('//*[@resource-id="com.tencent.mm:id/n9a"]'):
        try:
            # 分别找到该个体的网名、数据内容和朋友圈日期
            comment = mi.dxpath_text(t, './/*[@resource-id="com.tencent.mm:id/cut"]')
            name = mi.dxpath_text(t, './/*[@resource-id="com.tencent.mm:id/kbq"]')
            # 用weditor发现date的日期文本数据在text[2]中,所以更改对应布尔值
            date = mi.dxpath_text(t, './/*[@resource-id="com.tencent.mm:id/n93"]/', one=False, time_out=True)
            # 当日期数据为一天前内容时,停止循环
            match = re.search(r"天", date)
            # 确保数据不重复并且非朋友圈广告信息
            if comment not in data_value and not mi.dxpath_exist(t,'.//*[@resource-id="com.tencent.mm:id/egc"]'):  # 不能是广告
                print("抓取到{}朋友圈数据:\n{}\n时间为:{}".format(name, comment, date))
                item = Item()
                item.name = name
                item.comment = comment
                item.date = date
                items.append(item)
                data_value.add(comment)
                # 输出目前总共收集了多少天数据
                print('*' * 25 + str(len(data_value)))
        except:
            pass
    # 滑动
    d.swipe(300, 800, 300, 300, 0.1)

ok整体框架完成了

四、整体代码与运行结果展示

整体代码如下(当然代码结构比较混乱,功能模块也没有做封装处理,整体实现demo大致如此,大家有兴趣可以做优化和整理)

import uiautomator2 as u2
import time
from lxml import etree
import re

# 创建Dxpath类,封装一些操作安卓app的lxl元素的方法
class Dxpath:
    # 初始化安卓设备信息
    def __init__(self, d):
        self.d = d

# 定义一个通过参数返回app界面特定元素的方法
    def dxpath(self, arg):
        # 捕获当前屏幕的所有UI元素及其属性,并以XML的形式输出
        xml_content = self.d.dump_hierarchy()
        # 将字符串形式的 XML 数据解析成一个ElementTree对象
        root = etree.fromstring(xml_content.encode('utf-8'))
        return root.xpath(arg)

# 定义一个通过元素其他参数返回元素文本内容的方法
    def dxpath_text(self, t, arg, one=True, time_out=False):
        # t为dxpath迭代的对象
        # 定义文本参数的xpath格式
        args = '{}/@text'.format(arg)
        text = []
        # 将t对象中所有符合args规则的文本导入到列表中
        for txt in t.xpath(args):
            text.append(str(txt))
        # one/time_out的布尔值是根据所需要的内容来的:网名、数据内容或朋友圈日期
        if one:
            return text[0]
        elif time_out:
            return text[2]
        else:
            return text

    # 判断输入的xpath路径下是否有元素
    def dxpath_exist(self, t, arg):
        element = self.dxpath(arg)
        return len(element) > 0


# 创建一个类用来存储朋友圈的三个属性信息
class Item(object):
    name = None  # 更:网名
    comment = None  # 更:数据内容
    date = None  # 朋友圈日期


data_value = set()  # 记录已填入数据
items = []  # 数据汇总

# 正式开始,用u2库进行操作
phone_id = input("phone id:")
d = u2.connect(phone_id)
print(d.device_info)
mi = Dxpath(d)
# 打开微信app,等待界面加载完成
sess = d.app_start('com.tencent.mm', wait=True)  # start

d(resourceId="com.tencent.mm:id/icon_tv", text="发现").click()    # 点击‘发现’控件
d(resourceId="com.tencent.mm:id/m38").click()                    # 点击‘朋友圈’控件
d(resourceId="com.tencent.mm:id/n9a").exists()                   # 判断朋友圈界面是否存在
time.sleep(2)
# 刷新朋友圈
if d(resourceId="com.tencent.mm:id/ef").exists():
    d.double_click(0.522, 0.066)
d.swipe_ext('down', 3)
time.sleep(5)

match = False

while not match:
    # 循环每一个朋友圈个体内容
    for t in mi.dxpath('//*[@resource-id="com.tencent.mm:id/n9a"]'):
        try:
            # 分别找到该个体的网名、数据内容和朋友圈日期
            comment = mi.dxpath_text(t, './/*[@resource-id="com.tencent.mm:id/cut"]')
            name = mi.dxpath_text(t, './/*[@resource-id="com.tencent.mm:id/kbq"]')
            # 用weditor发现date的日期文本数据在text[2]中,所以更改对应布尔值
            date = mi.dxpath_text(t, './/*[@resource-id="com.tencent.mm:id/n93"]/', one=False, time_out=True)
            # 当日期数据为一天前内容时,停止循环
            match = re.search(r"天", date)
            # 确保数据不重复并且非朋友圈广告信息
            if comment not in data_value and not mi.dxpath_exist(t,'.//*[@resource-id="com.tencent.mm:id/egc"]'):  # 不能是广告
                print("抓取到{}朋友圈数据:\n{}\n时间为:{}".format(name, comment, date))
                item = Item()
                item.name = name
                item.comment = comment
                item.date = date
                items.append(item)
                data_value.add(comment)
                # 输出目前总共收集了多少天数据
                print('*' * 25 + str(len(data_value)))
        except:
            pass
    # 滑动
    d.swipe(300, 800, 300, 300, 0.1)

# 输出汇总数据
print(items)

运行结果如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值