Comment récupérer des données vitales sur YouTube avec Python

Commentaires: 0

Les créateurs de YouTube doivent évaluer la performance de leurs vidéos ; l'analyse des commentaires positifs et négatifs et la comparaison de leur contenu avec d'autres dans la même catégorie ou dans des catégories différentes deviennent essentielles.

Passer manuellement au crible les vidéos publiées peut s'avérer fastidieux et chronophage pour les créateurs. C'est précisément là qu'un script de scraping YouTube devient inestimable. Dans ce guide, nous allons développer un script YouTube conçu pour automatiser le processus de collecte de données.

Création d'un scraper pour extraire des données de YouTube

Pour que le script fonctionne correctement, nous devons installer certains paquets. Le premier paquet à installer est selenium-wire, une extension de Selenium qui permet une configuration correcte du proxy, et Selenium lui-même pour les classes et modules essentiels. Pour installer ces paquets, exécutez la commande suivante dans votre interface de commande :

pip install selenium-wire selenium blinker==1.7.0

Concentrons-nous maintenant sur les importations.

Étape 1 : Importation des bibliothèques et des paquets

À ce stade, il est important d'importer les bibliothèques et les paquets qui seront utilisés dans notre script pour interagir avec les éléments Web. En outre, nous devrions inclure des modules pour le traitement des données et la gestion du temps d'exécution afin d'assurer une exécution efficace du script.

from selenium.webdriver.chrome.options import Options
from seleniumwire import webdriver as wiredriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import json
import time

Le module json permet de convertir les données extraites en données JSON correctement formatées, ce qui garantit une présentation optimale des données. Bien qu'il masque notre IP, le module time est essentiel pour introduire un caractère aléatoire dans les actions, empêchant ainsi l'apparition d'un comportement semblable à celui d'un script.

En outre, ce module est essentiel pour s'assurer que les éléments dont nous avons besoin pour extraire les données de la page ont été chargés. Les importations restantes consistent en des classes ou des sous-modules nécessaires qui effectuent des actions distinctes et qui seront développées dans les sections suivantes du code.

Étape 2 : Configuration du pilote Selenium Chrome

Chaque fois que vous exécutez une instance Selenium à l'aide d'un script en python, le script utilise notre adresse IP pour n'importe quelle activité que nous souhaitons effectuer. C'est dangereux, surtout pour des sites web comme YouTube qui ont des politiques strictes contre l'extraction d'informations de leur site web, vous pouvez consulter leur fichier robots pour une meilleure référence. Vous pouvez consulter leur fichier robots pour une meilleure référence. Les conséquences de cette situation peuvent être des restrictions temporaires d'accès au contenu de YouTube pour votre adresse IP.

Pour éviter tout cela, il y a deux ou trois choses à faire. Nous devons créer 3 variables pour héberger les détails du proxy par lequel nous accèderons à la page. Nous créons ensuite une variable d'options, chrome_options, que nous transmettrons à l'instance Chrome WebDriver afin que Selenium sache quel proxy utiliser lors du scraping. Nous passons les détails du proxy en tant qu'arguments pour chrome_options et notre proxy est défini.

# Spécifier l'adresse du serveur proxy avec le nom d'utilisateur et le mot de passe
proxy_address = ""
proxy_username = ""
proxy_password = ""
# Configurer les options de Chrome avec le proxy et l'authentification
chrome_options = Options()
chrome_options.add_argument(f'--proxy-server={proxy_address}')
chrome_options.add_argument(f'--proxy-auth={proxy_username}:{proxy_password}')
# Créer une instance de WebDriver avec selenium-wire
driver = wiredriver.Chrome(options=chrome_options)

Étape 3 : Extraction des informations de la page vidéo YouTube

Créez une variable nommée "youtube_url_to_scrape" pour stocker l'URL de la page d'atterrissage YouTube. Cette variable est ensuite utilisée dans la méthode "driver.get()" pour demander à Selenium d'ouvrir une page spécifique pour le scraping. L'exécution de cette action ouvrira une fenêtre Chrome distincte lors de l'exécution du script.

youtube_url_to_scrape = ""
# Réalisez vos automatisations Selenium avec les capacités améliorées de selenium-wire
driver.get(youtube_url_to_scrape)

Ensuite, nous définissons la fonction "extract _information()" qui, comme son nom l'indique, extrait les informations nécessaires de la page.

Il est important de s'assurer que tous les éléments de la page sont chargés. Pour ce faire, nous utilisons la classe WebDriverWait pour mettre le script en pause au moins jusqu'à ce que le bouton "more" soit disponible et cliqué, ce qui est mis en œuvre sous la variable "element". Une fois disponible, Selenium exécute une action de clic JavaScript qui permet d'accéder à la description complète de la vidéo.

Pour résoudre le problème des commentaires dynamiques mentionné plus haut, nous mettons en œuvre une solution pour éliminer tout problème connexe. À l'aide de la classe Actions et du module Time, nous faisons défiler la page deux fois toutes les 10 secondes, en veillant à récupérer autant de commentaires que possible. Cette approche proactive protège contre les goulets d'étranglement potentiels associés au contenu chargé dynamiquement.

def extract_information() -> dict:
   try:
       element = WebDriverWait(driver, 15).until(
           EC.presence_of_element_located((By.XPATH, '//*[@id="expand"]'))
       )

       element.click()

       time.sleep(10)
       actions = ActionChains(driver)
       actions.send_keys(Keys.END).perform()
       time.sleep(10)
       actions.send_keys(Keys.END).perform()
       time.sleep(10)

Il existe différentes façons de rechercher des éléments à l'aide de selenium webdriver. Vous pouvez rechercher par ID, CLASS_NAME, XPATH, etc. Pour ce guide, nous utiliserons une combinaison plutôt qu'une seule méthode.

XPATH est un système plus complexe mais basé sur des modèles pour localiser les variables pendant le scraping. Il est considéré comme le plus compliqué, mais Chrome l'a simplifié.

Lorsque vous examinez le code à l'aide de l'outil d'inspection de Chrome, il vous suffit de cliquer avec le bouton droit de la souris pour copier le XPATH. Une fois copié, vous pouvez utiliser la fonction `find_elements` pour identifier tous les éléments contenant les informations souhaitées, comme le titre de la vidéo, la description, etc.

Il est essentiel de noter que certains éléments de la page peuvent partager des attributs similaires, ce qui peut amener l'appel `find_elements()` à renvoyer une liste plutôt qu'une chaîne. Dans ce cas, vous devez examiner la liste pour repérer l'index des informations pertinentes et extraire le texte.

En conclusion, une variable dictionnaire nommée `data` est renvoyée, encapsulant toutes les informations recueillies pendant le scraping, ce qui est essentiel pour la section suivante.

 video_title = driver.find_elements(By.XPATH, '//*[@id="title"]/h1')[0].text

   owner = driver.find_elements(By.XPATH, '//*[@id="text"]/a')[0].text

   total_number_of_subscribers = \
       driver.find_elements(By.XPATH, "//div[@id='upload-info']//yt-formatted-string[@id='owner-sub-count']")[
           0].text

   video_description = driver.find_elements(By.XPATH,                                  '//*[@id="description-inline-expander"]/yt-attributed-string/span/span')
   result = []
   for i in video_description:
       result.append(i.text)
   description = ''.join(result)

   publish_date = driver.find_elements(By.XPATH, '//*[@id="info"]/span')[2].text
   total_views = driver.find_elements(By.XPATH, '//*[@id="info"]/span')[0].text

   number_of_likes = driver.find_elements(By.XPATH,                                   '//*[@id="top-level-buttons-computed"]/segmented-like-dislike-button-view-model/yt-smartimation/div/div/like-button-view-model/toggle-button-view-model/button-view-model/button/div')[
       1].text

   comment_names = driver.find_elements(By.XPATH, '//*[@id="author-text"]/span')
   comment_content = driver.find_elements(By.XPATH, '//*[@id="content-text"]/span')
   comment_library = []

   for each in range(len(comment_names)):
       name = comment_names[each].text
       content = comment_content[each].text
       indie_comment = {
           'name': name,
           'comment': content
       }
       comment_library.append(indie_comment)

   data = {
       'owner': owner,
       'subscribers': total_number_of_subscribers,
       'video_title': video_title,
       'description': description,
       'date': publish_date,
       'views': total_views,
       'likes': number_of_likes,
       'comments': comment_library
   }

   return data

except Exception as err:
   print(f"Error: {err}")

Étape 4 : Écrire les données recueillies dans un fichier JSON

def organize_write_data(data:dict):
    output = json.dumps(data, indent=2, ensure_ascii=False).encode("ascii", "ignore").decode("utf-8")
    try:
        with open("output.json", 'w', encoding='utf-8') as file:
            file.write(output)
    except Exception as err:
        print(f"Error encountered: {err}")

La fonction `organize_write_data()` prend les `data` retournés en entrée et les organise en une structure JSON formatée. Elle écrit ensuite ces données organisées dans un fichier de sortie nommé "output.json" tout en gérant les erreurs potentielles pendant le processus d'écriture du fichier.

Code complet

Pour l'instant, voici le code complet de notre programme de scraping :

from selenium.webdriver.chrome.options import Options
from seleniumwire import webdriver as wiredriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import json
import time

# Spécifier l'adresse du serveur proxy avec le nom d'utilisateur et le mot de passe
proxy_address = ""
proxy_username = ""
proxy_password = ""

# Configurer les options de Chrome avec le proxy et l'authentification
chrome_options = Options()
chrome_options.add_argument(f'--proxy-server={proxy_address}')
chrome_options.add_argument(f'--proxy-auth={proxy_username}:{proxy_password}')

# Créer une instance de WebDriver avec selenium-wire
driver = wiredriver.Chrome(options=chrome_options)

youtube_url_to_scrape = ""

# Réalisez vos automatisations Selenium avec les capacités améliorées de selenium-wire
driver.get(youtube_url_to_scrape)


def extract_information() -> dict:
   try:
       element = WebDriverWait(driver, 15).until(
           EC.presence_of_element_located((By.XPATH, '//*[@id="expand"]'))
       )
       element.click()

       time.sleep(10)
       actions = ActionChains(driver)
       actions.send_keys(Keys.END).perform()
       time.sleep(10)
       actions.send_keys(Keys.END).perform()
       time.sleep(10)

       video_title = driver.find_elements(By.XPATH, '//*[@id="title"]/h1')[0].text

       owner = driver.find_elements(By.XPATH, '//*[@id="text"]/a')[0].text
       total_number_of_subscribers = \
           driver.find_elements(By.XPATH, "//div[@id='upload-info']//yt-formatted-string[@id='owner-sub-count']")[
               0].text

       video_description = driver.find_elements(By.XPATH,
                                                '//*[@id="description-inline-expander"]/yt-attributed-string/span/span')
       result = []
       for i in video_description:
           result.append(i.text)
       description = ''.join(result)

       publish_date = driver.find_elements(By.XPATH, '//*[@id="info"]/span')[2].text
       total_views = driver.find_elements(By.XPATH, '//*[@id="info"]/span')[0].text

       number_of_likes = driver.find_elements(By.XPATH,
                                              '//*[@id="top-level-buttons-computed"]/segmented-like-dislike-button-view-model/yt-smartimation/div/div/like-button-view-model/toggle-button-view-model/button-view-model/button/div')[
           1].text

       comment_names = driver.find_elements(By.XPATH, '//*[@id="author-text"]/span')
       comment_content = driver.find_elements(By.XPATH,
                                              '//*[@id="content-text"]/span')
       comment_library = []

       for each in range(len(comment_names)):
           name = comment_names[each].text
           content = comment_content[each].text
           indie_comment = {
               'name': name,
               'comment': content
           }
           comment_library.append(indie_comment)

       data = {
           'owner': owner,
           'subscribers': total_number_of_subscribers,
           'video_title': video_title,
           'description': description,
           'date': publish_date,
           'views': total_views,
           'likes': number_of_likes,
           'comments': comment_library
       }

       return data

   except Exception as err:
       print(f"Error: {err}")


# Enregistrer les données en JSON
def organize_write_data(data: dict):
   output = json.dumps(data, indent=2, ensure_ascii=False).encode("ascii", "ignore").decode("utf-8")
   try:
       with open("output.json", 'w', encoding='utf-8') as file:
           file.write(output)
   except Exception as err:
       print(f"Error encountered: {err}")


organize_write_data(extract_information())
driver.quit()

Résultats

Le résultat ressemble à ceci :

Screenshot_1.png

L'exploitation en toute sécurité de la mine d'informations de YouTube est très bénéfique lorsque l'on utilise des scripts bien conçus qui font appel à des mandataires pour garantir le respect des politiques et des réglementations de la plateforme. L'approche décrite ci-dessus facilite l'extraction responsable des données et atténue le risque de restrictions potentielles imposées par la plateforme.

Commentaires:

0 Commentaires