Analisador de WhatsApp | Análise de bate-papo em grupo do WhatsApp usando Python

Conteúdo

Introdução

Hoje em dia, uma das plataformas de mídia social da moda é .... adivinha que? Um único WhatsApp😅. É uma das plataformas de mídia social favoritas entre todos nós devido às suas características atraentes. Tem mais do que 2 um bilhão de usuários em todo o mundo e “De acordo com uma pesquisa, um usuário médio gasta mais do que 195 minutos por semana no WhatsApp”. Quão terrível é a afirmação acima. Abandone todas essas coisas e vamos entender o que o analisador WhatsApp realmente significa.

WhatsApp Analyzer significa que estamos analisando nossas atividades em grupo do WhatsApp. Acompanhe nossa conversa e analise quanto tempo passamos ou dizemos isso “nós desperdiçamos” No whatsapp. O objetivo deste artigo é fornecer um guia passo a passo para criar nosso próprio analisador WhatsApp usando Python.. Aqui, usei diferentes bibliotecas Python que me ajudam a extrair informações úteis dos dados brutos. Aqui eu escolho meu grupo oficial de WhatsApp da universidade para analisar o padrão que os alunos estavam seguindo, então, em alguns instantâneos, excluo as informações de contato de meus professores universitários e colegas de classe, sinto muito. Vamos começar…

Bibliotecas necessárias:

  • Regex
  • Pandas
  • Matplotlib
  • Numpy
  • Seaborn
  • Data e hora
  • Emoji
  • Palavra nuvem
  • Heatmapz
  • NLTK
  • Completamente

Nós importamos todas essas bibliotecas:

import re
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import *
import datetime as dt
from matplotlib.ticker import MaxNLocator
import regex
import emoji
from seaborn import *
from heatmap import heatmap
from wordcloud import WordCloud , STOPWORDS , ImageColorGenerator
from nltk import *
de plotly import expresso como px

WhatsApp nos brinda la función de exportar chats, así que exportemos el chat y guardemos el archivo. En el paso 2, vamos criar um programa Python que irá extrair a data, o nome de usuário do autor, a hora, as mensagens do arquivo de bate-papo exportado e criar um quadro de dados, e irá armazenar todos os dados nele. Na realidade, a coleta de dados e a parte de pré-processamento são abordadas na etapa 2 e nas etapas subsequentes.

Vamos extrair todas as informações úteis. do arquivo de bate-papo usando regex:

### Código Python para extrair Data do arquivo de bate-papo 

def startsWithDateAndTime (s):
padrão = ‘^ ([0-9]+) (/) ([0-9]+) (/) ([0-9][0-9]), ([0-9]+) :([0-9][0-9]) (SOU | PM) – ‘
resultado = re.match (Padrão, s)
se o resultado:
volver verdadero
falso retorno

### Padrão regex para extrair nome de usuário do Autor.
def FindAuthor(s):
    padrões = [
        '([C]+):',                        # First Name
        '([C]+[s]+[C]+):',              # Nome próprio + Last Name
        '([C]+[s]+[C]+[s]+[C]+):',    # Nome próprio + Nome do Meio + Last Name
        '([+]d{2} d{5} d{5}):',         # Número móvel (Índia não.)
        '([+]d{2} d{3} d{3} d{4}):',   # Número móvel (EUA não.)
        '([C]+)[u263a-U0001f9999]+:',    # Nome e Emoji              
    ]
    pattern = '^' + '|'.join(Padrões)
    resultado = re.match(padronizar, s)
    se resultado:
        return True
    return False


### Data de extração, Tempo, Autor e mensagem do arquivo de bate-papo.
def getDataPoint(linha):   
    splitLine = linha.split(' - ') 
    dateTime = splitLine[0]
    encontro, tempo = dateTime.split(', ') 
    mensagem =" ".Junte(splitLine[1:])
    se FindAuthor(mensagem): 
        splitMessage = message.split(': ') 
        autor = splitMessage[0] 
        mensagem =" ".Junte(splitMessage[1:])
    outro:
        author = None
    return date, Tempo, autor, mensagem

### Finalmente, criando um dataframe e armazenando todos os dados dentro desse dataframe.
parsedData = [] # Lista para acompanhar os dados para que possa ser usado por um dataframe pandas
### Uploading exported chat file
conversationPath="WhatsApp Chat com TE Comp 20-21 Oficial.txt" # chat file
with open(conversationPath, codificação ="utf-8") como fp:
    ### Skipping first line of the file because contains information related to something about end-to-end encryption
    fp.readline() 
    mensagemBuffer = [] 
    encontro, Tempo, autor = Nenhum, Nenhum, None
    while True:
        linha = fp.readline() 
        se não linha: 
            break
        line = line.strip() 
        se iniciarWithDateAndTime(linha): 
            se len(mensagemBuffer) > 0: 
                parsedData.append([encontro, Tempo, autor, ' '.join(mensagemBuffer)]) 
            messageBuffer.clear() 
            encontro, Tempo, autor, message = getDataPoint(linha) 
            messageBuffer.append(mensagem) 
        outro:
            messageBuffer.append(linha)
df = pd.DataFrame(parsedData, colunas =['Date', 'Tempo', 'Author', 'Message']) # Inicializando um Dataframe do pandas.
### alterando o tipo de dados de "Encontro" coluna.
df["Encontro"] = pd.to_datetime(df["Encontro"])

Primeiro, olhe para o nosso conjunto de dados recém-nascido:

359031-3825112

Agora, vamos verificar as informações básicas do nosso conjunto de dados e limpar o conjunto de dados:

### Verificando a forma de conjunto de dados.
df.shape
### Verificando informações básicas do conjunto de dados
df.info()
### Não verificando. do nulo valores no conjunto de dados
df.isnull().soma()
### Verificando a parte principal do conjunto de dados
df.head(50)
### Verificando a parte final do conjunto de dados
df.tail(50)
### Descartando valores Nan do conjunto de dados
df = df.dropna()
df = df.reset_index(drop = True)
df.shape
### Não verificando. dos autores do grupo
df['Author'].agora()
### Verificando os autores do grupo
df['Author'].exclusivo()

Agora, nós pré-processamos nosso conjunto de dados e tentamos extrair informações úteis dele:

### Adicionando mais uma coluna de "Dia" para uma melhor análise, aqui usamos a biblioteca datetime que nos ajuda a fazer essa tarefa facilmente.
semanas = {
0 : 'Monday',
1 : 'Tuesday',
2 : 'Wednesday',
3 : 'Thrusday',
4 : 'Friday',
5 : 'Saturday',
6 : 'Sunday'
}
df['Day'] = df['Date'].dt.weekday.map(semanas)
### Reorganizando as colunas para melhor compreensão
df = df[['Date','Day','Tempo','Author','Message']]
### Alterar o tipo de dados da coluna "Dia".
df['Day'] = df['Day'].astype('category')
### Procurando conjunto de dados recém-nascidos.
df.head()
### Contando o número de letras em cada mensagem
df['Letter's'] = df['Message'].Aplique(lambda s : len(s))
### Counting number of word's in each message
df['Word's'] = df['Message'].Aplique(lambda s : len(s.split(' ')))
### Função para contar o número de links no conjunto de dados, ele vai adicionar coluna extra e armazenar informações nele.
URLPATTERN = r'(https?://S +)'
df['Url_Count'] = df. Message.apply(lambda x: re.findall(URLPATTERN, x)).str.len()
links = np.sum(Df. Url_Count)
### Função para contar o número de mídia no chat.
MEDIAPATTERN = r'<Mídia omitida>'
df['Media_Count'] = df. Message.apply(lambda x : re.findall(MEDIAPATTERN, x)).str.len()
media = np.sum(df.Media_Count)
### Procurando conjunto de dados atualizado
df

678652-3047988

Extraia estatísticas básicas do conjunto de dados:

total_messages = df.shape[0]
media_messages = df[df['Message'] == '<Mídia omitida>'].forma[0]
links = np.sum(Df. Url_Count)
imprimir('Group Chatting Stats : ')
imprimir('Total Number of Messages : {}'.format(total_messages))
imprimir('Total Number of Media Messages : {}'.format(media_messages))
imprimir('Total Number of Links : {}'.format(links))
700403-3859433

Extração de estatísticas básicas de cada usuário:

l = df.Author.unique()
para eu no alcance(len(eu)):
  ### Filtrando mensagens de um usuário específico
  req_df = df[df["Autor"] == l[eu]]
  ### req_df conterá mensagens de apenas um usuário específico
  imprimir(f'--> Estatísticas de {eu[eu]} <-- ')
  ### forma irá imprimir o número de linhas que indiretamente significa o número de mensagens
  imprimir('Total Message Sent : ', req_df.shape[0])
  ### Word_Count contém um total de palavras em uma mensagem. A soma de todas as palavras / Total de mensagens resultará em palavras por mensagem
  words_per_message = (np.sum(req_df['Word's']))/req_df.shape[0]
  w_p_m = ("%.3f" % volta(palavras_por_mensagem, 2))  
  imprimir('Average Words per Message : ', w_p_m)
  ### conists de mídia de mensagens de mídia
  media = sum(req_df["Media_Count"])
  imprimir('Total Media Message Sent : ', meios de comunicação)
  ### links consistem em links totais
  links = soma(req_df["Url_Count"])   
  imprimir('Total Links Sent : ', links)   
  imprimir()
  imprimir('----------------------------------------------------------n')
868324-2659596

Vamos criar uma nuvem de palavras com as palavras mais usadas no chat:

### Nuvem de palavras da palavra mais usada em nosso grupo
text = " ".Junte(revisão para revisão em df.Message)
wordcloud = WordCloud(stopwords = STOPWORDS, background_color ="Branco").gerar(texto)
  ### Exibir a imagem gerada:
plt.figure( figsize =(10,5))
plt.imshow(palavra nuvem, interpolação='bilinear')
plt.axis("desligado")
plt.show()
30385download-7294185

Vamos imprimir o nº total.. de mensagens enviadas por cada usuário:

### Cria uma lista de autores únicos
l = df.Author.unique()
para eu no alcance(len(eu)):
  ### Filtrando mensagens de um usuário específico
  req_df = df[df["Autor"] == l[eu]]
  ### req_df conterá mensagens de apenas um usuário específico
  imprimir(eu[eu],'  ->  ',req_df.shape[0])

Imprimimos o total de mensagens enviadas em cada dia da semana:

l = df.Day.unique()
para eu no alcance(len(eu)):
  ### Filtrando mensagens de um usuário específico
  req_df = df[df["Dia"] == l[eu]]
  ### req_df conterá mensagens de apenas um usuário específico
  imprimir(eu[eu],'  ->  ',req_df.shape[0])
820455-4298474

Finalmente, extraímos informações de texto suficientes do arquivo de bate-papo, Agora vamos começar a parte de visualização de dados que nos ajudará para uma melhor análise e compreensão de todas as análises que fizemos em nosso arquivo de chat exportado. No lugar dos números de contato, Eu usei alfabetos por razões de segurança, sinto muito.

Vamos ver quem é o autor mais ativo do grupo:

### Autor mais ativo no grupo
plt.figure(figsize =(9,6))
principalmente_ativo = df['Author'].valor_contas()
### Principal 10 povos que são principalmente ativos em nosso grupo é : 
m_a = principalmente_ativo.head(10)
barras = ['A','B','C','D','E','F','G','H','I','J']
x_pos = np.arange(len(barras))
m_a.plot.bar()
plt.xlabel('Authors',fontdict ={'fontsize': 14,'fontweight': 10})
plt.ylabel('No. of messages',fontdict ={'fontsize': 14,'fontweight': 10})
plt.title('Mostly active member of Group',fontdict ={'fontsize': 20,'fontweight': 8})
plt.xticks(x_pos, barras)
plt.show()
670076-3037211

Vejamos o dia mais ativo em uma semana:

### Dia mais ativo no grupo
plt.figure(figsize =(8,5))
active_day = df['Day'].valor_contas()
### Principal 10 povos que são principalmente ativos em nosso grupo é : 
a_d = active_day.head(10)
a_d.plot.bar()
plt.xlabel('Day',fontdict ={'fontsize': 12,'fontweight': 10})
plt.ylabel('No. of messages',fontdict ={'fontsize': 12,'fontweight': 10})
plt.title('Mostly active day of Week in the Group',fontdict ={'fontsize': 18,'fontweight': 8})
plt.show()
961227-7889100

Vejamos o contribuidor de mídia Top-10 no grupo:

### Os 10 principais colaboradores de mídia do grupo
mm = df[df['Message'] == '<Mídia omitida>']
mm1 = mm['Author'].valor_contas()
barras = ['A','B','C','D','E','F','G','H','I','J']
x_pos = np.arange(len(barras))
top10 = mm1.head(10)
top10.plot.bar()
plt.xlabel('Author's',fontdict ={'fontsize': 12,'fontweight': 10})
plt.ylabel('No. of media',fontdict ={'fontsize': 12,'fontweight': 10})
plt.title('Top-10 media contributor of Group',fontdict ={'fontsize': 18,'fontweight': 8})
plt.xticks(x_pos, barras)
plt.show()
535338-2868307

As palavras são, claro, a arma mais poderosa do mundo, então vamos ver quem tem essa arma poderosa no grupo😅:

max_words = df[['Author','Word's']].groupby('Author').soma()
m_w = max_words.sort_values('Word's',ascendente = falso).cabeça(10)
barras = ['A','B','C','D','E','F','G','H','I','J']
x_pos = np.arange(len(barras))
m_w.plot.bar(podridão = 90)
plt.xlabel('Author')
plt.ylabel('No. of words')
plt.title('Analysis of members who has used max. não. of words in his/her messages')
plt.xticks(x_pos, barras)
plt.show()
623779-8463128

Vejamos o autor Top-10 que compartilhou o número máximo. de links no grupo:

### Membro que compartilhou o número máximo de links no grupo 
max_words = df[['Author','Url_Count']].groupby('Author').soma()
m_w = max_words.sort_values('Url_Count',ascendente = falso).cabeça(10)
barras = ['A','B','C','D','E','F','G','H','I','J']
x_pos = np.arange(len(barras))
m_w.plot.bar(podridão = 90)
plt.xlabel('Author')
plt.ylabel('No. of link's')
plt.title('Analysis of member's who has shared max no. of link's in Group')
plt.xticks(x_pos, barras)
plt.show()
7203110-3933500

Vamos ver quando cada vez que o grupo estava muito ativo:

### Tempo sempre que nosso grupo é altamente ativo
plt.figure(figsize =(8,5))
t = df['Tempo'].valor_contas().cabeça(20)
tx = t.plot.bar()
tx.yaxis.set_major_locator(MaxNLocator(inteiro=True))  #Converting y axis data to integer
plt.xlabel('Tempo',fontdict ={'fontsize': 12,'fontweight': 10})
plt.ylabel('No. of messages',fontdict ={'fontsize': 12,'fontweight': 10})
plt.title('Analysis of time when Group was highly active.',fontdict ={'fontsize': 18,'fontweight': 8})
plt.show()
7035911-3436594

La conversión de formato de 12 horas para 24 horas nos ayudará a realizar un mejor análisis:

Lst = []
para i no DF['Tempo'] :
out_time = datetime.strftime(datatime.strptime(eu,"%eu:%M %p"),"%H:%M")
Lst.append(out_time)
df['24H_Time'] = lst
df['Hours'] = df['24H_Time'].Aplique(lambda x : x.split(':')[0])

Revismos la hora más adecuada del día cuando haya haya más poibilidades de obtener una respuesta de los miembros del grupo:

### Hora mais adequada do dia, sempre que haverá mais chances de obter resposta dos membros do grupo.
plt.figure(figsize =(8,5))
std_time = df['Hours'].valor_contas().cabeça(15)
s_T = std_time.plot.bar()
s_T.yaxis.set_major_locator(MaxNLocator(inteiro=True))  #Converting y axis data to integer
plt.xlabel('Hours (24-Hora)',fontdict ={'fontsize': 12,'fontweight': 10})
plt.ylabel('No. of messages',fontdict ={'fontsize': 12,'fontweight': 10})
plt.title('Most suitable hour of day.',fontdict ={'fontsize': 18,'fontweight': 8})
plt.show()
2433312-7850260

Creemos una nube de palabras de los 10 miembros más activos:

active_m = [lista de membros top-10 altamente ativos]
para eu no alcance(len(active_m)) :
    # Filtering out messages of particular user
    m_chat = df[df["Autor"] == active_m[eu]]
    imprimir(f'--- Autor :  {active_m[eu]} --- ')
    # Word Cloud of mostly used word in our Group
    msg = ' '.join(x para x em m_chat. Mensagem)
    wordcloud = WordCloud(stopwords = STOPWORDS, background_color ="Branco").gerar(msg)
    plt.figure(figsize =(10,5))
    plt.imshow(palavra nuvem, interpolação='bilinear')
    plt.axis("desligado")
    plt.show()
    imprimir('____________________________________________________________________________________n')

Veamos la fecha en la que nuestro grupo estuvo muy activo:

### Data em que nosso Grupo era altamente ativo.
plt.figure(figsize =(8,5))
df['Date'].valor_contas().cabeça(15).plot.bar()
plt.xlabel('Date',fontdict ={'fontsize': 14,'fontweight': 10})
plt.ylabel('No. of messages',fontdict ={'fontsize': 14,'fontweight': 10})
plt.title('Analysis of Date on which Group was highly active',fontdict ={'fontsize': 18,'fontweight': 8})
plt.show()
4887613-6449672

Creemos una gráfica de série de tiempo wrt no. de mensajes:

z = df['Date'].valor_contas() 
z1 = z.to_dict() #converts to dictionary
df['Msg_count'] = df['Date'].mapa(z1)
### Enredo de Timeseries 
fig = px.line(x=df['Date'],y=df['Msg_count'])
fig.update_layout(título ="Análise do número de mensagens"s using TimeSeries plot.',
                  xaxis_title ="Mês",
                  yaxis_title ="Não. de Mensagens")
fig.update_xaxes(nticks=20)
fig.show()
8987214-7023657

Creemos una columna separado para Mes y Año para un mejor análisis:

df['Year'] = df['Date'].dt.year
df['Mon'] = df['Date'].dt.month
months = {
     1 : 'Jan',
     2 : 'Feb',
     3 : 'Mar',
     4 : 'Apr',
     5 : 'May',
     6 : 'Jun',
     7 : 'Jul',
     8 : 'Aug',
     9 : 'Sep',
    10 : 'Oct',
    11 : 'Nov',
    12 : 'Dec'
}
df['Mês'] = df['Mon'].mapa(meses)
df.drop('Mon',eixo = 1, local = Verdadeiro)

Veamos el mes mayormente activo:

### Mês ativo 
plt.figure(figsize =(12,6))
active_month = df['Month_Year'].valor_contas()
a_m = active_month
a_m.plot.bar()
plt.xlabel('Mês',fontdict ={'fontsize': 14,'fontweight': 10})
plt.ylabel('No. of messages',fontdict ={'fontsize': 14,'fontweight': 10})
plt.title('Analysis of mostly active month.',fontdict ={'fontsize': 20,
        'fontweight': 8})
plt.show()
1687615-5864106

Analicemos el mes más activo usando un diagrama de líneas:

z = df['Month_Year'].valor_contas() 
z1 = z.to_dict() #converts to dictionary
df['Msg_count_monthly'] = df['Month_Year'].mapa(z1)
plt.figure(figsize =(18,9))
sns.set_style("darkgrid")
sns.lineplot(data = df,x='Month_Year',y='Msg_count_monthly',marcadores=True,marcador ="o")
plt.xlabel('Mês',fontdict ={'fontsize': 14,'fontweight': 10})
plt.ylabel('No. of messages',fontdict ={'fontsize': 14,'fontweight': 10})
plt.title('Analysis of mostly active month using line plot.',fontdict ={'fontsize': 20,'fontweight': 8})
plt.show()
1823516-7890099

Vamos revisar o total de mensagens por ano:

### Total de mensagens por ano
### Ao analisarmos que o grupo foi criado em meados 2019, é por isso que o número de mensagens em 2019 é menos.
plt.figure(figsize =(12,6))
active_month = df['Year'].valor_contas()
a_m = active_month
a_m.plot.bar()
plt.xlabel('Year',fontdict ={'fontsize': 14,'fontweight': 10})
plt.ylabel('No. of messages',fontdict ={'fontsize': 14,'fontweight': 10})
plt.title('Analysis of mostly active year.',fontdict ={'fontsize': 20,'fontweight': 8})
plt.show()
8230117-3501940

Usemos un mapa de calor y analicemos la hora del día con gran actividad:

df2 = df.groupby(['Hours', 'Day'], as_index = False)["Mensagem"].contar()
df2 = df2.dropna()
df2.reset_index(drop = True,inplace = True)
### Analisar em qual grupo de tempo está mais ativo com base nas horas e no dia.
analysis_2_df = df.groupby(['Hours', 'Day'], as_index = False)["Mensagem"].contar()
### Eliminando valores nulos
analysis_2_df.dropna(inplace = True)
analysis_2_df.sort_values(por =['Message'],ascendente = falso)
day_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thrusday', 'Friday', 'Saturday', 'Sunday']
plt.figure(figsize =(15,8))
mapa de calor(
    x = analysis_2_df['Hours'],
    y = analysis_2_df['Day'],
    size_scale = 500,
    size = analysis_2_df['Message'], 
    y_order = day_of_week[::-1],
    color = analysis_2_df['Message'], 
    palette = sns.cubehelix_palette(128)
)
plt.show()
6516518-9990731

Do mapa de calor acima, nós analisamos que o “Segunda-feira” entre as 10:00 e as 10:59, nosso grupo era
muito ativo, similarmente o “quarta-feira” entre as 10:00 e as 10:59, nosso grupo era
Altamente ativo. Entre as 00:00 e as 08:00 o grupo era menos ativo.

Nota final:

Espero que este artigo realmente ajude você a criar seu próprio analisador de bate-papo do WhatsApp e a analisar o padrão no grupo.

Espero que tenha gostado deste artigo. Qualquer pergunta? Eu perdi algo? Entre em contato comigo no meu LinkedIn. E finalmente, … Não precisa dizer,

Obrigado pela leitura!

Saúde!!!

Ronil

A mídia mostrada neste artigo não é propriedade da DataPeaker e é usada a critério do autor.

Assine a nossa newsletter

Nós não enviaremos SPAM para você. Nós odiamos isso tanto quanto você.

Datapeaker