Introduction

Dans le domaine de la recherche en Sciences Humaines, l’analyse des données provenant de médias alternatifs tels que YouTube revêt un intérêt croissant. Ces plateformes offrent un « vaste réservoir » de données générées par les utilisateurs, notamment à travers les commentaires, qui peuvent fournir des insights précieux sur divers sujets, opinions et comportements sociaux.

Cette démarche s’inscrit dans une tendance d’exploration des médias sociaux en tant que source de données pour la recherche en Sciences Humaines. Par exemple, le travail de Pascal Marchand et Pierre Ratinaud sur une analyse lexicométrique des tweets utilisant le hashtag « #mariagepourtous » a démontré la valeur des médias sociaux pour comprendre les débats sociétaux et politiques en temps réel.

Cependant, avec les restrictions croissantes imposées par Twitter, ainsi que l’orientation politique émergente de la plateforme, l’extraction des données via X devient complexe. De plus, les changements récents sur X ont entraîné un exode d’utilisateurs mécontents de la nouvelle orientation de la plateforme. L’accès aux données, mais également la réduction de l’intensité des débats et interactions, rendent l’analyse des tweets moins riche.

Dans mes explorations précédentes autour des possibilités offertes par les médias alternatifs, j’ai testé la récupération de données à partir de fichiers audio transcrits via la technologie de speech-to-text. Cette approche s’est avérée intéressante même si elle n’est pas parfaite car elle nécessite un post-traitement du corpus pour une utilisation avec IRaMuTeq.

Dans ce contexte, YouTube émerge comme une alternative prometteuse pour la collecte de données dans le cadre de la recherche en Sciences Humaines.

La vidéo du professeur Raoult qui m’a servi pour élaborer le script, a suscité pas moins de 5476 commentaires en seulement 11 jours… Toutefois, il convient de noter que ce chiffre inclut de nombreuses réponses aux commentaires, des commentaires de second niveau qui ne sont pas toujours très intéressant pour les analyses.

Le script magique 😉

Le script présenté permet de récupérer diverses informations essentielles d’une vidéo YouTube, telles que le titre, la chaîne, et la date de mise en ligne. Ces éléments pourront être encodés comme des variables étoilées dans le logiciel IRaMuTeq.

En ce qui concerne les commentaires, le script extrait le nom du profil sans le caractère « @ » et reformate la date pour une meilleure lisibilité. De plus, il supprime les emojis des commentaires, (toujours dans l’idée de préparer le corpus à une exploration dans IRAMUTEQ).
Toutefois dans le cadre des techniques s’appuyant sur le NLP je ne sais pas si les émojis sont potentiellement reconnus notamment dans le cadre d’une analyse de sentiments (TextBlob… Bert… CamemBERT)
Bien que les commentaires de niveau 2 soient disponibles en activant les lignes correspondantes dans le script, j’ai une petite hésitation quand à l’utilité de ces commentaires qui apporte souvent de la confusion, ainsi pour une analyse plus concise je conseille de rester sur les commentaire de premier niveau.

En cas d’affichage des réponses aux commentaires, la mention « Reply : » précède chaque réponse pour pouvoir les identifier.

Enfin, il faut noter que le script fonctionne avec des url « classiques » de vidéo YouTube mais également avec des shorts (format court à l’image des « reels » pour instagram). Ce dernier point est important car une longue vidéo peut être fractionnée en « shorts » ce qui génère des commentaires supplémentaires…

 

import re
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from datetime import datetime

# Votre clé API pour YouTube Data API
api_key = 'ici votre clé API YouTube' # Remplacez par votre clé API

# URL de votre vidéo YouTube ou YouTube Shorts
url_video = 'https://youtube.com/shorts/WraeFTmQ-Sg?si=748QYhUIU0760x6V'  # Remplacez par l'URL de votre choix

# Extraction de l'ID de la vidéo à partir de l'URL, compatible avec les URLs de YouTube et YouTube Shorts
match = re.search(r"((?<=[?&]v=)|(?<=/videos/)|(?<=/shorts/))([a-zA-Z0-9_-]+)", url_video)
if not match:
    raise ValueError("L'URL de la vidéo ne semble pas valide.")

video_id = match.group(2)  # Modification ici pour capturer le bon groupe

# Initialisation du client YouTube API
youtube = build('youtube', 'v3', developerKey=api_key)

def remove_emojis(text):
    emoji_pattern = re.compile("["
                               u"\U0001F600-\U0001F64F"  # emoticons
                               u"\U0001F300-\U0001F5FF"  # symbols & pictographs
                               u"\U0001F680-\U0001F6FF"  # transport & map symbols
                               u"\U0001F700-\U0001F77F"  # alchemical symbols
                               u"\U0001F780-\U0001F7FF"  # Geometric Shapes Extended
                               u"\U0001F800-\U0001F8FF"  # Supplemental Arrows-C
                               u"\U0001F900-\U0001F9FF"  # Supplemental Symbols and Pictographs
                               u"\U0001FA00-\U0001FA6F"  # Chess Symbols
                               u"\U0001FA70-\U0001FAFF"  # Symbols and Pictographs Extended-A
                               u"\U00002702-\U000027B0"  # Dingbats
                               u"\U000024C2-\U0001F251"
                               "]+", flags=re.UNICODE)
    return emoji_pattern.sub(r'', text)  # Supprime les emojis du texte

def get_video_details(video_id):
    response = youtube.videos().list(
        part="snippet",
        id=video_id
    ).execute()

    if not response['items']:
        return None, None  # Si aucune vidéo n'est trouvée

    video_details = response['items'][0]['snippet']
    title = remove_emojis(video_details['title'])  # Supprime les emojis du titre
    published_at = video_details['publishedAt']
    return title, published_at

def fetch_comments(video_id, max_results=100):
    # Fonction pour récupérer les commentaires de la vidéo
    comments = []
    try:
        response = youtube.commentThreads().list(
            part="snippet",
            videoId=video_id,
            textFormat="plainText",
            maxResults=max_results,
            order="time"  # Récupère également les réponses aux commentaires, triées par date
        ).execute()

        while response:
            for item in response['items']:
                # Récupérer le commentaire de niveau supérieur (niveau 1)
                comment = item['snippet']['topLevelComment']['snippet']['textDisplay']
                comment = remove_emojis(comment).lower()  # Nettoyer les emojis et passer en minuscules
                author = item['snippet']['topLevelComment']['snippet']['authorDisplayName']
                author = author.replace("@", "")  # Supprimer le symbole "@" devant le nom de l'utilisateur
                published_at = item['snippet']['topLevelComment']['snippet']['publishedAt']
                published_date = datetime.strptime(published_at, '%Y-%m-%dT%H:%M:%SZ').date()
                comments.append(f'{author} - {published_date}\n{comment}\n\n')

                # Récupérer les réponses aux commentaires (niveau 2)
                # Décommentez les lignes suivantes pour récupérer également les réponses aux commentaires
                # reply_response = youtube.comments().list(
                    # part="snippet",
                    # parentId=item['id'],  # ID du commentaire de niveau supérieur
                    # textFormat="plainText"
                # ).execute()

                # Décommentez les lignes suivantes pour récupérer également les réponses aux commentaires
                # for reply_item in reply_response['items']:
                    # reply_comment = reply_item['snippet']['textDisplay']
                    # reply_comment = remove_emojis(reply_comment).lower()  # Nettoyer les emojis et passer en minuscules
                    # reply_author = reply_item['snippet']['authorDisplayName']
                    # reply_author = reply_author.replace("@", "")  # Supprimer le symbole "@" devant le nom de l'utilisateur
                    # reply_published_at = reply_item['snippet']['publishedAt']
                    # reply_published_date = datetime.strptime(reply_published_at, '%Y-%m-%dT%H:%M:%SZ').date()
                    # comments.append(f'Reply : {reply_author} - {reply_published_date}\n{reply_comment}\n\n')

            if 'nextPageToken' in response:
                response = youtube.commentThreads().list(
                    part="snippet",
                    videoId=video_id,
                    pageToken=response['nextPageToken'],
                    textFormat="plainText",
                    maxResults=max_results
                ).execute()
            else:
                break

    except HttpError as e:
        print(f"An HTTP error {e.resp.status} occurred:\n{e.content}")

    return comments

def get_channel_name(video_id):
    # Fonction pour récupérer le nom de la chaîne YouTube à partir de l'ID de la vidéo
    response = youtube.videos().list(
        part="snippet",
        id=video_id
    ).execute()

    if not response['items']:
        return None  # Si aucune vidéo n'est trouvée, retourne None pour le nom de la chaîne

    channel_title = response['items'][0]['snippet']['channelTitle']
    return channel_title

def save_data_to_file(title, published_at, channel_name, comments, filename='youtube_comments.txt'):
    # Fonction pour sauvegarder les données dans un fichier texte
    with open(filename, 'w', encoding='utf-8') as file:
        published_date = datetime.strptime(published_at, '%Y-%m-%dT%H:%M:%SZ').date()
        file.write(f'Channel: {channel_name}\nTitle: {title.replace("Published at:", "").strip()} - {published_date.strftime("%d-%m-%Y")}\n\nComments:\n\n')
        for comment in comments:
            file.write(comment)

# Récupère les détails de la vidéo
title, published_at = get_video_details(video_id)
channel_name = get_channel_name(video_id)
# Vérifie si les détails de la vidéo sont disponibles
if title is None or published_at is None or channel_name is None:
    print("Failed to fetch video details.")
else:
    # Récupère les commentaires de la vidéo
    comments = fetch_comments(video_id)
    # Sauvegarde les données dans un fichier
    save_data_to_file(title, published_at, channel_name, comments)
    # Affiche un message de confirmation
    print(f'{len(comments)} Les commentaires sont sauvegardés dans le fichier youtube_comments.txt along with video details.')

En conclusion, bien que le script puisse nécessiter des ajustements pour une utilisation optimale avec IRaMuTeQ, il reste un outil précieux pour collecter des données à partir des commentaires YouTube.
Sa flexibilité permet de s’adapter aux besoins spécifiques de chaque projet de recherche en Sciences humaines.

 

1 commentaire

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.