python分析QQ群聊天记录全过程,从获取到可视化

news2024/11/26 4:38:35

随着社交媒体的兴起,QQ群成为了人们交流的重要平台,而提取这些数据可以帮助我们了解用户关注的重点和行为,那么如何获取QQ群聊天记录呢?如何对其进行处理并分析呢?

这是一套完整的流程,从选定的QQ群中获取记录,并对其进行处理及可视化。

其中包括:

共有多少人发过言,分别是谁
谁发表的言论最多
聊天密度周、日期、小时分布
活跃天数最多的用户(在群里说话天数最多的用户)
用户连续活跃天数(用户在群里连续说话天数)
每个用户在群里连续说话最长天数以及时间段
群里聊的最多的话题

目录

  • 1 聊天记录获取
  • 2 聊天记录读取并查看
  • 3 数据处理
    • 3.1 使用正则提取信息
    • 3.2 拆分记录头并处理记录内容
      • 3.2.1 将日期、用户名、QQ号分离出来
      • 3.2.2 处理内容
      • 3.2.3 删除无用内容
  • 4 探索分析
    • 4.1 共有多少人发过言,分别是谁
    • 4.2 谁说话做多,说了什么
    • 4.3 聊天密度分布
      • 4.3.1 聊天密度周分布
      • 4.3.2 聊天密度日期分布
      • 4.3.3 聊天密度小时分布
    • 4.4 在群里说话天数最多的用户
    • 4.5 用户在群里连续说话天数
    • 4.6 每个用户在群里连续说话最长天数以及时间段
    • 4.6 群里聊的最多的话题

1 聊天记录获取

  1. 选中需要进行分析的群聊,鼠标右击——查看消息记录
    在这里插入图片描述
  2. 在“消息管理器”中,在选中的群上面右击——导出消息记录
    在这里插入图片描述
  3. 将消息记录保存为txt文件
    [点击并拖拽以移动]

2 聊天记录读取并查看

import pandas as pd
import numpy as np
#上下文管理语句 
with open('E:\学习交流群.txt',mode = 'r',encoding='utf-8') as f:
    txt = f.read() #返回的是字符串
txt  #所有内容组成的字符串

在这里插入图片描述

3 数据处理

从源文件中我们可以看到内容中有以下几部分且比较直观,时间、用户名、QQ号以及聊天内容,而python读取的文件内容看起来极不方便。
在这里插入图片描述

3.1 使用正则提取信息

为了后面更好的分析探索数据,我们需要将读取到的字符串进行处理,存储为dataframe

import re
#正则表达式
re_pat = '[\d-]{10}\s[\d:]{8}\s.*[\)>]'#数字或者'-'共出现10位,\s(匹配任意的空白符)分开,数字或':'共8位,\s分开,任意字符以')'或'>'结尾
log_title_list = re.findall(re_pat,txt) #记录头
log_title_list

在这里插入图片描述

log_content_list = re.split(re_pat,txt) #记录内容,re_pat做分隔符,将文本进行分割
log_content_list

在这里插入图片描述

#查看两个列表量级是否一致
len(log_title_list)
len(log_content_list)

在这里插入图片描述

两个数据量并不一致,因为内容导出时,会有最前面的一行消息记录故需要做删除处理

#头与内容数量应保持一致,现发现内容多1,是因为多了第1行
log_content_list.pop(0) #删除第一行
len(log_content_list)

在这里插入图片描述

删除后,记录头与记录内容的数量已一致,将其存储到dataframe中

#将记录头及记录内容存储到dataframe中
df = pd.DataFrame()
df['title'] = log_title_list
df['content'] = log_content_list
df

在这里插入图片描述

3.2 拆分记录头并处理记录内容

3.2.1 将日期、用户名、QQ号分离出来

#分离日期、用户名、QQ号
df['time'] = df['title'].str.findall('\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}').str.get(0)
df['name'] = df['title'].str.findall('\d{2}:\d{2}:\d{2}(.*)[\(<]').str.get(0) #提取用户名 从时间开始一直到'('为止,要的数据用'()'括起来
df['QQ'] =  df['title'].str.findall('[\(<]([\dA-z\.@]*)[\)>]').str.get(0) #以'('或'<'开头,以')'或'>'结尾,中间部分可以是数字、字母、.、@的组合

在这里插入图片描述

3.2.2 处理内容

#删除空格
df['content'] = df['content'].str.replace('\n','')

在这里插入图片描述

3.2.3 删除无用内容

注意:删除、增加、拼接行数据后,需重置索引

  1. title列已经被拆分为“time”、“name”、“QQ”,在这里不保留原始数据,故将“title”列删除(可以根据实际情况选择保留与否)
#title列内容已被拆分,可以进行删除
df.drop(['title'],axis = 1,inplace = True)
df

在这里插入图片描述

  1. 删除无用的消息记录,比如系统提示信息等
# 单个的时候 !=     多个的时候isin取反
df = df[~df['QQ'].isin(['1000000','10000'])] 
df.reset_index(drop = True,inplace = True)

在这里插入图片描述

4 探索分析

4.1 共有多少人发过言,分别是谁

QQ号作为唯一标识,故通过QQ号来分析

df['QQ'].nunique() #去重后的计数
df['QQ'].unique() #去重后的数据列举出来

在这里插入图片描述

4.2 谁说话做多,说了什么

逻辑:消息出现一条则认为其说了一次话,按照QQ号对条数进行计数

#谁说话最多
# 也可以计数后直接使用 nlargest(1) 选出聊天内容最多的QQ号
#df['QQ'].value_counts().nlargest(1).index[0]
df['QQ'].value_counts() 

在这里插入图片描述

在这里插入图片描述

#话痨说了什么
df[df['QQ'] =='1520034124']['content'].str.cat()

在这里插入图片描述

4.3 聊天密度分布

从周、日期、小时三个角度查看聊天情况

df.time #因为是正则匹配出来的,时间并不是标准的日期格式,需要进行处理
#转换为标准的时间
df['time'] = pd.to_datetime(df['time'])

在这里插入图片描述

4.3.1 聊天密度周分布

#若图表无法在notebook中显示出来,需要执行下面两行代码
#打开pylab模式,IPython中执行
%pylab
%matplotlib inline
df['weekday'] = df['time'].dt.weekday+1
df['weekday'].value_counts().sort_index().plot(kind='bar')

在这里插入图片描述

4.3.2 聊天密度日期分布

在这里插入图片描述

4.3.3 聊天密度小时分布

在这里插入图片描述

4.4 在群里说话天数最多的用户

逻辑:只要发过一条记录,就是在群里说话了,与当天发过多少消息无关,故需要“QQ”与“date”两列去重后统计次数

#QQ号与日期列去重
df.drop_duplicates(subset = ['QQ','date'])['QQ'].value_counts()

在这里插入图片描述

4.5 用户在群里连续说话天数

#数据 按照 'QQ','date' 两列 去重
df1 = df.drop_duplicates(subset = ['QQ','date'])[['QQ','date']]
df1.reset_index(drop = True,inplace = True)
# 将聊天时间列转换为日期类型
df1['date'] = pd.to_datetime(df1['date'])
# 对数据进行排序
df1 = df1.sort_values(by='date')
# 统计用户连续聊天的天数
result = df1.groupby('QQ')['date'].apply(lambda x: (x.diff().dt.days != 1).cumsum().value_counts())
result

在这里插入图片描述

4.6 每个用户在群里连续说话最长天数以及时间段

#数据 按照 'QQ','date' 两列 去重
df1 = df.drop_duplicates(subset = ['QQ','date'])[['QQ','date']]
# 将聊天时间列转换为日期类型
df1['date'] = pd.to_datetime(df1['date'])
# 对数据进行排序
df1.sort_values(by=['QQ','date'], inplace=True)
df1.reset_index(drop = True,inplace = True)
# 计算连续聊天的天数、起始时间和结束时间的函数
def calculate_consecutive_days(group):
    if len(group) > 1:
  		#计算相邻日期之间的差异
        consecutive_days = group['date'].diff().dt.days
        #返回一个布尔值序列,指示日期差异是否不等于1
        consecutive_days = consecutive_days.fillna(0) != 1
        #计算布尔值序列的累积和
        consecutive_days = consecutive_days.cumsum()
		#最大连续天数
        max_consecutive_days = consecutive_days.value_counts().max()
      #最大连续天数对应id  
        id_max_consecutive_days = consecutive_days.value_counts().idxmax()
        
        start_index = np.argmin(consecutive_days[consecutive_days.values == id_max_consecutive_days])
        end_index = start_index + max_consecutive_days -1

        start_date = group.loc[start_index]['date'].strftime('%Y-%m-%d')
        end_date = group.loc[end_index]['date'].strftime('%Y-%m-%d')

        return pd.Series([max_consecutive_days, start_date, end_date], index=['最长连续聊天天数', '起始时间', '结束时间'])

    elif len(group) == 1:  # 处理只有一次聊天记录的情况
        date = group['date'].iloc[0].strftime('%Y-%m-%d')
        return pd.Series([1, date, date], index=['最长连续聊天天数', '起始时间', '结束时间'])
    else:
        return pd.Series([0, np.nan, np.nan], index=['最长连续聊天天数', '起始时间', '结束时间'])
result = df1.groupby('QQ').apply(calculate_consecutive_days).reset_index()

result

在这里插入图片描述

4.6 群里聊的最多的话题

逻辑:先将聊天信息拼接起来,因为聊过过程中会有各种标题点符号等没有意义的词语,所以去除停用词之后,再进行分词,并用词云图展示

#内容拼接起来
content_txt = df['content'].str.cat(sep = '。')
#加载停用词
with open('stopwords.txt',encoding = 'utf-8') as file:
    stopword = file.read()
import jieba
words = jieba.lcut(content_txt)
words = [word for word in words if (word not in stopword.split('\n'))&(len(word)>1)]
#大致看看是否已将无用信息去除完毕,若没有还需进行清洗
word_s = pd.Series(words).value_counts()

在这里插入图片描述在这里可以发现,图片、表情等信息无法真实展现处理,而这些词对我们进行话题探索并没有什么意义,所以从拼接好的内容中,将“图片”、“表情”去除后,再进行分词而后分析。

content_txt = content_txt.replace('[图片]','').replace('[表情]','')

生成词云图pyecharts网址

#pycharts 里面提供的数据需要是 二维列表
data = word_s.reset_index().values.tolist()
#词云图 
import pyecharts.options as opts
from pyecharts.charts import WordCloud

(
    WordCloud()
    .add(series_name="QQ", data_pair=data, word_size_range=[20, 66])
    .set_global_opts(
        title_opts=opts.TitleOpts(
            title="QQ", title_textstyle_opts=opts.TextStyleOpts(font_size=23)
        ),
        tooltip_opts=opts.TooltipOpts(is_show=True),
    )
    .render("QQ_wordcloud.html")
)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/701326.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023最新版SpringCloudAlibaba笔记,把微服务玩的出神入化

SpringCloud Alibaba 大家都知道&#xff0c;新的东西出现必然是因为市场的需求。由于 SpringCloud 版本更新较快&#xff0c;日积月累之下产生了许多的 Bug&#xff0c;所以 SpringCloud 微服务实现方式&#xff1a;Spring Cloud Netflix 自然而然地进入了维护状态&#xff0…

java计算器拓展

源代码&#xff1a; package shixun; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.JButton; import javax.swing.SwingConstants;import java.awt.event.ActionListener; import java.awt.event.ActionEvent; import java.awt.Font; impor…

Golang项目引入第三方依赖库

基本目录 第一步&#xff1a; 初始化依赖&#xff0c;切换到项目根目录下面&#xff0c;执行一下命令&#xff0c;g6 为 module 的名称 go mod init g6 生成 go.mod 文件 module g6 go 1.20 将来我们项目的所有依赖都会依赖于 g6 第二步&#xff1a; 引入第三方依赖 &qu…

禁烟警示器报警器

本例介绍的禁止吸烟警示器&#xff0c;可用于家庭居室或各种不宜吸烟的场合 (例如医院、会议室等)。当有人吸烟时&#xff0c;该禁止吸烟警示器会发出"请不要吸烟!"的语言警示声&#xff0c;提醒吸烟者自觉停止吸烟。 一、电路工作原理 电路原理如图 5 所示。 该…

3-如何创建等比数列?【视频版】

目录 问题视频解答 问题 视频解答 点击观看&#xff1a; 3-如何创建等差数列&#xff1f;

一文带你了解WebSocket与技术原理

文章目录 一、技术发展史二、什么是WebSocket三、WebSocket与Socket四、WebSocket 机制五、WebSocket API简单实现 一、技术发展史 在了解WebSocket之前&#xff0c;我们先了解这项技术的发展史&#xff0c;它可以追溯到2008年&#xff0c;当时HTML5规范中引入了该协议作为一种…

【Java】Java核心 80:Git 教程(3)初始化工作区 add与commit

文章目录 04.GIT本地操作-初始化工作区目标内容小结 05.GIT本地操作-add与commit目标内容小结 在Git中&#xff0c;初始化工作区并使用add和commit命令是进行版本控制的基本操作。 下面是对这些操作的简要解释&#xff1a; 初始化工作区&#xff1a;在使用Git之前&#xff0c…

【语音播报】没时间刷新闻热搜?让博灵语音通知终端读给你听!-声光报警灯|语音播报器|Modbus报警灯|网口语音播报|网络语音播报器

背景 每天上班太忙碌&#xff0c;没有时间刷微博&#xff0c;新闻发展的太快&#xff0c;生怕错过微博热搜&#xff0c;看着手边的博灵语音通知终端&#xff0c;决定自己写一个脚本&#xff0c;让它给我读新闻&#xff01; 少废话&#xff0c;先看东西 实现了以下效果 每90…

02 快速定位关键点并爆破

vm所进行的代码级的保护是对于软件保护的最后一层 1、API断点法 如何切换到程序的代码节的位置&#xff1f; 》od点击e->双击xxx.exe即可 程序需要读取文本框输入的内容&#xff0c;所以肯定会调用GetWindowText函数&#xff0c;所以可以ctrlg然后输入GetWindowText进行…

ChatGPT 和 Elasticsearch:分面、过滤和更多上下文

作者&#xff1a;Luca Wintergerst 在最近的一篇博客文章中&#xff0c;我们讨论了 ChatGPT 和 Elasticsearch 如何协同工作以帮助更有效地管理专有数据。 通过利用 Elasticsearch 的搜索功能和 ChatGPT 的上下文理解&#xff0c;我们演示了如何改进结果。 在这篇文章中&#…

制造业数字化转型难?低代码带来曙光

概要&#xff1a;制造业企业在数字化转型中一直面临着许多困难和挑战&#xff0c;中小企业更是如此。天翎低代码平台通过自身可视化设计、私有化部署、灵活性、扩展性和兼容性等特性&#xff0c;帮助制造业企业更好地完成数字化转型目标。不仅如此&#xff0c;天翎还推出了微鳄…

iview tree树形控件多选,自定义内容

项目中需要一个iview框架的树形控件,需要里面包含以下功能 1、控件宽度可展开,可缩小2、树形控件可搜索,并且定位到搜索的节点3、控件可以一键勾选,一键取消4、控件图标自定义5、 点击最后一个节点时可以进入到二级节点,点击上一节点可返回完整代码:listToTree文件 效果图: 具…

标准模版库 知识点总结 C++程序设计与算法笔记总结(八) 北京大学 郭炜

标准模版库 https://blog.csdn.net/shaozheng0503/article/details/129101932?ops_request_misc%257B%2522request%255Fid%2522%253A%2522168802585416800211563089%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id1688025854168…

前端判断img图片未能正确加载时显示一个默认图片。img标签onerror事件设置了本地默认图片还是不显示的问题

前端img标签中引用后端交给的图片地址时&#xff0c;有可能这个路径下图片被删除或者损坏了&#xff0c;那么页面在加载img图片时就显示为&#xff0c;太丑了。 img标签有个onerror事件&#xff0c;就是当图片未被正确加载的时候调用此事件&#xff0c;写的时候在onerror事件里…

安装国产系统Kylin-Desktop实战

前言 随着国产化系统的呼声越来越高&#xff0c;再加上今年6月红帽公司发表声明&#xff0c;只有付费才能拿到代码的通告&#xff0c;学习国产化势在必行。 在众多的国产化系统中&#xff0c;我选择了排名比较高的系统&#xff0c;今天我们就一起来安装下麒麟的操作系统 &…

习题-集合框架

目录 1.打印信息 2.ArrayList的使用 User类 测试类 3.Set的使用 汽车类 测试类 4.ArrayList使用 5.新闻 新闻类 测试类 6.返回索引 7.删除重复QQ 8.Map集合操作 9.成绩排序 学生类 测试类 10.Map基础题 学员类 测试类 11.遍历Map综合-国家名称 12.Collec…

1. Linux手写简单的线程池

目录 一、线程池的概念二、线程池的核心组件三、数据结构设计1、任务队列2、线程池 四、接口设计1、创建线程池2、销毁线程池3、抛出任务的接口 五、实现一个线程池及测试1、测试单生成者——多消费者2、测试多生产者——多消费者3、thrd_pool.h4、thrd_pool.c5、main.c6、thrd…

<C语言> 操作符

1.算术操作符 加法&#xff08;&#xff09;&#xff1a;用于将两个操作数相加。减法&#xff08;-&#xff09;&#xff1a;用于将第一个操作数减去第二个操作数。乘法&#xff08;*&#xff09;&#xff1a;用于将两个操作数相乘。除法&#xff08;/&#xff09;&#xff1a;…

使用JavaScript获取随机数序列

使用Javascript 生成随机数 要在 Javascript 中生成随机数&#xff0c;可以使用 Math 对象的 random() 方法。该方法返回一个大于等于 0 小于 1 的伪随机浮点数。 Javascript中的 Math.random() 函数是一个用于生成随机数的内置函数。 MDN 官方解释 Math.random() 函数返回…

idea常用快捷方式,保姆级!图文并茂【建议收藏】

大家好&#xff0c;我是三叔&#xff0c;很高兴这期又和大家见面了&#xff0c;一个奋斗在互联网的打工人。 给大家分享一下idea在开发过程中使用的快捷方式把&#xff0c;可以极大的提升生产力&#xff0c;提高自己的开发速度&#xff0c;需要在开发中不断地使用&#xff0c;…