Récupérer et nettoyer des données sur le Web

Roch Delannay

11/15/23

Plan de la séance

  1. Questions légales et éthiques
  2. Les différentes manières de collecter des données sur le Web
  3. Exercice de Web scraping

1. Questions légales et éthiques

Quelles sont les législations sur la récupération de données en ligne ?

Quels protocoles mettre en place ?

1.1 Ninth Circuit Court of Appeals

Cas de HiQ vs LinkedIn :

1.2 Le RGPD en Europe

1.3 Légal ou éthique ?

Ce n’est pas parce que la loi approuve une pratique qu’elle est forcément éthique.

2. Les différentes manières de collecter des données sur le web

  • Le Web scraping
  • Le Web crawling

2.1 Le Web scraping

  • Logiciels dédiés
  • Scripts personnel (en Python par exemple)
  • API (Application programming interface)

2.2 Le web crawling

Le crawl est un logiciel d’indexation qui explore automatiquement le web. Il peut collecter différents types de ressources : 

  • pages web
  • images
  • vidéos
  • documents
  • etc

3. Exercice de Web scraping

Pour cet exercice nous allons nous familiariser avec les concepts basiques de Python avec le site web generationcovid.fr. L’objectif de l’exercice est de récupérer les contributions présentes sur ce site web et de les encapsuler dans un fichier CSV. Chaque contribution doit avoir sa propre ligne et contenir deux informations :

  • la date de publication
  • le texte de la contribution

3.1 Repérer les données que l’on souhaite récupérer

  • visiter le site : https://generationcovid.fr/vos-temoignages/
  • ouvrir les outils de développements et regarder la structure du document

3.2 Récupérer le contenu HTML

  • On peut faire un essai préliminaire avec une commande bash pour récupérer le contenu dans son terminal (pour faire un rappel des commandes que nous avons vu la dernière fois).
  • commencer notre script Python : de quoi avons-nous besoin ? 
    • BeautifulSoup pour parser le contenu HTML
    • requests pour faire des requêtes http
    • os pour utiliser des fonctionnalité du système d’exploitation (lire un fichier ou suivre un path)
# On importe les librairies dont on a besoin pour travailler
# Ainsi on peut utiliser les fonctions disponibles dans ces librairies
# sans avoir à les redévelopper

import os
import requests
from bs4 import BeautifulSoup

# Pour ne pas à avoir à réécrire tout le temps notre url on peut créer une variable dans laquelle l'affecter
url = "https://generationcovid.fr/vos-temoignages/"

# Plutôt que d'avoir une requête très longue, on peut aussi fragmenter
# la récuperation du contenu en plusieurs étapes
# D'abord la requete :
reponse_de_la_requete = requests.get(url)

# Pour vérifier l'information que nous retourne cette fonction, utiliser la fonction print().
print(reponse_de_la_requete)

# La réponse nous informe normalement un succès de la requête.

# Pour voir la réponse HTML nous allons utiliser BeautifulSoup

soup = BeautifulSoup(reponse_de_la_requete.content, "html.parser")

# Comme tout à l'heure, nous allons utiliser la fonction print() pour afficher le résultat dans la console Python.

print(soup)

Bravo ! Si vous êtes arrivés jusqu’ici c’est que vous avez réussi à récupérer la page HTML d’un site web et que vous avez créé un objet soup à partir duquel vous pourrez filtrer les contenus !

3.3 Parser le contenu

Nous avons récupéré tout le contenu de la page HTML. Maintenant nous devons trier les informations et ne garder que celles qui nous intéressent, conformément à ce que nous avons ciblé lors de l’exercice 3.1.

# On crée une variable à laquelle on affecte toutes les contributions
# la fonction find_all de BeautifulSoup permet de récupérer toutes les occurences mentionnées
# en paramètres.

contributions_elements = soup.find_all("div", class_="testimonial-inner")

# Nous avons pris l'habitude de vérifier les informations que nous retournent les fonctions avec print().

print(contributions_elements)

# Là on voit bien que nous avons récupéré tous les éléments mais ils sont tous les uns à la suite des autres.
# Ce n'est pas très pratique si l'on souhaite travailler contribution par contribution
# Nous allons utiliser une boucle for pour mettre un peu d'ordre dans tout ce texte

for contribution_element in contributions_elements:
    content_element = contribution_element.find("div", class_="testimonial-content").text.strip()
    date_element = contribution_element.find("div", class_="testimonial-date").text.strip()
    print(date_element)
    print(content_element)
    # On ajoute le résultat à une variable, attention il faut déclarer la variable au préalable !
    # Pour cela, on ajoute site_content = [] en haut du fichier
    # pour indiquer que site_content contient une liste vide à laquelle append() va ajouter des éléments
    site_content.append([date_element, content_element])

# On refait un print pour voir le résultat obtenu dans notre variable (même si les print() intermédiaires nous
# donne déjà une bonne idée du résultat)

print(site_content)

# On obtient une liste qui contient des listes composées de deux chaines de caractères : une date et un texte

Félicitations ! Si vous êtes arrivés jusqu’ici c’est que vous avez réussi à récupérer le contenu indiqué dans la consigne !

3.4 Récupérer toutes les contributions

Comme vous avez du le remarquer, toutes les contributions ne sont pas présentes. Vous n’avez récupéré que les contributions de l’URL que vous avez affecté à votre variable.

Mais alors, comment faire pour tout récupérer ?

# Une des manières possible est d'utiliser une boucle while
# pour passer sur toutes les pages du site web.

# Pour appliquer cette boucle while il nous faut regarder quel élément pourrait nous permettre de créer une condition.
# Pour rappel la boucle while fonctionne sur le principe de la réalisation d'une condition : 
# tant que cette condition est valide, exécuter les instructions suivantes.

# Cette boucle doit nous permettre de modificer l'url passée à la requête get(url)
# pour récupérer le contenu sur toutes les pages du site web.
# L'URL des pages est formée comme suit : https://generationcovid.fr/vos-temoignages/page/2/
# Le paramètre qu iva changer à chaque page est le numéro de la page.
# Le nombre maximal de page est 72
# On peut donc faire une boucle avec un compteur qui va jusqu'à 73
# Tant que le compteur est différent de 73, exécuter les instructions.

# En haut du fichier, on crée d'abord une variable pour amorcer notre compteur

numero_page = 1

# Puis on englobe tout ce qu'on a fait jusqu'à présent dans une boucle while

while numero_page != 73:
    #tout le code
    reponse_requete = requests.get(url)
    #soup....
    #for ...

    # Maintenant on incrémente le compteur pour modifier l'url données à la get()
    # On rappelle la variable url et on lui affecte une nouvelle valeur
    # Le dernier élément entre accolades prendra la valeur affectée à la variable numero_page
    url = f"https://generationcovid.fr/vos-temoignages/page/{numero_page}/"
    # On affiche la valeur d'url dans la console
    print(url)
    # On incrémente le compteur pour qu'au prochain passage de la boucle on puisse à nouveau changer de page
    numero_page = numero_page + 1

Excellent ! Si vous êtes arrivés jusqu’ici, vous avez compris le fonctionnement d’un compteur et d’une boucle while. À ce stade, si vous utilisez la fonction print() sur votre variable site_content vous devriez voir toutes les contributions dans votre liste !

3.5 Exporter les données en CSV

Avoir les données dans un script en Python est déjà une très bonne avancée ! La prochaine étape consiste à exporter les données dans une fichier CSV que vous pourrez alors manipuler avec d’autres programmes.

# Il y a plusieurs options pour écrire dans des fichiers CSV.
# Celle que nous allons utiliser consiste à importer la librairie CSV
# En en-tête de fichier, avec les autres librairies, on ajoute : import csv

import csv

# Pour créer notre csv nous avons déjà tout le contenu à disposition, 
# mais nous avons également besoin de des en-têtes de colonne pour décrire les données qui s'y trouvent.
# Pour cela, nous allons créer une variable en-dessous des imports de librairies, avec celle de l'url et le compteur.
# On va créer une liste contenant deux chaines de caractères qui correspondent au titre de nos colonnes.

entetesCsv = ["date", "content"]

# Sous la boucle while, nous allons pouvoir exporter les résultats dans un fichier CSV
# On ouvre un csv avec la fonction open() qui prend deux paramètres : le nom du document
# et le mode dans lequel nous sommes, "w" pour write.
# Ensuite on lui passe en écriture les en-têtes puis les contributions

with open("generation-covid.csv", "w") as f :
    write = csv.writer(f)
    write.writerow(entetesCsv)
    write.writerows(site_content)

Félicitations ! C’était l’étape finale de notre exercice ! Maintenant vous avez votre fichier csv contenant toutes les contributions du site web !