美文网首页
用python【itchat】库获取群聊信息的正确姿势

用python【itchat】库获取群聊信息的正确姿势

作者: PowerQuery | 来源:发表于2019-11-10 12:01 被阅读0次

我在《昆明单车骑行群体分析报告(2019版)》中曾用python的itchat模块抓取了我加入的昆明单车群信息,并做了简要分析。

在持续十来天抓取群数据的时候,我发现一个奇怪现象,就是有一个群神出鬼没,有时候能抓到它的信息,有时候不能。


伸出规模的乐途群

从图中可以看到,监测的12天中,乐途群的信息出现了5次,有七天没抓到它的数据。

在我的另一个小号中,我写了一个帖子,对这个“神奇”的现象用我惯有的笔法夸张了一番《骑行之苦,苦在恨水;骑行之乐,乐在乐途》。

我检查了各个群的设置,都是一模一样;我检查了是否itchat有抓取的群数量限制,答案是否定的;我甚至检查了是不是群主为了好玩不定时把我踢出群又把我拉回去。

很明显都是不是以上原因。原因一定出在代码上。

今早我再次检查了代码,终于找到原因所在。

先贴上原来的代码【代码是我在网上抄的,做了简单的调整以适合我的需要】:

#!/usr/bin/env python
# coding: utf-8

import itchat
from itchat.content import TEXT
from itchat.content import *
import sys
import os
import socket
import time
import pandas as pd
import re
import datetime

itchat.auto_login(hotReload=True)
friends = itchat.get_friends(update=True)[0:]

if socket.gethostname()=='xxxx':
    root=r'C:\Users\xxxx'
else:
    root=r'E:\OneDrive - xxx'

roomslist = []

def getroom_message(n):
    #获取群的 username,对群成员进行分析需要用到
    itchat.dump_login_status() # 显示所有的群聊信息,默认是返回保存到通讯录中的群聊
    RoomList =  itchat.search_chatrooms(name=n)
    if RoomList is None:
        pass
        #print("{0} group is not found!".format(name))
    else:
       # print('取得:',RoomList[0]['UserName'])
        return RoomList[0]['UserName']

def getchatrooms():
    #获取群聊列表
    roomslist = itchat.get_chatrooms()
    #print('列表',roomslist)
    return roomslist

for i in getchatrooms():
    roomslist.append(i['NickName'])

data=[]
for n in roomslist:
    ChatRoom = itchat.update_chatroom(getroom_message(n), detailedMember=True)
    for i in ChatRoom['MemberList']:
        data.append({'群名称':ChatRoom['NickName'],
                     '省份':i['Province'],
                     '用户名':i['NickName'],
                     'ID':i['UserName'],
                     '性别':i['Sex']})

df=pd.DataFrame(data)
df.to_csv((root+'\jupyter\群数据{}-{}-{}.csv').format(time.localtime().tm_year,time.localtime().tm_mon,time.localtime().tm_mday))

问题处在什么地方?

并不是itchat有bug,而是第一个函数getroom_message(n)出了问题。

RoomList =  itchat.search_chatrooms(name=n)

这一行中,原作者用了【name】作为参数传递给函数,我看网上其他资源都是用的这个函数以及这个参数。并且返回的是【RoomList】中第一个元素。

但是检查search_chatrooms()函数源代码可以发现【name】接收的是群聊的名称【NickName】,而【userName】接收的是群聊的id,并且【name】参数会把相似的群聊名称收集到【matchlist】中:

ef search_chatrooms(self, name=None, userName=None):
        with self.updateLock:
            if userName is not None:
                for m in self.chatroomList:
                    if m['UserName'] == userName:
                        return copy.deepcopy(m)
            elif name is not None:
                matchList = []
                for m in self.chatroomList:
                    if name in m['NickName']:
                        matchList.append(copy.deepcopy(m))
                return matchList

所以在我这个例子中,【NickName】包含“云南乐途户外骑行联盟”的有三个群聊,那么getroom_message(n)函数返回的RoomList就有3个群聊名称。由于在python中,list是可变的,其元素位置不固定,所以,当取RoomList的第一个元素时,返回的结果就可能是三个群聊名称中的任意一个而不一定是“云南乐途户外骑行联盟”。

所以我们需要在getroom_message(n)返回的RoomList中再一次判断,每一个元素的【NickName】键对应的值是不是等于参数【n】。

但我又发现,去改这个函数是没有意义的,整个这个getroom_message(n)函数都是多余的。

我们只需要想办法获取到群聊的【userName】,将其放入到一个list中,然后循环获取其相关信息即可,于是有了最终的代码。

最终代码

如下所示:

#!/usr/bin/env python
# coding: utf-8

import itchat
from itchat.content import TEXT
from itchat.content import *
import sys
import os
import socket
import time
import pandas as pd
import re
import datetime

itchat.auto_login(hotReload=True)
friends = itchat.get_friends(update=True)[0:]

if socket.gethostname()=='xxxx':
    root=r'C:\Users\xxxx'
else:
    root=r'E:\OneDrive - xxx'

roomslist = []

def getchatrooms():
    #获取群聊列表
    res = itchat.get_chatrooms()
    for each in res:
        roomslist.append(each['UserName'])
    return roomslist

data=[]
for group_id in getchatrooms():
    ChatRoom = itchat.update_chatroom(group_id, detailedMember=True)
    for i in ChatRoom['MemberList']:
        data.append({'群名称':ChatRoom['NickName'],
                     '省份':i['Province'],
                     '用户名':i['NickName'],
                     'ID':i['UserName'],
                     '性别':i['Sex']})

df=pd.DataFrame(data)
df.to_csv((root+'\jupyter\群数据{}-{}-{}.csv').format(time.localtime().tm_year,time.localtime().tm_mon,time.localtime().tm_mday))

与换来的代码相比,就仅仅是去掉了getroom_message(n)函数,稍微修改了一下getchatrooms()函数,把itchat.update_chatroom()函数的参数直接修改为roomslist中获取的群聊【userName】。

如此一来,名称相似的群聊再也不会神出鬼没地时而出现时而不出现了。

相关文章

网友评论

      本文标题:用python【itchat】库获取群聊信息的正确姿势

      本文链接:https://www.haomeiwen.com/subject/rmaobctx.html