Initial commit
This commit is contained in:
commit
f6ba06ce8d
1 changed files with 280 additions and 0 deletions
280
Lecteur_messenger.py
Normal file
280
Lecteur_messenger.py
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Created on Tue Apr 28 10:46:49 2020
|
||||||
|
|
||||||
|
@author: Leopold
|
||||||
|
@version = 2.0
|
||||||
|
|
||||||
|
module permetant une annalyse des conversations Mesenger
|
||||||
|
"""
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class Conv():
|
||||||
|
"""
|
||||||
|
Representation en machine d'une conversation.
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
Utiliser `Conv.from_list` de preference.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, cible):
|
||||||
|
"""
|
||||||
|
## Initialisation
|
||||||
|
cible : str
|
||||||
|
Emplacement du fichier `.json` de la conversation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
file = open(cible)
|
||||||
|
datas = json.load(file)
|
||||||
|
file.close()
|
||||||
|
try:
|
||||||
|
self.nom = datas["title"].encode('cp1252').decode('utf8')
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
self.nom = datas["title"]
|
||||||
|
self.membres = {}
|
||||||
|
"""Liste des utilisaeur dans la conversation."""
|
||||||
|
self.messages = []
|
||||||
|
"""Liste des messages de la conversation."""
|
||||||
|
for elem in datas['participants']:
|
||||||
|
self.membres[elem['name']] = User(elem['name'], self)
|
||||||
|
self._ajout_list_msg(datas['messages'])
|
||||||
|
|
||||||
|
def _ajout_list_msg(self, list_msg):
|
||||||
|
for msg in list_msg:
|
||||||
|
try:
|
||||||
|
user = self.membres[msg['sender_name']]
|
||||||
|
self.messages.append(Messages.bon_type(
|
||||||
|
msg,
|
||||||
|
user,
|
||||||
|
self,
|
||||||
|
msg['timestamp_ms']))
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "{}:\n{}\n-{} messages".format(self.nom, self.membres, len(self.messages))
|
||||||
|
|
||||||
|
def classement(self):
|
||||||
|
"""
|
||||||
|
Crée un classment des membres de la conversation en fonction de
|
||||||
|
leur nombre de participation.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
chaine : str
|
||||||
|
Ladite chaine de la forme `numero : nom, n message`.
|
||||||
|
"""
|
||||||
|
users = [self.membres[elem] for elem in self.membres]
|
||||||
|
users.sort(key=User.n_msg, reverse=True)
|
||||||
|
chaine = ""
|
||||||
|
for n, usr in enumerate(users):
|
||||||
|
chaine += "{} : {} - {} messages\n".format(n+1, usr.nom, usr.n_msg())
|
||||||
|
return chaine
|
||||||
|
|
||||||
|
def add_fichier(self, cible):
|
||||||
|
"""
|
||||||
|
Rajoute un fichier a l'objet `Conv`.
|
||||||
|
"""
|
||||||
|
file = open(cible)
|
||||||
|
datas = json.load(file)
|
||||||
|
file.close()
|
||||||
|
self._ajout_list_msg(datas['messages'])
|
||||||
|
|
||||||
|
def pie_participation(self):
|
||||||
|
"""
|
||||||
|
Camembert du nombre de participation des participants de la conv.
|
||||||
|
"""
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
plt.xkcd()
|
||||||
|
fig = plt.figure()
|
||||||
|
fig.title = self.nom
|
||||||
|
ax = fig.add_axes([0, 0, 1, 1])
|
||||||
|
ax.axis('equal')
|
||||||
|
users = [self.membres[elem] for elem in self.membres]
|
||||||
|
users.sort(key=User.n_msg)
|
||||||
|
noms = [usr.nom for usr in users]
|
||||||
|
participations = [usr.n_msg() for usr in users]
|
||||||
|
ax.pie(participations, labels=noms, autopct='%1.2f%%')
|
||||||
|
plt.title("Participation des membres de la conv {}".format(self.nom))
|
||||||
|
return fig
|
||||||
|
|
||||||
|
def hist_heure(self):
|
||||||
|
"""
|
||||||
|
histogramme de l'utilisation de la `Conv` en fonction de l'heure.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
list_des_minutes = []
|
||||||
|
|
||||||
|
def convertisseur_timestamps(datetime_object: datetime.datetime) -> float:
|
||||||
|
time = datetime_object.time()
|
||||||
|
minutes = 0
|
||||||
|
minutes += 60 * time.hour
|
||||||
|
minutes += time.minute
|
||||||
|
minutes += 1/60 * time.second
|
||||||
|
return minutes
|
||||||
|
|
||||||
|
for message in self.messages:
|
||||||
|
list_des_minutes.append(convertisseur_timestamps(message.datetime))
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
plt.xkcd()
|
||||||
|
plt.hist(list_des_minutes, density=True, bins=4*24, range=(0, 24*60))
|
||||||
|
plt.xticks(
|
||||||
|
[i*60*2 for i in range(0, 13)],
|
||||||
|
["{}h00".format(i*2) for i in range(0, 13)],
|
||||||
|
rotation=45)
|
||||||
|
plt.xlim(0, 24*60)
|
||||||
|
plt.title("""activité de la conv "{}" en fonction de l'heure""".format(self.nom))
|
||||||
|
return plt
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.messages)
|
||||||
|
|
||||||
|
def bar_nom_ocurence_mot(self, chaine_cible: str):
|
||||||
|
"""
|
||||||
|
BarGraph du nombre d'utilisation de la chaine `chaine_cible`.
|
||||||
|
Insensible à la case.
|
||||||
|
"""
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
plt.xkcd()
|
||||||
|
chaine_cible = chaine_cible.lower()
|
||||||
|
liste_user = []
|
||||||
|
liste_occurence = []
|
||||||
|
for msg in self.messages:
|
||||||
|
if isinstance(msg, MsgTexte):
|
||||||
|
if chaine_cible in msg.content.lower():
|
||||||
|
if msg.user in liste_user:
|
||||||
|
for n, user in enumerate(liste_user):
|
||||||
|
if msg.user == user:
|
||||||
|
liste_occurence[n] += 1
|
||||||
|
else:
|
||||||
|
liste_user.append(msg.user)
|
||||||
|
liste_occurence.append(1)
|
||||||
|
plt.bar([str(user) for user in liste_user], liste_occurence)
|
||||||
|
plt.xticks(rotation=25)
|
||||||
|
plt.title("""Utilisation du terme "{}" """.format(chaine_cible))
|
||||||
|
return plt
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_list(cls, liste_adresse):
|
||||||
|
"""Permet d'initialiser une conversation à partir d'une liste de fichier"""
|
||||||
|
if not liste_adresse:
|
||||||
|
raise ValueError
|
||||||
|
conv = cls(liste_adresse[0])
|
||||||
|
for elem in liste_adresse[1:]:
|
||||||
|
conv.add_fichier(elem)
|
||||||
|
return conv
|
||||||
|
|
||||||
|
|
||||||
|
class User():
|
||||||
|
"""
|
||||||
|
Objet representant un utiliateur dans une `Conv`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, nom, conv=None):
|
||||||
|
"""
|
||||||
|
## Initialisation
|
||||||
|
|
||||||
|
nom : str
|
||||||
|
Nom de l'utilisateur.
|
||||||
|
|
||||||
|
conv : `Conv
|
||||||
|
Conversation associé, optionel.
|
||||||
|
"""
|
||||||
|
self.nom = None
|
||||||
|
"""Nom de l'utilisateur."""
|
||||||
|
try:
|
||||||
|
self.nom = nom.encode('cp1252').decode('utf8')
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
self.nom = nom
|
||||||
|
self.conv = conv
|
||||||
|
"""`Conv` où se trouve l'utilisateur."""
|
||||||
|
self.messages = []
|
||||||
|
"""Liste des messages de l'utilisateur."""
|
||||||
|
|
||||||
|
def add_msg(self, msg):
|
||||||
|
self.messages.append(msg)
|
||||||
|
|
||||||
|
def n_msg(self):
|
||||||
|
return len(self.messages)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "{} - {} messages".format(self.nom, self.n_msg())
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.nom
|
||||||
|
|
||||||
|
|
||||||
|
class Messages():
|
||||||
|
"""
|
||||||
|
Class representant les messages d'une conversation.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, msg_data, user: User, conv: Conv, timestamp):
|
||||||
|
self.datetime = datetime.datetime.fromtimestamp(timestamp/1000)
|
||||||
|
"""Temps POSIX de parution du message."""
|
||||||
|
self.user = user
|
||||||
|
"""`User` ayant poster le message."""
|
||||||
|
self.reactionaire = []
|
||||||
|
"""Liste des personnes ayant reagit au message."""
|
||||||
|
try:
|
||||||
|
for elem in msg_data["reactions"]:
|
||||||
|
self.reactionaire.append(conv.membres[elem["actor"]])
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
user.add_msg(self)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def bon_type(cls, msg_data, user: User, conv: Conv, timestamp):
|
||||||
|
"""
|
||||||
|
Permet de creer un message avec la bonne sous-class en fonction de son contenu.
|
||||||
|
|
||||||
|
Soit `MsgTexe`, `MsgPhoto`.
|
||||||
|
Si le message n'a pas de class particulière `Messages`.
|
||||||
|
"""
|
||||||
|
if 'content' in msg_data:
|
||||||
|
msg = MsgTexte(msg_data, user, conv, timestamp)
|
||||||
|
elif 'photos' in msg_data:
|
||||||
|
msg = MsgPhoto(msg_data, user, conv, timestamp)
|
||||||
|
else:
|
||||||
|
msg = Messages(msg_data, user, conv, timestamp)
|
||||||
|
return msg
|
||||||
|
|
||||||
|
@property
|
||||||
|
def nombre_react(self):
|
||||||
|
"""
|
||||||
|
Nombre de personne ayant reagit à ce message.
|
||||||
|
"""
|
||||||
|
return len(self.reactionaire)
|
||||||
|
|
||||||
|
|
||||||
|
class MsgTexte(Messages):
|
||||||
|
"""
|
||||||
|
Message comportant du texte.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, msg_data, user: User, conv: Conv, timestamp):
|
||||||
|
Messages.__init__(self, msg_data, user, conv, timestamp)
|
||||||
|
contenu = msg_data['content']
|
||||||
|
self.content = None
|
||||||
|
"""Texte du message."""
|
||||||
|
try:
|
||||||
|
self.content = contenu.encode('cp1252').decode('utf8')
|
||||||
|
except UnicodeEncodeError:
|
||||||
|
self.content = contenu
|
||||||
|
|
||||||
|
|
||||||
|
class MsgPhoto(Messages):
|
||||||
|
"""
|
||||||
|
Message comportant une image.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, msg_data, user: User, conv: Conv, timestamp):
|
||||||
|
Messages.__init__(self, msg_data, user, conv, timestamp)
|
||||||
|
self.contenu = [elem["uri"] for elem in msg_data['photos']]
|
||||||
|
"""Emplacement de l'image dans l'archive des données FaceBook."""
|
||||||
|
|
||||||
|
|
||||||
|
EEA = Conv.from_list(["msg/EEA/message_{}.json".format(n+1) for n in range(2)])
|
Loading…
Reference in a new issue