基于DataEase的QQ群数据分析

本文最后更新于 2024年1月21日 下午

基于DataEase的QQ群数据分析

云计算系统期末设计

项目介绍

本次项目所选赛道为 数据分析与可视化

使用从个人QQ群采集的数据进行分析,包括聊天记录、群成员信息等,将数据存储于云数据库服务,并使用DataEase网页版进行数据分析可视化呈现

分享的知乎链接:

https://zhuanlan.zhihu.com/p/679053445

考虑到本次项目数据的隐私性,并未录制视频,也并未将源码上传至Github

项目文件

.
├── cut_word.py    // 用以分词
├── db.py          // 用以创建数据表
├── gocqhttp       // 仿QQ客户端
├── imgs
├── README.md      // 项目报告
├── README.pdf     // 项目报告
├── record.py      // 用以记录QQ群数据
└── stopwords.txt  // 中文停用词,用以分词

项目过程

一、准备数据集

1. 如何获取QQ群数据

由于QQ官方并未提供API(个人开发认证仅提供频道API),因此需要考虑获取QQ群数据的方式

经过多次探索,可能的获取方式有以下几种:

  • 通过模拟点击获取聊天记录
  • 通过QQ自带的聊天记录导出功能获取
  • 使用HOOK技术拦截QQ内部函数
  • 使用第三方QQ客户端

考虑到获取消息的方便性,我们使用最后一种方法,这里选择了go-cqhttp

go-cqhttp原本的目的是为QQ机器人服务的,它通过模拟一个QQ客户端,接受QQ服务器发来的消息,同时将API引出用以服务机器人,而对于我们项目来说,我们可以利用它的API来获取消息

在阅读相关文档后,我们使用反向websocket的方式,即通过python创建一个websocket服务端,然后通过go-cqhttp登陆个人QQ,登陆后它会作为客户端连接我们创建的服务端,并且实时上报接受到的消息,这样,我们就可以通过python代码处理我们接受到的消息

async def server(websocket, _):
    print("Server is connected...")

    # Get group list and members
    await websocket.send(json.dumps({"action": "get_group_list", "echo": "groups"}))

    while True:
        raw = await websocket.recv()
        await handle_response(websocket, raw)

start_server = websockets.serve(server, ip, 2024)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

除了消息之外,我们可以通过go-cqhttp提供的API获取其他信息,如群成员信息等。另外由于本次项目基本使用云的环境,所以仅仅考虑群消息的获取而不考虑私聊消息

令人遗憾的是,作者已经放弃了对go-cqhttp的维护(由于QQ官方针对协议库的围追堵截, 不断更新加密方案, 我们已无力继续维护此项目.),虽然目前此方案仍然可行,但是已经不能保证未来的稳定使用。但是,QQNT的出现(Electron版QQ)让第三种方案更易于实现

2. 连接云数据库

在解决获取消息的问题后,我们要考虑如何存储消息。最常用的办法当然是使用数据库,另外考虑到DataEase接入数据源需要云数据库,因此我们使用Ucloud来提供云数据服务,并选择Mysql数据库。

我们首先租用一个Mysql数据库,但是其IP是内网隔离的,因此我们还需要租用一个弹性网络。我们通过端口转发的方式将SQl服务暴露给外网:

3. 创建数据表

之后,我们便可以组织数据表的结构。

我们使用四张数据表,结构定义如下(python代码中使用ORM的方式操纵数据库)

class User(Base):
    __tablename__ = "user"

    user_id = Column(BigInteger, primary_key=True)  # QQ ID
    group_id = Column(Integer, primary_key=True)
    name = Column(String(100))
    card = Column(String(100))
    sex = Column(String(10))
    age = Column(Integer)
    level = Column(Integer)
    join_time = Column(Integer)
    last_sent_time = Column(Integer)


class Group(Base):
    __tablename__ = "group"

    group_id = Column(Integer, primary_key=True)  # Group ID
    group_name = Column(String(100))
    group_create_time = Column(Integer)
    group_level = Column(Integer)
    member_count = Column(Integer)


class Message(Base):
    __tablename__ = "message"

    message_id = Column(Integer, primary_key=True)
    time = Column(Integer)
    user_id = Column(BigInteger)
    group_id = Column(Integer)
    raw_message = Column(String(5000))
    anonymous = Column(Boolean)
    emotion = Column(Float)


class Word(Base):
    __tablename__ = "word"

    user_id = Column(BigInteger, primary_key=True)
    group_id = Column(Integer, primary_key=True)
    word = Column(String(50), primary_key=True)
    count = Column(Integer)

分别对应群成员信息、群信息、群消息和群消息分词词频统计

4. 记录数据

由于go-cqhttp并未提供获取群所有历史消息的API,因此我们需要在我们的程序中实时记录群消息。

在创建的websocket服务端中,当客户端连接后,我们即向其发送获取所有群信息,以及所有群成员信息的API,之后,我们循环处理收到的每一条上报信息,根据上报类型,将数据存储于不同的数据表,另外,我们还针对消息利用SnowNLP获取其情感值,一并存储于数据表中(代码详见record.py

另外为了后续方便进行词云图展示,我们将所有消息利用jieba库进行分词,并将分词结果进行词频统计,然后存储于word数据表中(代码详见cut_word.py)

最后还需注意,我们需要将数据库的编码格式改为utf8mb4,以适应群成员昵称

5. 部署

我们首先运行record.py代码,然后运行go-cqhttp客户端,即可实时将消息记录到云数据库中,记录过程如下:

当然我们也可以将其部署到云主机上,从而能够持续不断稳定的记录消息。由于本人使用linux操作系统,将整个过程编写为服务,本地仍然可以保证长时间的部署

二、数据可视化

我们通过DataEase进行数据的可视化分析,首先添加数据源:

然后创建仪表盘和数据集

之后我们便可以根据自己需要的数据表形式,进行sql查询:

然后在仪表盘中根据sql查询的数据集创建相应的视图

项目结果

项目最终制作的仪表盘如下:

其中最上方的三个表属于全局分析(群人数排名、群发言数排名、发言数与人数关系),可以宏观展示自己所加的所有群的活跃度

而在关系表散点图中,左上方的点表示尤其活跃(群人数少,群发言数多),而右下方的点则表示不活跃的群

接着,在左边放置了一个文本下拉框组建,我们可以选择一个具体的群:

之后可以看到根据所选择的群,呈现出的群成员发言排名、群成员性别分布以及群消息词云图,这样可以帮助我们查看群中活跃的成员、性别比例、讨论消息的主要方向

而在仪表盘最中间的部分,放置了群发言总数与平均情感值随时间的变化,最上方呈现的是最新的时间,通过此图我们可以看到群活跃度随时间的变化以及情绪值的变化:

从图中我们可以看到本人所加的群中普遍在夜晚的消息数量较多

而在右下角,放置了一个可以选择所有群成员的文本下拉框:

我们可以选择一个具体的群成员,然后查看他发言的消息以及情绪值随时间的变化,以了解他发言活跃度的变化,以及在一天中何时最活跃,另外还有他所发消息的词云图,以了解他的发言的关注点

比如对于图中这位用户,我们就发现他在凌晨时发消息较多,并且情绪值也较高,就可以推断他属于夜猫子类型,而从词云图中,我们也可以推断他与初中的关系较大

项目总结

一、功能完备性

我们通过部署websocket服务端与gocqhttp客户端,持续记录QQ群消息至数据库,然后通过DataEase制作了能够实时更新的仪表盘,从而快速、实时了解自己的群聊信息

整个仪表盘刚好可以平铺1080P分辨率的整个网页,通过这些图表可以迅速了解自己所有群、单个群、群成员的活跃状态、聊天的关注点

二、技术难点

难点之一便是如何获取QQ群消息,而项目选择使用gocqhttp客户端提供的API来持续记录消息

其次便是云数据库的搭建以及与DataEase的对接

最后便是较为复杂的SQL编写,以适应不同的图表创建

三、创新性

1. 实时性

我们通过将项目部署到云主机和云数据库上,并且接入网站前端,可以持续不断的记录数据,而前端的数据可视化也是实时更新的

2. 普适性

由于项目数据属于个人QQ群,分析的结果对个人更有价值,所以项目应当具备普适性,即可以方便的为所有人提供属于自己的QQ群数据可视化与分析

而实际上这也是易于实现的,而需要考虑的问题仅为隐私性问题

首先用户可以自行提供一个可以连接的云数据库,然后通过项目的代码与gocqhttp客户端将数据上传,之后可以套用本次项目创建的仪表盘模板,从而获得属于自己的QQ群数据可视化

更进一步,我们可以搭建一个云服务,只要用户提供QQ账号,以及可选的云服务器,我们就可以返还仪表盘链接,用户即可看到属于自己的QQ群数据分析


基于DataEase的QQ群数据分析
https://gentlecold.top/20240121/qq-groups-analysis-with-dataease/
作者
GentleCold
发布于
2024年1月21日
许可协议