Améliorations au moteur de recherche
This commit is contained in:
parent
15eb318212
commit
fc6bd9f255
21 changed files with 509 additions and 223 deletions
|
@ -1,11 +1,11 @@
|
||||||
import os
|
import os
|
||||||
import utils.reseau_social_data as rs_data
|
import utils.reseau_social_data as rs_data
|
||||||
|
|
||||||
# %% Créer le répertoire data s'il n'existe pas
|
## %% Créer le répertoire data s'il n'existe pas
|
||||||
if not os.path.exists('data'):
|
if not os.path.exists('data'):
|
||||||
os.makedirs('data')
|
os.makedirs('data')
|
||||||
|
|
||||||
# %% Créer les répertoires pour chaque réseau sociaux
|
## %% Créer les répertoires pour chaque réseau sociaux
|
||||||
for reseau_social in rs_data.reseau_social_data:
|
for reseau_social in rs_data.reseau_social_data:
|
||||||
if not os.path.exists(f'data/{reseau_social["nom"]}/'):
|
if not os.path.exists(f'data/{reseau_social["nom"]}/'):
|
||||||
os.makedirs(f'data/{reseau_social["nom"]}/')
|
os.makedirs(f'data/{reseau_social["nom"]}/')
|
||||||
|
|
|
@ -2,7 +2,7 @@ from typesense.exceptions import TypesenseClientError, ObjectAlreadyExists
|
||||||
|
|
||||||
from utils.typesense_client import client
|
from utils.typesense_client import client
|
||||||
|
|
||||||
# Create a collection
|
## %% Create a collection
|
||||||
try:
|
try:
|
||||||
client.collections.create({
|
client.collections.create({
|
||||||
'name': 'social_media_posts',
|
'name': 'social_media_posts',
|
||||||
|
@ -13,10 +13,13 @@ try:
|
||||||
{'name': 'index', 'type': 'string', 'facet': True},
|
{'name': 'index', 'type': 'string', 'facet': True},
|
||||||
{'name': 'chemin', 'type': 'string'},
|
{'name': 'chemin', 'type': 'string'},
|
||||||
{'name': 'texte', 'type': 'string'},
|
{'name': 'texte', 'type': 'string'},
|
||||||
|
{'name': 'langue', 'type': 'string', 'facet': True},
|
||||||
|
{'name': 'texte_urls', 'type': 'string[]'},
|
||||||
|
{'name': 'nombre_de_mots', 'type': 'int64'},
|
||||||
{'name': 'creation_timestamp', 'type': 'int64'},
|
{'name': 'creation_timestamp', 'type': 'int64'},
|
||||||
{
|
{
|
||||||
"name" : "embedding",
|
"name": "embedding",
|
||||||
"type" : "float[]",
|
"type": "float[]",
|
||||||
"embed": {
|
"embed": {
|
||||||
"from": [
|
"from": [
|
||||||
"texte"
|
"texte"
|
||||||
|
@ -31,10 +34,8 @@ try:
|
||||||
})
|
})
|
||||||
print("Collection 'social_media_posts' created successfully.")
|
print("Collection 'social_media_posts' created successfully.")
|
||||||
except TypesenseClientError as e:
|
except TypesenseClientError as e:
|
||||||
if e==ObjectAlreadyExists:
|
if e == ObjectAlreadyExists:
|
||||||
print("Collection 'social_media_posts' already exists. Skipping creation.")
|
print("Collection 'social_media_posts' already exists. Skipping creation.")
|
||||||
else:
|
else:
|
||||||
print(f"Error creating collection: {str(e)}")
|
print(f"Error creating collection: {str(e)}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
# Utiliser au besoin seulement pour supprimer la collection 'social_media_posts' dans Typesense
|
## %% Utiliser au besoin seulement pour supprimer la collection 'social_media_posts' dans Typesense
|
||||||
from utils.typesense_client import client
|
from utils.typesense_client import client
|
||||||
|
## %%
|
||||||
client.collections['social_media_posts'].delete()
|
client.collections['social_media_posts'].delete()
|
|
@ -6,21 +6,18 @@ from pathlib import Path
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
from utils.convert_encoding_meta import convert_encoding_meta
|
from utils.convert_encoding_meta import convert_encoding_meta
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Déterminer le chemin du répertoire du script
|
||||||
|
|
||||||
#%% In[ ]:
|
|
||||||
|
|
||||||
# Get the current file's directory
|
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
fb_data_path = [os.path.join(project_root, 'import_data', 'data', 'FacebookBusiness', 'posts', 'profile_posts_1.json')]
|
fb_data_path = [os.path.join(project_root, 'import_data', 'data', 'FacebookBusiness', 'posts', 'profile_posts_1.json')]
|
||||||
|
|
||||||
|
## %% Lire et parser le fichier JSON des posts Facebook
|
||||||
try:
|
try:
|
||||||
with open(fb_data_path[0], "r", encoding="raw-unicode-escape") as posts:
|
with open(fb_data_path[0], "r", encoding="raw-unicode-escape") as posts:
|
||||||
posts_json = json.loads(convert_encoding_meta(posts.read()))
|
posts_json = json.loads(convert_encoding_meta(posts.read()))
|
||||||
|
@ -28,17 +25,18 @@ except Exception as e:
|
||||||
print(f"Error reading JSON file: {e}")
|
print(f"Error reading JSON file: {e}")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Extraire les données pertinentes de chaque post
|
||||||
posts_medias = []
|
posts_medias = []
|
||||||
for post in posts_json:
|
for post in posts_json:
|
||||||
# data
|
# Extraire le texte du post
|
||||||
data_post_items = post['data']
|
data_post_items = post['data']
|
||||||
texte_post_list = []
|
texte_post_list = []
|
||||||
for item in data_post_items:
|
for item in data_post_items:
|
||||||
if item.get('post'):
|
if item.get('post'):
|
||||||
texte_post_list.append(item['post'])
|
texte_post_list.append(item['post'])
|
||||||
texte = "\n".join(texte_post_list)
|
texte = "\n".join(texte_post_list)
|
||||||
# attachments
|
|
||||||
|
# Traiter les pièces jointes du post
|
||||||
for attachment in post['attachments']:
|
for attachment in post['attachments']:
|
||||||
if attachment.get('data'):
|
if attachment.get('data'):
|
||||||
for data_item in attachment['data']:
|
for data_item in attachment['data']:
|
||||||
|
@ -52,14 +50,14 @@ for post in posts_json:
|
||||||
"texte": texte,
|
"texte": texte,
|
||||||
"creation_timestamp": media["creation_timestamp"]})
|
"creation_timestamp": media["creation_timestamp"]})
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des données extraites
|
||||||
posts_medias_df = pd.DataFrame(posts_medias)
|
posts_medias_df = pd.DataFrame(posts_medias)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
posts_medias_df.fillna(value="", inplace=True)
|
posts_medias_df.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les doublons basés sur le texte et le timestamp de création
|
||||||
posts_medias_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
posts_medias_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(posts_medias_df)
|
documents_to_database(posts_medias_df)
|
|
@ -6,23 +6,23 @@ from pathlib import Path
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
from utils.convert_encoding_meta import convert_encoding_meta
|
from utils.convert_encoding_meta import convert_encoding_meta
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
|
# Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
fb_data_path = [os.path.join(project_root, 'import_data', 'data', 'Facebook', 'comments_and_reactions', 'comments.json')]
|
fb_data_path = [os.path.join(project_root, 'import_data', 'data', 'Facebook', 'comments_and_reactions', 'comments.json')]
|
||||||
|
|
||||||
|
## %% Lire et parser le fichier JSON des commentaires Facebook
|
||||||
with open(fb_data_path[0], "r", encoding="raw-unicode-escape") as posts:
|
with open(fb_data_path[0], "r", encoding="raw-unicode-escape") as posts:
|
||||||
comments_json = json.loads(convert_encoding_meta(posts.read()))
|
comments_json = json.loads(convert_encoding_meta(posts.read()))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Extraire les données pertinentes de chaque commentaire
|
||||||
facebook_comments = []
|
facebook_comments = []
|
||||||
for comment in comments_json['comments_v2']:
|
for comment in comments_json['comments_v2']:
|
||||||
if comment.get('data'):
|
if comment.get('data'):
|
||||||
|
@ -36,8 +36,8 @@ for comment in comments_json['comments_v2']:
|
||||||
"texte": comment["comment"],
|
"texte": comment["comment"],
|
||||||
"creation_timestamp": comment["timestamp"]})
|
"creation_timestamp": comment["timestamp"]})
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des données extraites
|
||||||
facebook_comments_df = pd.DataFrame(facebook_comments)
|
facebook_comments_df = pd.DataFrame(facebook_comments)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(facebook_comments_df)
|
documents_to_database(facebook_comments_df)
|
|
@ -6,46 +6,45 @@ from pathlib import Path
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
from utils.convert_encoding_meta import convert_encoding_meta
|
from utils.convert_encoding_meta import convert_encoding_meta
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
|
# Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
fb_data_path = os.path.join(project_root, 'import_data', 'data', 'Facebook', 'posts', 'your_uncategorized_photos.json')
|
fb_data_path = os.path.join(project_root, 'import_data', 'data', 'Facebook', 'posts', 'your_uncategorized_photos.json')
|
||||||
|
|
||||||
|
## %% Lire et parser le fichier JSON des photos Facebook non catégorisées
|
||||||
with open(fb_data_path, "r", encoding="raw-unicode-escape") as posts:
|
with open(fb_data_path, "r", encoding="raw-unicode-escape") as posts:
|
||||||
photos_json = json.loads(convert_encoding_meta(posts.read()))
|
photos_json = json.loads(convert_encoding_meta(posts.read()))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Extraire les photos non catégorisées du JSON
|
||||||
facebook_photos = photos_json['other_photos_v2']
|
facebook_photos = photos_json['other_photos_v2']
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des photos extraites
|
||||||
facebook_photos_df = pd.DataFrame(facebook_photos)
|
facebook_photos_df = pd.DataFrame(facebook_photos)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les publications sans description
|
||||||
# Filter out posts without a description
|
|
||||||
facebook_photos_df = facebook_photos_df[~facebook_photos_df['description'].isnull()]
|
facebook_photos_df = facebook_photos_df[~facebook_photos_df['description'].isnull()]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Ajouter des métadonnées au DataFrame
|
||||||
facebook_photos_df['index'] = "rs_facebook_posts"
|
facebook_photos_df['index'] = "rs_facebook_posts"
|
||||||
facebook_photos_df['network'] = "Facebook"
|
facebook_photos_df['network'] = "Facebook"
|
||||||
facebook_photos_df['type'] = "posts"
|
facebook_photos_df['type'] = "posts"
|
||||||
facebook_photos_df['chemin'] = fb_data_path
|
facebook_photos_df['chemin'] = fb_data_path
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Renommer la colonne 'description' en 'texte'
|
||||||
facebook_photos_df.rename(columns={"description": "texte"}, inplace=True)
|
facebook_photos_df.rename(columns={"description": "texte"}, inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer la colonne 'media_metadata'
|
||||||
del facebook_photos_df['media_metadata']
|
del facebook_photos_df['media_metadata']
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
facebook_photos_df.fillna(value="", inplace=True)
|
facebook_photos_df.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(facebook_photos_df)
|
documents_to_database(facebook_photos_df)
|
|
@ -6,23 +6,23 @@ from pathlib import Path
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
from utils.convert_encoding_meta import convert_encoding_meta
|
from utils.convert_encoding_meta import convert_encoding_meta
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'content', 'posts_1.json')
|
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'content', 'posts_1.json')
|
||||||
|
|
||||||
|
## %% Lire et parser le fichier JSON des publications Instagram
|
||||||
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
||||||
posts_json = json.loads(convert_encoding_meta(posts.read()))
|
posts_json = json.loads(convert_encoding_meta(posts.read()))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Extraire et structurer les données des publications Instagram
|
||||||
posts_medias = []
|
posts_medias = []
|
||||||
for post in posts_json:
|
for post in posts_json:
|
||||||
medias = post['media']
|
medias = post['media']
|
||||||
|
@ -56,18 +56,17 @@ for post in posts_json:
|
||||||
"texte": title,
|
"texte": title,
|
||||||
"creation_timestamp": creation_timestamp})
|
"creation_timestamp": creation_timestamp})
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des données extraites
|
||||||
posts_medias_df = pd.DataFrame(posts_medias)
|
posts_medias_df = pd.DataFrame(posts_medias)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
posts_medias_df.fillna(value="", inplace=True)
|
posts_medias_df.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les doublons basés sur le texte et la date de création
|
||||||
posts_medias_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
posts_medias_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les publications avec un texte vide
|
||||||
# Filter empty texte
|
|
||||||
posts_medias_df = posts_medias_df[~posts_medias_df['texte'].str.strip().eq('')]
|
posts_medias_df = posts_medias_df[~posts_medias_df['texte'].str.strip().eq('')]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(posts_medias_df)
|
documents_to_database(posts_medias_df)
|
|
@ -6,50 +6,50 @@ from pathlib import Path
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
from utils.convert_encoding_meta import convert_encoding_meta
|
from utils.convert_encoding_meta import convert_encoding_meta
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'content', 'reels.json')
|
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'content', 'reels.json')
|
||||||
|
|
||||||
|
## %% Lire et parser le fichier JSON des reels Instagram
|
||||||
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
||||||
reels_json = json.loads(convert_encoding_meta(posts.read()))
|
reels_json = json.loads(convert_encoding_meta(posts.read()))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Extraire les données média des reels
|
||||||
ig_reels_media = [x['media'][0] for x in reels_json['ig_reels_media']]
|
ig_reels_media = [x['media'][0] for x in reels_json['ig_reels_media']]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des données extraites
|
||||||
ig_reels_df = pd.DataFrame(ig_reels_media)
|
ig_reels_df = pd.DataFrame(ig_reels_media)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Ajouter des colonnes supplémentaires au DataFrame
|
||||||
ig_reels_df['index'] = "rs_instagram_content"
|
ig_reels_df['index'] = "rs_instagram_content"
|
||||||
ig_reels_df['type'] = "reels"
|
ig_reels_df['type'] = "reels"
|
||||||
ig_reels_df['network'] = "Instagram"
|
ig_reels_df['network'] = "Instagram"
|
||||||
ig_reels_df['chemin'] = instagram_data_path
|
ig_reels_df['chemin'] = instagram_data_path
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Renommer la colonne 'title' en 'texte'
|
||||||
ig_reels_df.rename(columns={"title": "texte"}, inplace=True)
|
ig_reels_df.rename(columns={"title": "texte"}, inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les colonnes non nécessaires
|
||||||
del ig_reels_df['media_metadata']
|
del ig_reels_df['media_metadata']
|
||||||
del ig_reels_df['cross_post_source']
|
del ig_reels_df['cross_post_source']
|
||||||
del ig_reels_df['dubbing_info']
|
del ig_reels_df['dubbing_info']
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
ig_reels_df.fillna(value="", inplace=True)
|
ig_reels_df.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les doublons basés sur le texte et la date de création
|
||||||
ig_reels_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
ig_reels_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les reels avec un texte vide
|
||||||
# Filter empty texte
|
|
||||||
ig_reels_df = ig_reels_df[~ig_reels_df['texte'].str.strip().eq('')]
|
ig_reels_df = ig_reels_df[~ig_reels_df['texte'].str.strip().eq('')]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(ig_reels_df)
|
documents_to_database(ig_reels_df)
|
|
@ -6,47 +6,48 @@ from pathlib import Path
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
from utils.convert_encoding_meta import convert_encoding_meta
|
from utils.convert_encoding_meta import convert_encoding_meta
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'content', 'stories.json')
|
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'content', 'stories.json')
|
||||||
|
|
||||||
|
## %% Lire et parser le fichier JSON des stories Instagram
|
||||||
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
||||||
stories_json = json.loads(convert_encoding_meta(posts.read()))
|
stories_json = json.loads(convert_encoding_meta(posts.read()))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des données des stories
|
||||||
ig_stories_df = pd.DataFrame(stories_json['ig_stories'])
|
ig_stories_df = pd.DataFrame(stories_json['ig_stories'])
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Ajouter des colonnes supplémentaires au DataFrame
|
||||||
ig_stories_df['index'] = "rs_instagram_content"
|
ig_stories_df['index'] = "rs_instagram_content"
|
||||||
ig_stories_df['type'] = "stories"
|
ig_stories_df['type'] = "stories"
|
||||||
ig_stories_df['network'] = "Instagram"
|
ig_stories_df['network'] = "Instagram"
|
||||||
ig_stories_df['chemin'] = instagram_data_path
|
ig_stories_df['chemin'] = instagram_data_path
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Renommer la colonne 'title' en 'texte'
|
||||||
ig_stories_df.rename(columns={"title": "texte"}, inplace=True)
|
ig_stories_df.rename(columns={"title": "texte"}, inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les colonnes non nécessaires
|
||||||
del ig_stories_df['media_metadata']
|
del ig_stories_df['media_metadata']
|
||||||
del ig_stories_df['cross_post_source']
|
del ig_stories_df['cross_post_source']
|
||||||
del ig_stories_df['ai_stickers']
|
del ig_stories_df['ai_stickers']
|
||||||
del ig_stories_df['dubbing_info']
|
del ig_stories_df['dubbing_info']
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
ig_stories_df.fillna(value="", inplace=True)
|
ig_stories_df.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les doublons basés sur le texte et la date de création
|
||||||
ig_stories_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
ig_stories_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les stories avec un texte vide
|
||||||
# Filter empty texte
|
|
||||||
ig_stories_df = ig_stories_df[~ig_stories_df['texte'].str.strip('\n').str.strip().eq('')]
|
ig_stories_df = ig_stories_df[~ig_stories_df['texte'].str.strip('\n').str.strip().eq('')]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(ig_stories_df)
|
documents_to_database(ig_stories_df)
|
|
@ -6,22 +6,23 @@ from pathlib import Path
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
from utils.convert_encoding_meta import convert_encoding_meta
|
from utils.convert_encoding_meta import convert_encoding_meta
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'comments', 'post_comments_1.json')
|
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'comments', 'post_comments_1.json')
|
||||||
|
|
||||||
|
## %% Lire et parser le fichier JSON des commentaires Instagram
|
||||||
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
||||||
post_comments_1 = json.loads(convert_encoding_meta(posts.read()))
|
post_comments_1 = json.loads(convert_encoding_meta(posts.read()))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Extraire les données pertinentes de chaque commentaire
|
||||||
ig_comments = []
|
ig_comments = []
|
||||||
for comment in post_comments_1:
|
for comment in post_comments_1:
|
||||||
ig_comments.append({"texte": comment['string_map_data']['Comment']['value'],
|
ig_comments.append({"texte": comment['string_map_data']['Comment']['value'],
|
||||||
|
@ -31,18 +32,18 @@ for comment in post_comments_1:
|
||||||
"type": "comments",
|
"type": "comments",
|
||||||
"network": "Instagram"})
|
"network": "Instagram"})
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des données extraites
|
||||||
ig_comments_df = pd.DataFrame(ig_comments)
|
ig_comments_df = pd.DataFrame(ig_comments)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
ig_comments_df.fillna(value="", inplace=True)
|
ig_comments_df.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les doublons basés sur le texte et la date de création
|
||||||
ig_comments_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
ig_comments_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les commentaires avec un texte vide
|
||||||
# Filter empty texte
|
# Filtrer les textes vides
|
||||||
ig_comments_df = ig_comments_df[~ig_comments_df['texte'].str.strip('\n').str.strip().eq('')]
|
ig_comments_df = ig_comments_df[~ig_comments_df['texte'].str.strip('\n').str.strip().eq('')]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(ig_comments_df)
|
documents_to_database(ig_comments_df)
|
|
@ -6,22 +6,23 @@ from pathlib import Path
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
from utils.convert_encoding_meta import convert_encoding_meta
|
from utils.convert_encoding_meta import convert_encoding_meta
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'comments', 'reels_comments.json')
|
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'comments', 'reels_comments.json')
|
||||||
|
|
||||||
|
## %% Lire et parser le fichier JSON des commentaires Instagram Reels
|
||||||
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
with open(instagram_data_path, "r", encoding="raw-unicode-escape") as posts:
|
||||||
reels_comments = json.loads(convert_encoding_meta(posts.read()))
|
reels_comments = json.loads(convert_encoding_meta(posts.read()))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Extraire les données pertinentes de chaque commentaire Reels
|
||||||
ig_comments = []
|
ig_comments = []
|
||||||
for comment in reels_comments['comments_reels_comments']:
|
for comment in reels_comments['comments_reels_comments']:
|
||||||
ig_comments.append({"texte": comment['string_map_data']['Comment']['value'],
|
ig_comments.append({"texte": comment['string_map_data']['Comment']['value'],
|
||||||
|
@ -31,18 +32,18 @@ for comment in reels_comments['comments_reels_comments']:
|
||||||
"type": "comments",
|
"type": "comments",
|
||||||
"network": "Instagram"})
|
"network": "Instagram"})
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des données extraites
|
||||||
ig_comments_df = pd.DataFrame(ig_comments)
|
ig_comments_df = pd.DataFrame(ig_comments)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
ig_comments_df.fillna(value="", inplace=True)
|
ig_comments_df.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les doublons basés sur le texte et la date de création
|
||||||
ig_comments_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
ig_comments_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les commentaires avec un texte vide
|
||||||
# Filter empty texte
|
# Filtrer les textes vides
|
||||||
ig_comments_df = ig_comments_df[~ig_comments_df['texte'].str.strip('\n').str.strip().eq('')]
|
ig_comments_df = ig_comments_df[~ig_comments_df['texte'].str.strip('\n').str.strip().eq('')]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(ig_comments_df)
|
documents_to_database(ig_comments_df)
|
|
@ -6,22 +6,23 @@ from pathlib import Path
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
from utils.convert_encoding_meta import convert_encoding_meta
|
from utils.convert_encoding_meta import convert_encoding_meta
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'threads', 'threads_and_replies.json')
|
instagram_data_path = os.path.join(project_root, 'import_data', 'data', 'Instagram', 'threads', 'threads_and_replies.json')
|
||||||
|
|
||||||
|
## %% Lire et parser le fichier JSON des posts Threads
|
||||||
with open(instagram_data_path, "r") as posts:
|
with open(instagram_data_path, "r") as posts:
|
||||||
post_comments_1 = json.loads(convert_encoding_meta(posts.read()))
|
post_comments_1 = json.loads(convert_encoding_meta(posts.read()))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Extraire les données pertinentes de chaque post Threads
|
||||||
threads_comments = []
|
threads_comments = []
|
||||||
for post in post_comments_1['text_post_app_text_posts']:
|
for post in post_comments_1['text_post_app_text_posts']:
|
||||||
for element in post['media']:
|
for element in post['media']:
|
||||||
|
@ -32,18 +33,18 @@ for post in post_comments_1['text_post_app_text_posts']:
|
||||||
"type": "posts",
|
"type": "posts",
|
||||||
"network": "Threads"})
|
"network": "Threads"})
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des données extraites
|
||||||
ig_comments_df = pd.DataFrame(threads_comments)
|
ig_comments_df = pd.DataFrame(threads_comments)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
ig_comments_df.fillna(value="", inplace=True)
|
ig_comments_df.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les doublons basés sur le texte et la date de création
|
||||||
ig_comments_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
ig_comments_df.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les posts avec un texte vide
|
||||||
# Filter empty texte
|
# Filtrer les textes vides
|
||||||
ig_comments_df = ig_comments_df[~ig_comments_df['texte'].str.strip('\n').str.strip().eq('')]
|
ig_comments_df = ig_comments_df[~ig_comments_df['texte'].str.strip('\n').str.strip().eq('')]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(ig_comments_df)
|
documents_to_database(ig_comments_df)
|
|
@ -6,13 +6,13 @@ from pathlib import Path
|
||||||
|
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
|
@ -20,39 +20,38 @@ linkedin_data_path = os.path.join(project_root, 'import_data', 'data', 'LinkedIn
|
||||||
|
|
||||||
raw_shares = pd.read_csv(linkedin_data_path)
|
raw_shares = pd.read_csv(linkedin_data_path)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Ajouter des colonnes d'identification au DataFrame
|
||||||
raw_shares['index'] = "rs_linkedin_shares"
|
raw_shares['index'] = "rs_linkedin_shares"
|
||||||
raw_shares['type'] = "posts"
|
raw_shares['type'] = "posts"
|
||||||
raw_shares['network'] = "LinkedIn"
|
raw_shares['network'] = "LinkedIn"
|
||||||
raw_shares['chemin'] = linkedin_data_path
|
raw_shares['chemin'] = linkedin_data_path
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Convertir la date en timestamp et supprimer la colonne originale
|
||||||
raw_shares["creation_timestamp"] = raw_shares["Date"].apply(
|
raw_shares["creation_timestamp"] = raw_shares["Date"].apply(
|
||||||
lambda x: int(datetime.datetime.fromisoformat(x).timestamp())
|
lambda x: int(datetime.datetime.fromisoformat(x).timestamp())
|
||||||
)
|
)
|
||||||
del raw_shares["Date"]
|
del raw_shares["Date"]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Renommer les colonnes pour correspondre au format standard
|
||||||
raw_shares.rename(columns={"ShareLink": "uri", "ShareCommentary": "texte"}, inplace=True)
|
raw_shares.rename(columns={"ShareLink": "uri", "ShareCommentary": "texte"}, inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Convertir la colonne 'texte' en type string
|
||||||
raw_shares["texte"] = raw_shares["texte"].apply(lambda x: str(x))
|
raw_shares["texte"] = raw_shares["texte"].apply(lambda x: str(x))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les colonnes non nécessaires
|
||||||
del raw_shares["SharedUrl"]
|
del raw_shares["SharedUrl"]
|
||||||
del raw_shares["MediaUrl"]
|
del raw_shares["MediaUrl"]
|
||||||
del raw_shares["Visibility"]
|
del raw_shares["Visibility"]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
raw_shares.fillna(value="", inplace=True)
|
raw_shares.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les doublons basés sur le texte et la date de création
|
||||||
raw_shares.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
raw_shares.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les partages avec un texte vide
|
||||||
# Filter empty texte
|
# Filtrer les textes vides
|
||||||
raw_shares = raw_shares[~raw_shares['texte'].str.strip('\n').str.strip().eq('')]
|
raw_shares = raw_shares[~raw_shares['texte'].str.strip('\n').str.strip().eq('')]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(raw_shares)
|
documents_to_database(raw_shares)
|
||||||
|
|
|
@ -6,19 +6,19 @@ from pathlib import Path
|
||||||
|
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
linkedin_data_path = os.path.join(project_root, 'import_data', 'data', 'LinkedIn', 'comments', 'Comments.csv')
|
linkedin_data_path = os.path.join(project_root, 'import_data', 'data', 'LinkedIn', 'comments', 'Comments.csv')
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Lire et nettoyer les données CSV des commentaires LinkedIn
|
||||||
raw_comments_csv = pd.read_csv(linkedin_data_path,
|
raw_comments_csv = pd.read_csv(linkedin_data_path,
|
||||||
escapechar='\\',
|
escapechar='\\',
|
||||||
skipinitialspace=True)
|
skipinitialspace=True)
|
||||||
|
@ -26,33 +26,33 @@ raw_comments_csv['MessageFix'] = raw_comments_csv['Message'].str.replace(r'[\r\n
|
||||||
raw_comments_csv = raw_comments_csv.drop(columns=['Message'])
|
raw_comments_csv = raw_comments_csv.drop(columns=['Message'])
|
||||||
raw_comments = raw_comments_csv[(raw_comments_csv['MessageFix'] != "")].drop_duplicates()
|
raw_comments = raw_comments_csv[(raw_comments_csv['MessageFix'] != "")].drop_duplicates()
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Ajouter des colonnes d'identification au DataFrame
|
||||||
raw_comments['index'] = "rs_linkedin_comments"
|
raw_comments['index'] = "rs_linkedin_comments"
|
||||||
raw_comments['type'] = "comments"
|
raw_comments['type'] = "comments"
|
||||||
raw_comments['network'] = "LinkedIn"
|
raw_comments['network'] = "LinkedIn"
|
||||||
raw_comments['chemin'] = linkedin_data_path
|
raw_comments['chemin'] = linkedin_data_path
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Convertir la date en timestamp et supprimer la colonne originale
|
||||||
raw_comments["creation_timestamp"] = raw_comments["Date"].apply(
|
raw_comments["creation_timestamp"] = raw_comments["Date"].apply(
|
||||||
lambda x: int(datetime.datetime.fromisoformat(x).timestamp())
|
lambda x: int(datetime.datetime.fromisoformat(x).timestamp())
|
||||||
)
|
)
|
||||||
del raw_comments["Date"]
|
del raw_comments["Date"]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Renommer les colonnes pour correspondre au format standard
|
||||||
raw_comments.rename(columns={"Link": "uri", "MessageFix": "texte"}, inplace=True)
|
raw_comments.rename(columns={"Link": "uri", "MessageFix": "texte"}, inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Ajouter le chemin du fichier source
|
||||||
raw_comments["chemin"] = linkedin_data_path
|
raw_comments["chemin"] = linkedin_data_path
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
raw_comments.fillna(value="", inplace=True)
|
raw_comments.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Supprimer les doublons basés sur le texte et la date de création
|
||||||
raw_comments.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
raw_comments.drop_duplicates(subset=['texte', 'creation_timestamp'], inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les commentaires avec un texte vide
|
||||||
# Filter empty texte
|
# Filtrer les textes vides
|
||||||
raw_comments = raw_comments[~raw_comments['texte'].str.strip('\n').str.strip().eq('')]
|
raw_comments = raw_comments[~raw_comments['texte'].str.strip('\n').str.strip().eq('')]
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(raw_comments)
|
documents_to_database(raw_comments)
|
|
@ -10,13 +10,13 @@ from pathlib import Path
|
||||||
|
|
||||||
from utils.documents_to_database import documents_to_database
|
from utils.documents_to_database import documents_to_database
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Obtenir le répertoire du fichier courant
|
||||||
# Get the current file's directory
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
# This will work when running as a script
|
# Ceci fonctionnera lors de l'exécution en tant que script
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
# This will work in interactive environments
|
# Ceci fonctionnera dans des environnements interactifs
|
||||||
script_dir = Path().absolute()
|
script_dir = Path().absolute()
|
||||||
|
|
||||||
project_root = script_dir
|
project_root = script_dir
|
||||||
|
@ -25,22 +25,21 @@ wordpress_xml_path = os.path.join(project_root, 'import_data', 'data', 'Wordpres
|
||||||
with open(wordpress_xml_path, "r") as xml_file:
|
with open(wordpress_xml_path, "r") as xml_file:
|
||||||
wordpress_xml = xml_file.read()
|
wordpress_xml = xml_file.read()
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Convertir le XML en dictionnaire Python
|
||||||
wordpress_dict = xmltodict.parse(wordpress_xml)
|
wordpress_dict = xmltodict.parse(wordpress_xml)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Créer un DataFrame à partir des éléments du canal RSS
|
||||||
items_df = pd.DataFrame(wordpress_dict['rss']['channel']['item'])
|
items_df = pd.DataFrame(wordpress_dict['rss']['channel']['item'])
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Filtrer les éléments pour ne garder que les pages et les articles publiés
|
||||||
items_df_filter = items_df[
|
items_df_filter = items_df[
|
||||||
(items_df['wp:post_type'].isin(['page', 'post'])) & (items_df['wp:status'] == 'publish')].copy()
|
(items_df['wp:post_type'].isin(['page', 'post'])) & (items_df['wp:status'] == 'publish')].copy()
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Convertir la date de publication en timestamp
|
||||||
items_df_filter['creation_timestamp'] = items_df_filter['wp:post_date'].apply(
|
items_df_filter['creation_timestamp'] = items_df_filter['wp:post_date'].apply(
|
||||||
lambda x: int(datetime.datetime.fromisoformat(x).timestamp()))
|
lambda x: int(datetime.datetime.fromisoformat(x).timestamp()))
|
||||||
|
|
||||||
|
## %% Définir une fonction pour convertir le contenu WordPress en Markdown
|
||||||
#%% In[ ]:
|
|
||||||
def wp_to_markdown(x):
|
def wp_to_markdown(x):
|
||||||
try:
|
try:
|
||||||
md_text = re.sub(r'\n+', ' ', markdownify.markdownify(x, heading_style='ATX')).strip()
|
md_text = re.sub(r'\n+', ' ', markdownify.markdownify(x, heading_style='ATX')).strip()
|
||||||
|
@ -50,22 +49,21 @@ def wp_to_markdown(x):
|
||||||
pass
|
pass
|
||||||
return md_text
|
return md_text
|
||||||
|
|
||||||
|
## %% Appliquer la conversion Markdown au contenu
|
||||||
#%% In[ ]:
|
|
||||||
items_df_filter['texte'] = items_df_filter['content:encoded'].apply(lambda x: wp_to_markdown(x))
|
items_df_filter['texte'] = items_df_filter['content:encoded'].apply(lambda x: wp_to_markdown(x))
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Renommer les colonnes pour correspondre au format standard
|
||||||
items_df_filter.rename(columns={"link": "uri", "wp:post_type": "type"}, inplace=True)
|
items_df_filter.rename(columns={"link": "uri", "wp:post_type": "type"}, inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Ajouter des colonnes d'identification
|
||||||
items_df_filter['index'] = "rs_wordpress_jevalideca"
|
items_df_filter['index'] = "rs_wordpress_jevalideca"
|
||||||
items_df_filter['network'] = "Wordpress"
|
items_df_filter['network'] = "Wordpress"
|
||||||
items_df_filter['chemin'] = wordpress_xml_path
|
items_df_filter['chemin'] = wordpress_xml_path
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Remplacer les valeurs NaN par des chaînes vides
|
||||||
items_df_filter.fillna(value="", inplace=True)
|
items_df_filter.fillna(value="", inplace=True)
|
||||||
|
|
||||||
#%% In[ ]:
|
## %% Envoyer les données à la base de données
|
||||||
documents_to_database(items_df_filter[['title',
|
documents_to_database(items_df_filter[['title',
|
||||||
'uri',
|
'uri',
|
||||||
'type',
|
'type',
|
||||||
|
@ -73,4 +71,4 @@ documents_to_database(items_df_filter[['title',
|
||||||
'texte',
|
'texte',
|
||||||
'index',
|
'index',
|
||||||
'network',
|
'network',
|
||||||
'chemin']])
|
'chemin']])
|
|
@ -3,7 +3,8 @@ from pathlib import Path
|
||||||
from tqdm import tqdm
|
from tqdm import tqdm
|
||||||
from faster_whisper import WhisperModel
|
from faster_whisper import WhisperModel
|
||||||
|
|
||||||
# Get the current file's directory
|
## %% Configuration du chemin et des répertoires
|
||||||
|
# Obtenir le répertoire du fichier courant
|
||||||
try:
|
try:
|
||||||
script_dir = Path(__file__).parent.parent
|
script_dir = Path(__file__).parent.parent
|
||||||
except NameError:
|
except NameError:
|
||||||
|
@ -13,15 +14,17 @@ project_root = script_dir
|
||||||
podcast_dir = os.path.join(project_root, 'import_data', 'data', 'Podcast', 'audio')
|
podcast_dir = os.path.join(project_root, 'import_data', 'data', 'Podcast', 'audio')
|
||||||
output_dir = os.path.join(project_root, 'import_data', 'data', 'Podcast', 'transcripts')
|
output_dir = os.path.join(project_root, 'import_data', 'data', 'Podcast', 'transcripts')
|
||||||
|
|
||||||
# Create output directory if it doesn't exist
|
# Créer le répertoire de sortie s'il n'existe pas
|
||||||
os.makedirs(output_dir, exist_ok=True)
|
os.makedirs(output_dir, exist_ok=True)
|
||||||
|
|
||||||
# Load Faster-Whisper model
|
## %% Chargement du modèle Faster-Whisper
|
||||||
|
# Charger le modèle Faster-Whisper
|
||||||
model = WhisperModel("small", device="cpu", compute_type="int8")
|
model = WhisperModel("small", device="cpu", compute_type="int8")
|
||||||
|
|
||||||
|
## %% Définition des fonctions de transcription et de création de fichiers SRT
|
||||||
def transcribe_audio(audio_path):
|
def transcribe_audio(audio_path):
|
||||||
l_segments, _ = model.transcribe(audio_path, language="fr", task="transcribe")
|
l_segments, _ = model.transcribe(audio_path, language="fr", task="transcribe")
|
||||||
return list(l_segments) # Convert generator to list
|
return list(l_segments) # Convertir le générateur en liste
|
||||||
|
|
||||||
def create_srt(l_segments, output_path):
|
def create_srt(l_segments, output_path):
|
||||||
with open(output_path, 'w', encoding='utf-8') as f:
|
with open(output_path, 'w', encoding='utf-8') as f:
|
||||||
|
@ -38,15 +41,16 @@ def format_time(seconds):
|
||||||
milliseconds = int((seconds % 1) * 1000)
|
milliseconds = int((seconds % 1) * 1000)
|
||||||
return f"{hours:02d}:{minutes:02d}:{seconds:02d},{milliseconds:03d}"
|
return f"{hours:02d}:{minutes:02d}:{seconds:02d},{milliseconds:03d}"
|
||||||
|
|
||||||
# Process all MP3 files
|
## %% Traitement de tous les fichiers MP3
|
||||||
|
# Traiter tous les fichiers MP3
|
||||||
for filename in tqdm(os.listdir(podcast_dir)):
|
for filename in tqdm(os.listdir(podcast_dir)):
|
||||||
if filename.endswith(".mp3"):
|
if filename.endswith(".mp3"):
|
||||||
mp3_path = os.path.join(podcast_dir, filename)
|
mp3_path = os.path.join(podcast_dir, filename)
|
||||||
srt_path = os.path.join(output_dir, filename.replace(".mp3", ".srt"))
|
srt_path = os.path.join(output_dir, filename.replace(".mp3", ".srt"))
|
||||||
|
|
||||||
print(f"Transcribing {filename}...")
|
print(f"Transcription de {filename}...")
|
||||||
segments = transcribe_audio(mp3_path)
|
segments = transcribe_audio(mp3_path)
|
||||||
create_srt(segments, srt_path)
|
create_srt(segments, srt_path)
|
||||||
print(f"Transcription saved to {srt_path}")
|
print(f"Transcription sauvegardée dans {srt_path}")
|
||||||
|
|
||||||
print("All podcasts have been transcribed.")
|
print("Tous les podcasts ont été transcrits.")
|
|
@ -1,17 +1,28 @@
|
||||||
altair==5.5.0
|
altair==5.5.0
|
||||||
|
annotated-types==0.7.0
|
||||||
attrs==24.2.0
|
attrs==24.2.0
|
||||||
av==13.1.0
|
av==13.1.0
|
||||||
beautifulsoup4==4.12.3
|
beautifulsoup4==4.12.3
|
||||||
blinker==1.9.0
|
blinker==1.9.0
|
||||||
|
blis==1.0.1
|
||||||
cachetools==5.5.0
|
cachetools==5.5.0
|
||||||
|
catalogue==2.0.10
|
||||||
certifi==2024.8.30
|
certifi==2024.8.30
|
||||||
charset-normalizer==3.4.0
|
charset-normalizer==3.4.0
|
||||||
click==8.1.7
|
click==8.1.7
|
||||||
|
cloudpathlib==0.20.0
|
||||||
coloredlogs==15.0.1
|
coloredlogs==15.0.1
|
||||||
|
confection==0.1.5
|
||||||
|
contourpy==1.3.1
|
||||||
ctranslate2==4.5.0
|
ctranslate2==4.5.0
|
||||||
|
cycler==0.12.1
|
||||||
|
cymem==2.0.10
|
||||||
|
en_core_web_sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl#sha256=1932429db727d4bff3deed6b34cfc05df17794f4a52eeb26cf8928f7c1a0fb85
|
||||||
faster-whisper==1.1.0
|
faster-whisper==1.1.0
|
||||||
filelock==3.16.1
|
filelock==3.16.1
|
||||||
flatbuffers==24.3.25
|
flatbuffers==24.3.25
|
||||||
|
fonttools==4.55.0
|
||||||
|
fr_core_news_sm @ https://github.com/explosion/spacy-models/releases/download/fr_core_news_sm-3.8.0/fr_core_news_sm-3.8.0-py3-none-any.whl#sha256=7d6ad14cd5078e53147bfbf70fb9d433c6a3865b695fda2657140bbc59a27e29
|
||||||
fsspec==2024.10.0
|
fsspec==2024.10.0
|
||||||
gitdb==4.0.11
|
gitdb==4.0.11
|
||||||
GitPython==3.1.43
|
GitPython==3.1.43
|
||||||
|
@ -21,22 +32,33 @@ idna==3.10
|
||||||
Jinja2==3.1.4
|
Jinja2==3.1.4
|
||||||
jsonschema==4.23.0
|
jsonschema==4.23.0
|
||||||
jsonschema-specifications==2024.10.1
|
jsonschema-specifications==2024.10.1
|
||||||
|
kiwisolver==1.4.7
|
||||||
|
langcodes==3.5.0
|
||||||
|
langdetect==1.0.9
|
||||||
|
language_data==1.3.0
|
||||||
|
marisa-trie==1.2.1
|
||||||
markdown-it-py==3.0.0
|
markdown-it-py==3.0.0
|
||||||
markdownify==0.11.6
|
markdownify==0.11.6
|
||||||
MarkupSafe==3.0.2
|
MarkupSafe==3.0.2
|
||||||
|
matplotlib==3.9.3
|
||||||
mdurl==0.1.2
|
mdurl==0.1.2
|
||||||
mpmath==1.3.0
|
mpmath==1.3.0
|
||||||
|
murmurhash==1.0.11
|
||||||
narwhals==1.15.0
|
narwhals==1.15.0
|
||||||
numpy==1.26.4
|
numpy==2.0.2
|
||||||
onnxruntime==1.20.1
|
onnxruntime==1.20.1
|
||||||
packaging==24.2
|
packaging==24.2
|
||||||
pandas==2.2.0
|
pandas==2.2.3
|
||||||
pillow==11.0.0
|
pillow==11.0.0
|
||||||
plotly==5.24.1
|
plotly==5.24.1
|
||||||
|
preshed==3.0.9
|
||||||
protobuf==5.29.0
|
protobuf==5.29.0
|
||||||
pyarrow==17.0.0
|
pyarrow==17.0.0
|
||||||
|
pydantic==2.10.2
|
||||||
|
pydantic_core==2.27.1
|
||||||
pydeck==0.9.1
|
pydeck==0.9.1
|
||||||
Pygments==2.18.0
|
Pygments==2.18.0
|
||||||
|
pyparsing==3.2.0
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.9.0.post0
|
||||||
python-dotenv==1.0.1
|
python-dotenv==1.0.1
|
||||||
pytz==2024.2
|
pytz==2024.2
|
||||||
|
@ -46,18 +68,30 @@ requests==2.31.0
|
||||||
rich==13.9.4
|
rich==13.9.4
|
||||||
rpds-py==0.21.0
|
rpds-py==0.21.0
|
||||||
setuptools==75.6.0
|
setuptools==75.6.0
|
||||||
|
shellingham==1.5.4
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
|
smart-open==7.0.5
|
||||||
smmap==5.0.1
|
smmap==5.0.1
|
||||||
soupsieve==2.6
|
soupsieve==2.6
|
||||||
|
spacy==3.8.2
|
||||||
|
spacy-language-detection==0.2.1
|
||||||
|
spacy-legacy==3.0.12
|
||||||
|
spacy-loggers==1.0.5
|
||||||
|
srsly==2.4.8
|
||||||
streamlit==1.40.2
|
streamlit==1.40.2
|
||||||
sympy==1.13.3
|
sympy==1.13.3
|
||||||
tenacity==9.0.0
|
tenacity==9.0.0
|
||||||
|
thinc==8.3.2
|
||||||
tokenizers==0.21.0
|
tokenizers==0.21.0
|
||||||
toml==0.10.2
|
toml==0.10.2
|
||||||
tornado==6.4.2
|
tornado==6.4.2
|
||||||
tqdm==4.67.1
|
tqdm==4.67.1
|
||||||
|
typer==0.14.0
|
||||||
typesense==0.21.0
|
typesense==0.21.0
|
||||||
typing_extensions==4.12.2
|
typing_extensions==4.12.2
|
||||||
tzdata==2024.2
|
tzdata==2024.2
|
||||||
urllib3==2.2.3
|
urllib3==2.2.3
|
||||||
|
wasabi==1.1.3
|
||||||
|
weasel==0.4.1
|
||||||
|
wrapt==1.17.0
|
||||||
xmltodict==0.13.0
|
xmltodict==0.13.0
|
||||||
|
|
|
@ -1,11 +1,72 @@
|
||||||
import tqdm
|
import tqdm
|
||||||
|
import spacy
|
||||||
|
from spacy.language import Language
|
||||||
|
from spacy_language_detection import LanguageDetector
|
||||||
|
from urlextract import URLExtract
|
||||||
|
import requests
|
||||||
|
|
||||||
from .typesense_client import client
|
from .typesense_client import client
|
||||||
|
|
||||||
|
# Load spaCy models
|
||||||
|
nlp_en = spacy.load("en_core_web_sm")
|
||||||
|
nlp_fr = spacy.load("fr_core_news_sm")
|
||||||
|
|
||||||
|
# Create language detector
|
||||||
|
def get_lang_detector(nlp, name):
|
||||||
|
return LanguageDetector(seed=42)
|
||||||
|
|
||||||
|
Language.factory("language_detector", func=get_lang_detector)
|
||||||
|
nlp_en.add_pipe("language_detector", last=True)
|
||||||
|
|
||||||
|
# Initialize URL extractor
|
||||||
|
extractor = URLExtract()
|
||||||
|
|
||||||
|
def count_words(text, lang):
|
||||||
|
if lang == 'en':
|
||||||
|
doc = nlp_en(text)
|
||||||
|
elif lang == 'fr':
|
||||||
|
doc = nlp_fr(text)
|
||||||
|
else:
|
||||||
|
# Default to English if language is not supported
|
||||||
|
doc = nlp_en(text)
|
||||||
|
|
||||||
|
# Count words excluding stopwords
|
||||||
|
word_count = len([token for token in doc if not token.is_stop and not token.is_punct])
|
||||||
|
return word_count
|
||||||
|
|
||||||
|
def resolve_shortened_url(url):
|
||||||
|
try:
|
||||||
|
response = requests.head(url, allow_redirects=True, timeout=5)
|
||||||
|
return response.url
|
||||||
|
except:
|
||||||
|
return url
|
||||||
|
|
||||||
|
def extract_and_resolve_urls(text):
|
||||||
|
urls = extractor.find_urls(text)
|
||||||
|
resolved_urls = [resolve_shortened_url(url) for url in urls]
|
||||||
|
return list(set(resolved_urls)) # Remove duplicates
|
||||||
|
|
||||||
def documents_to_database(documents_list, os_client=client):
|
def documents_to_database(documents_list, os_client=client):
|
||||||
try:
|
try:
|
||||||
for document in tqdm.tqdm(documents_list.to_dict(orient='records')):
|
for document in tqdm.tqdm(documents_list.to_dict(orient='records')):
|
||||||
|
# Detect language
|
||||||
|
doc = nlp_en(document['texte'])
|
||||||
|
lang = doc._.language['language']
|
||||||
|
|
||||||
|
# Count words
|
||||||
|
word_count = count_words(document['texte'], lang)
|
||||||
|
|
||||||
|
# Extract and resolve URLs
|
||||||
|
urls = extract_and_resolve_urls(document['texte'])
|
||||||
|
|
||||||
|
# Add language, word count, and URLs to the document
|
||||||
|
document['langue'] = lang
|
||||||
|
document['nombre_de_mots'] = word_count
|
||||||
|
document['texte_urls'] = urls
|
||||||
|
|
||||||
|
# Create document in Typesense
|
||||||
os_client.collections['social_media_posts'].documents.create(document)
|
os_client.collections['social_media_posts'].documents.create(document)
|
||||||
|
|
||||||
print(f"Successfully inserted {len(documents_list)} documents.")
|
print(f"Successfully inserted {len(documents_list)} documents.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error inserting documents: {str(e)}")
|
print(f"Error inserting documents: {str(e)}")
|
25
search_app_ui/run_streamlit_app.py
Normal file
25
search_app_ui/run_streamlit_app.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
def run_streamlit_app():
|
||||||
|
# Obtenir le chemin du répertoire courant
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
# Construire le chemin vers streamlit_app.py
|
||||||
|
app_path = os.path.join(current_dir, 'streamlit_app.py')
|
||||||
|
|
||||||
|
# Commande pour exécuter l'application Streamlit
|
||||||
|
command = f"streamlit run {app_path}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Exécuter la commande
|
||||||
|
subprocess.run(command, shell=True, check=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Erreur lors du lancement de l'application Streamlit : {e}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Une erreur inattendue s'est produite : {e}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_streamlit_app()
|
|
@ -77,12 +77,15 @@ client = typesense.Client({
|
||||||
'connection_timeout_seconds': 2
|
'connection_timeout_seconds': 2
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def rechercher_documents(cette_requete, ces_filtres=None, facette_par=None):
|
def rechercher_documents(cette_requete, ces_filtres=None, facette_par=None):
|
||||||
parametres_recherche = {
|
parametres_recherche = {
|
||||||
'q': cette_requete,
|
'q': cette_requete,
|
||||||
'query_by': 'texte',
|
'query_by': 'texte,embedding',
|
||||||
'sort_by': 'creation_timestamp:desc',
|
'sort_by': '_text_match(buckets: 10):desc,creation_timestamp:desc',
|
||||||
'per_page': 100,
|
"exclude_fields": "embedding",
|
||||||
|
"prefix": "false",
|
||||||
|
'per_page': 10,
|
||||||
'page': 1
|
'page': 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,31 +95,72 @@ def rechercher_documents(cette_requete, ces_filtres=None, facette_par=None):
|
||||||
if facette_par:
|
if facette_par:
|
||||||
parametres_recherche['facet_by'] = facette_par
|
parametres_recherche['facet_by'] = facette_par
|
||||||
|
|
||||||
all_results = []
|
st.write("Search parameters:", parametres_recherche)
|
||||||
while True:
|
|
||||||
results = client.collections['social_media_posts'].documents.search(parametres_recherche)
|
all_results = []
|
||||||
all_results.extend(results['hits'])
|
try:
|
||||||
if len(all_results) >= results['found']:
|
while True:
|
||||||
break
|
results = client.collections['social_media_posts'].documents.search(parametres_recherche)
|
||||||
parametres_recherche['page'] += 1
|
all_results.extend(results['hits'])
|
||||||
|
if len(all_results) >= results['found']:
|
||||||
|
break
|
||||||
|
parametres_recherche['page'] += 1
|
||||||
|
results['hits'] = all_results
|
||||||
|
return results
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"Error during search: {str(e)}") # Error handling
|
||||||
|
|
||||||
|
|
||||||
|
# Récupérer dynamiquement les réseaux depuis Typesense
|
||||||
|
def get_networks():
|
||||||
|
search_parameters = {
|
||||||
|
'q': '*',
|
||||||
|
'query_by': 'network',
|
||||||
|
'facet_by': 'network',
|
||||||
|
'per_page': 0
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
results = client.collections['social_media_posts'].documents.search(search_parameters)
|
||||||
|
networks = [facet['value'] for facet in results['facet_counts'][0]['counts']]
|
||||||
|
return networks
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"Erreur lors de la récupération des réseaux : {str(e)}")
|
||||||
|
return ['Facebook', 'Instagram', 'Threads', 'LinkedIn', 'WordPress'] # Valeurs par défaut en cas d'erreur
|
||||||
|
|
||||||
results['hits'] = all_results
|
|
||||||
return results
|
|
||||||
|
|
||||||
# Interface utilisateur Streamlit
|
# Interface utilisateur Streamlit
|
||||||
st.title('Recherche dans tes contenus publiés sur le web')
|
st.title('Recherche dans tes contenus publiés sur le web')
|
||||||
|
|
||||||
|
# Indiquer le nombre total de documents indexés dans Typesense
|
||||||
|
collections = client.collections.retrieve()
|
||||||
|
total_documents = sum(collection['num_documents'] for collection in collections)
|
||||||
|
|
||||||
|
st.write(f"Total documents indexés: {total_documents}")
|
||||||
|
|
||||||
# Champ de recherche
|
# Champ de recherche
|
||||||
requete = st.text_input('Entrez votre requête de recherche')
|
requete = st.text_input('Entrez votre requête de recherche')
|
||||||
|
|
||||||
# Filtre de plage de dates
|
# Filtre de plage de dates
|
||||||
col1, col2 = st.columns(2)
|
col1, col2 = st.columns(2)
|
||||||
date_debut = col1.date_input('Date de début')
|
date_debut = col1.date_input('Date de début', value=datetime.now() - pd.DateOffset(years=1))
|
||||||
date_fin = col2.date_input('Date de fin')
|
date_fin = col2.date_input('Date de fin', value=datetime.now())
|
||||||
|
|
||||||
# Filtre de réseau social
|
# Filtre de réseau social
|
||||||
reseaux = ['Facebook', 'Instagram', 'Threads' ,'LinkedIn', 'WordPress']
|
|
||||||
reseaux_selectionnes = st.multiselect('Sélectionnez les réseaux sociaux', reseaux)
|
reseaux = get_networks()
|
||||||
|
reseaux_selectionnes = st.multiselect('Sélectionnez les réseaux sociaux', reseaux,
|
||||||
|
default=reseaux[0] if reseaux else None)
|
||||||
|
|
||||||
|
# Filtre de langue
|
||||||
|
langues = [('fr', 'Français'), ('en', 'English')]
|
||||||
|
langue_selectionnees = st.multiselect('Sélectionnez la langue',
|
||||||
|
options=[label for code, label in langues],
|
||||||
|
format_func=lambda x: x,
|
||||||
|
default='Français')
|
||||||
|
|
||||||
|
# Convertir les étiquettes en codes de langage
|
||||||
|
selected_lang_codes = [code for code, label in langues if label in langue_selectionnees]
|
||||||
|
|
||||||
if st.button('Rechercher'):
|
if st.button('Rechercher'):
|
||||||
# Préparer les filtres
|
# Préparer les filtres
|
||||||
|
@ -124,8 +168,9 @@ if st.button('Rechercher'):
|
||||||
fin_datetime = datetime.combine(date_fin, time.max)
|
fin_datetime = datetime.combine(date_fin, time.max)
|
||||||
filtre_date = f"creation_timestamp:[{int(debut_datetime.timestamp())}..{int(fin_datetime.timestamp())}]"
|
filtre_date = f"creation_timestamp:[{int(debut_datetime.timestamp())}..{int(fin_datetime.timestamp())}]"
|
||||||
filtre_reseau = f"network:[{' '.join(reseaux_selectionnes)}]" if reseaux_selectionnes else None
|
filtre_reseau = f"network:[{' '.join(reseaux_selectionnes)}]" if reseaux_selectionnes else None
|
||||||
|
filtre_langue = f"langue:[{' '.join(selected_lang_codes)}]" if selected_lang_codes else None
|
||||||
|
|
||||||
filtres = ' && '.join(filter(None, [filtre_date, filtre_reseau]))
|
filtres = ' && '.join(filter(None, [filtre_date, filtre_reseau, filtre_langue]))
|
||||||
|
|
||||||
# Effectuer la recherche pour tous les résultats
|
# Effectuer la recherche pour tous les résultats
|
||||||
tous_resultats = rechercher_documents(requete, ces_filtres=filtres, facette_par='network')
|
tous_resultats = rechercher_documents(requete, ces_filtres=filtres, facette_par='network')
|
||||||
|
@ -133,14 +178,44 @@ if st.button('Rechercher'):
|
||||||
|
|
||||||
# Afficher le nombre total de résultats
|
# Afficher le nombre total de résultats
|
||||||
st.subheader(f"Trouvé {nombre_total_resultats} résultats")
|
st.subheader(f"Trouvé {nombre_total_resultats} résultats")
|
||||||
|
|
||||||
|
# Affichage des résultats (100 maximum)
|
||||||
|
st.subheader("Résultats de la recherche")
|
||||||
|
|
||||||
|
for hit in tous_resultats['hits'][:100]: # Limite à 100 résultats
|
||||||
|
col1, col2 = st.columns([1, 4])
|
||||||
|
|
||||||
|
with col1:
|
||||||
|
st.markdown(f"**{hit['document']['network']}**")
|
||||||
|
st.markdown(
|
||||||
|
f"**{datetime.fromtimestamp(hit['document']['creation_timestamp']).strftime('%Y-%m-%d %H:%M:%S')}**")
|
||||||
|
|
||||||
|
# Étiquettes de couleur pour les facettes
|
||||||
|
st.markdown(f"""
|
||||||
|
<span style="background-color: #007bff; color: white; padding: 2px 6px; border-radius: 10px;">
|
||||||
|
{hit['document']['langue']}
|
||||||
|
</span>
|
||||||
|
""", unsafe_allow_html=True)
|
||||||
|
|
||||||
|
with col2:
|
||||||
|
# Boîte de texte pour le contenu
|
||||||
|
st.text_area("Contenu", hit['document']['texte'], height=150)
|
||||||
|
|
||||||
|
# URI en dessous
|
||||||
|
if 'uri' in hit['document']:
|
||||||
|
st.markdown(f"[Lien vers le post original]({hit['document']['uri']})")
|
||||||
|
|
||||||
|
st.markdown("---")
|
||||||
|
|
||||||
# Afficher les facettes
|
# Afficher les facettes
|
||||||
if 'facet_counts' in tous_resultats:
|
if 'facet_counts' in tous_resultats:
|
||||||
facettes_reseau = {facette['value']: facette['count'] for facette in tous_resultats['facet_counts'][0]['counts']}
|
facettes_reseau = {facette['value']: facette['count'] for facette in
|
||||||
|
tous_resultats['facet_counts'][0]['counts']}
|
||||||
st.subheader("Résultats par Réseau")
|
st.subheader("Résultats par Réseau")
|
||||||
|
|
||||||
# Graphique en camembert pour montrer la distribution des résultats par réseau social
|
# Graphique en camembert pour montrer la distribution des résultats par réseau social
|
||||||
fig = px.pie(values=list(facettes_reseau.values()), names=list(facettes_reseau.keys()), title="Distribution par Réseau")
|
fig = px.pie(values=list(facettes_reseau.values()), names=list(facettes_reseau.keys()),
|
||||||
|
title="Distribution par Réseau")
|
||||||
# Ce graphique montre la proportion de résultats pour chaque réseau social
|
# Ce graphique montre la proportion de résultats pour chaque réseau social
|
||||||
st.plotly_chart(fig)
|
st.plotly_chart(fig)
|
||||||
|
|
||||||
|
@ -180,21 +255,3 @@ if st.button('Rechercher'):
|
||||||
df_pivot['mois'] = df_pivot['mois'].dt.strftime('%B %Y')
|
df_pivot['mois'] = df_pivot['mois'].dt.strftime('%B %Y')
|
||||||
# Ce tableau fournit un résumé détaillé du nombre de posts par réseau social pour chaque mois
|
# Ce tableau fournit un résumé détaillé du nombre de posts par réseau social pour chaque mois
|
||||||
st.dataframe(df_pivot)
|
st.dataframe(df_pivot)
|
||||||
|
|
||||||
# Créer une chaîne pour contenir tous les résultats
|
|
||||||
all_results_text = ""
|
|
||||||
|
|
||||||
# Peupler la chaîne avec tous les résultats
|
|
||||||
for hit in tous_resultats['hits']:
|
|
||||||
horodatage = hit['document']['creation_timestamp']
|
|
||||||
all_results_text += f"**{hit['document']['network']}** - {datetime.fromtimestamp(horodatage).strftime('%Y-%m-%d %H:%M:%S')}\n\n"
|
|
||||||
|
|
||||||
paragraphes = hit['document']['texte'].split('\n')
|
|
||||||
for paragraphe in paragraphes:
|
|
||||||
if paragraphe.strip():
|
|
||||||
all_results_text += f"{paragraphe}\n\n"
|
|
||||||
|
|
||||||
all_results_text += "---\n\n"
|
|
||||||
|
|
||||||
# Afficher les résultats dans une zone de texte
|
|
||||||
st.text_area("Résultats de la recherche", all_results_text, height=400)
|
|
106
typesense_stats/typesense_stats.py
Normal file
106
typesense_stats/typesense_stats.py
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import typesense
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
## %% Configuration initiale
|
||||||
|
# Charger les variables d'environnement et initialiser le client Typesense
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# Initialiser le client Typesense
|
||||||
|
client = typesense.Client({
|
||||||
|
'nodes': [{
|
||||||
|
'host': os.getenv('TYPESENSE_HOST', 'localhost'),
|
||||||
|
'port': os.getenv('TYPESENSE_PORT', '8108'),
|
||||||
|
'protocol': os.getenv('TYPESENSE_PROTOCOL', 'http')
|
||||||
|
}],
|
||||||
|
'api_key': os.getenv('TYPESENSE_API_KEY'),
|
||||||
|
'connection_timeout_seconds': 2
|
||||||
|
})
|
||||||
|
|
||||||
|
## %% Fonction pour obtenir les statistiques d'index
|
||||||
|
def get_index_stats():
|
||||||
|
collections = client.collections.retrieve()
|
||||||
|
total_documents = sum(collection['num_documents'] for collection in collections)
|
||||||
|
|
||||||
|
print(f"Nombre total de documents indexés : {total_documents}")
|
||||||
|
print("\nStatistiques par collection :")
|
||||||
|
for collection in collections:
|
||||||
|
print(f" {collection['name']}: {collection['num_documents']} documents")
|
||||||
|
|
||||||
|
## %% Fonction pour obtenir la distribution par réseau social
|
||||||
|
def get_network_distribution():
|
||||||
|
search_parameters = {
|
||||||
|
'q': '*',
|
||||||
|
'query_by': 'texte',
|
||||||
|
'facet_by': 'network',
|
||||||
|
'per_page': 0
|
||||||
|
}
|
||||||
|
|
||||||
|
result = client.collections['social_media_posts'].documents.search(search_parameters)
|
||||||
|
|
||||||
|
network_counts = {facet['value']: facet['count'] for facet in result['facet_counts'][0]['counts']}
|
||||||
|
|
||||||
|
print("\nDistribution par réseau social :")
|
||||||
|
for network, count in network_counts.items():
|
||||||
|
print(f" {network}: {count}")
|
||||||
|
|
||||||
|
## %% Fonction pour obtenir la distribution temporelle
|
||||||
|
def get_temporal_distribution():
|
||||||
|
search_parameters = {
|
||||||
|
'q': '*',
|
||||||
|
'query_by': 'texte',
|
||||||
|
'per_page': 250, # Maximum autorisé par Typesense
|
||||||
|
'sort_by': 'creation_timestamp:asc',
|
||||||
|
'page': 1
|
||||||
|
}
|
||||||
|
|
||||||
|
all_dates = []
|
||||||
|
while True:
|
||||||
|
result = client.collections['social_media_posts'].documents.search(search_parameters)
|
||||||
|
|
||||||
|
if not result['hits']:
|
||||||
|
break
|
||||||
|
|
||||||
|
dates = [datetime.fromtimestamp(hit['document']['creation_timestamp']) for hit in result['hits']]
|
||||||
|
all_dates.extend(dates)
|
||||||
|
|
||||||
|
search_parameters['page'] += 1
|
||||||
|
|
||||||
|
df = pd.DataFrame({'date': all_dates})
|
||||||
|
df['month'] = df['date'].dt.to_period('M')
|
||||||
|
monthly_counts = df['month'].value_counts().sort_index()
|
||||||
|
|
||||||
|
print("\nDistribution temporelle (par mois) :")
|
||||||
|
for month, count in monthly_counts.items():
|
||||||
|
print(f" {month}: {count}")
|
||||||
|
|
||||||
|
## %% Fonction pour obtenir un échantillon de documents
|
||||||
|
def get_document_sample(sample_size=5):
|
||||||
|
search_parameters = {
|
||||||
|
'q': '*',
|
||||||
|
'query_by': 'texte',
|
||||||
|
'per_page': sample_size,
|
||||||
|
'sort_by': 'creation_timestamp:desc'
|
||||||
|
}
|
||||||
|
|
||||||
|
result = client.collections['social_media_posts'].documents.search(search_parameters)
|
||||||
|
|
||||||
|
print(f"\nÉchantillon de {sample_size} documents récents :")
|
||||||
|
for hit in result['hits']:
|
||||||
|
doc = hit['document']
|
||||||
|
print(f"\n ID: {doc.get('id', 'N/A')}")
|
||||||
|
print(f" Réseau: {doc.get('network', 'N/A')}")
|
||||||
|
print(f" Type: {doc.get('type', 'N/A')}")
|
||||||
|
print(f" Date: {datetime.fromtimestamp(doc['creation_timestamp']).strftime('%Y-%m-%d %H:%M:%S')}")
|
||||||
|
print(f" Texte: {doc.get('texte', 'N/A')[:100]}...") # Afficher les 100 premiers caractères du texte
|
||||||
|
print(f" URL: {doc.get('uri', 'N/A')}")
|
||||||
|
print(f" Langue: {doc.get('langue', 'N/A')}")
|
||||||
|
|
||||||
|
## %% Point d'entrée principal du script
|
||||||
|
if __name__ == "__main__":
|
||||||
|
get_index_stats()
|
||||||
|
get_network_distribution()
|
||||||
|
get_temporal_distribution()
|
||||||
|
get_document_sample()
|
Loading…
Reference in a new issue