<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 # Cours 5
Introductions au techniques de crawl en Python
Principes du crawl
Le crawl est une technique qui consiste à naviguer sur ou plusieurs site pour en récupérer les information 
C'est la technique qu'emploient les moteurs de recherche pour créer une base de données qui contient les références
au site et les mots clés qui correspondent à la recherche.
La base du crawl est de stocker les liens présents dans une page, de les télécharger au fur et à mesure et de stocker les informations intéressantes.
Le crawl permet donc de reconstituer une base de données en collectant les informations html et en les formattant pour les insérer dans une base
Les différents types de crawl
Il existe autant de crawler que de besoins spécifiques parfois et même souvent 
une même extraction peut procéder de différentes manières et donc avoir différents algorithmes.
Pour la collecte de données, on développe des crawlers spécifiques
Step1:  Evidemment c'est un tout petit peu plus compliqué que ça...
Quelques exemples...
Fonctionnement du Spider de Google
Fonctionnement de Hyphe
Fonctionnement de Crawtext
Reprendre le fonctionnement des crawlers en ligne
Step2:  Définissons ensuite l'encodage pour prendre en compte les accents
Step3:  un module pour ecrire des csv
Step4:  On importe au debut du script 
tous les modules complémentaire 
dont on va avoir besoin et qui sont importer grace à l'instruction import
un module de téléchargement
Step5:  un module qui permet de parcourir le html
Step6:  Pour BeautifulSoup, on spécifie le type parser que nous allons utiliser
Step7:  On va ensuite écrire les fonctions dont on a besoin
Step8:  L'avantage d'écrire une fonction est qu'elle peut etre utilisée autant de fois
qu'on veut avec n'importe quelle variable c'est à dire pour cette fonction download
avec n'importe quelle url
Step9:  Toutes ces fonctions toutes sont universelles et s'applique à n'importe quelle page html
sauf la derniere extract_data() qui extrait les données a partir de tag qui n'existent que pour ce site et cette page précise.
Vous pouvez télécharger la version propre et complete depuis ce fichier 
Maintenant nous allons appeler les différentes fonctions pour faire marcher notre crawler
Step10:  La liste de toutes les urls de cette page de départ est stockées dans liens1
pour savoir combien d'url on a récupéré on peut appeler une fonction standard dans python
len(uneliste) qui a partir d'une liste en parametres donne le nombre d'élements présents dans la liste
Step11:  Crawl simple d'urls
Maintenant imaginons que nous soyons un simple crawler qui collecte toutes les url 
sans rien stocker de plus que des liens mais à profondeur infinie
On a besoin d'une liste d'url à traiter et d'une liste d'url déjà traitée pour s'assurer 
que le robot ne tourne pas à l'infini et qu'il ne crawl pas plusieurs fois une même url
pour la même raison il est utile aussi de vérifier qu'une url n'est pas en double dans les deux listes
<ASSISTANT_TASK:>
Python Code:
tocrawl = []
def crawl(url):
    html = download(url)
    page = parse(html)
    urls = extract_links(page)
    tocrawl.append(urls)
    return tocrawl
starter_url = "www.example.com"
tocrawl = crawl(starter_url)
while len(tocrawl) != 0:
    for url in tocrawl:
        crawl(url)
Explanation: # Cours 5
Introductions au techniques de crawl en Python
Principes du crawl
Le crawl est une technique qui consiste à naviguer sur ou plusieurs site pour en récupérer les information 
C'est la technique qu'emploient les moteurs de recherche pour créer une base de données qui contient les références
au site et les mots clés qui correspondent à la recherche.
La base du crawl est de stocker les liens présents dans une page, de les télécharger au fur et à mesure et de stocker les informations intéressantes.
Le crawl permet donc de reconstituer une base de données en collectant les informations html et en les formattant pour les insérer dans une base
Les différents types de crawl
Il existe autant de crawler que de besoins spécifiques parfois et même souvent 
une même extraction peut procéder de différentes manières et donc avoir différents algorithmes.
Pour la collecte de données, on développe des crawlers spécifiques:
* qui suit le parcours identifié sur le site
* a une profondeur fixée
* se concentre uniquement sur le site en question
* extrait les informations préalablement identifiées
* représente souvent les données sous forme tabulaire 
Par opposition le crawler web que développent les moteurs de recherche
et qu'on appelera ici Spider
* suit toujours le même parcours 
* ne se concentre sur aucun site en particuler
* n'extrait que les informations qui sont communes à tous les sites web
* représente souvent les données sous forme de réseau ou de graphes
Le Spider web
Algorithme et implémentation
L'algorithme d'un spider simplifié fonctionne de la manière suivante:
A partir d'une url de départ:
        * télécharger la page
        * parser le contenu
        * extraire toutes les urls
Pour chaque url de la liste de départ:
    * refaire le travail
    * et ainsi de suite jusqu'à ce qu'il n'y ait plus d'url à traiter
En pseudo code python cela donnerait
End of explanation
#!/usr/bin/python 
Explanation: Evidemment c'est un tout petit peu plus compliqué que ça...
Quelques exemples...
Fonctionnement du Spider de Google
Fonctionnement de Hyphe
Fonctionnement de Crawtext
Reprendre le fonctionnement des crawlers en ligne: détailer leur algorithme
Représentation des données
Les données du spider permettent de constituer des réseaux et des graphes en fonctions des informations collectées.
Les réseaux constitués les plus simple constistent en graphes de co-citations
une url source etant reliée a plusieurs urls par le fait quelle les mentionnent sur la page 
on peut cartographier les sites qui se citent les uns les autres.
Le crawler de site
Algorithme et implémentation
L'algorithme d'un crawler de site simplifié fonctionne de la manière suivante:
Une fois le parcours sur le site et les informations identifiées, le robot aggrège les données 
cibles qu'il stocke dans une base de données ou un fichier final à plat.
La parcours varie en fonction de l'information auquel on souhaite accéder et la manière dont on veut interroger les données.
Un exemple d'implémentation de crawl pour le site 
https://www.republique-numerique.fr/consultations/projet-de-loi-numerique/consultation/consultation
L'objectif étant de récupérer l'ensemble des arguments pour chaque article de loi
* Lister les urls de tous les participants
    Pour chaque participants:
    * extraire les arguments qui lui appartiennent
Représentation des données
Le crawl produit une base de données d'arguments reliés à un article de loi
Dans le cas d'un crawl sur un site particulier, il est capital de définir avant le crawl 
les données à extraire et les différentes étapes pour appliquer l'extraction à plusieurs pages
TP: construction d'un crawler de site web
Extracteur d'une page web
Reprenons les étapes d'extraction pour la page d'un site.
à travers plusieurs exercices
Exercice 0: Extraire les liens d'une page web
Vous pouvez télécharger le [script0] complet d'exemple
ou le copier coller dans votre éditeur
End of explanation
# coding: utf-8
Explanation: Définissons ensuite l'encodage pour prendre en compte les accents
End of explanation
import csv
Explanation: un module pour ecrire des csv
End of explanation
import requests
Explanation: On importe au debut du script 
tous les modules complémentaire 
dont on va avoir besoin et qui sont importer grace à l'instruction import
un module de téléchargement
End of explanation
from bs4 import BeautifulSoup
Explanation: un module qui permet de parcourir le html
End of explanation
BeautifulSoup("html.parser")
Explanation: Pour BeautifulSoup, on spécifie le type parser que nous allons utiliser
End of explanation
def download(url):
    '''fonction qui télécharge une page a partir d'une url et retourne le html sous forme de texte'''
    #on appelle le module requests qui permet de télécharger la page
    #et on stocke le résultat du téléchargement
    #dans une variable qu'on appelle ici reponse
    reponse = requests.get(url)
    #response est produite par le module requests
    #elle a donc des valeurs spécifiques qui sont documentés sur la page du module
    # requests 
    #tel que le code de status de la page cf[[Les codes d'erreur HTTP
    # le texte ou encore un json
    if response.status_code == 200:
        return response.text
Explanation: On va ensuite écrire les fonctions dont on a besoin:
* une fonction pour télécharger les urls ``download``
* une fonction pour écrire dans un fichier ``write_csv``
* une fonction pour extraire les liens ``extract_links``
Pour les utiliser ensuite (les appeler) dans notre fichier à la fin comme on va voir par la suite
End of explanation
#ici la fonction pour écrire une ligne dans un fichier CSV
def write_csv(filename, line):
    #on ouvre le fichier appelé filename comme un fichier csv
    # a pour ajouter à la suite (append)
    #r pour lire (read)
    #w pour ecrire (write)
    with open(filename, 'a') as csvfile: 
        #on met le fichier dans le writer de csv
        #en specifiant la délimitation ici ";"
        spamwriter = csv.writer(csvfile, delimiter=';')
        #line doit etre une liste d'éléments représentée en python par []
        # chaque element contenu dans line va s'inscrire dans une colonne
        spamwriter.writerow(data)
    return
#ici la fonction pour extraire des liens a partir d'une url
def extract_links(url):
    #on télécharge le contenu de la page
    #avec une fonction qu'on a déjà écrite plus haut
    html = download(page)
    #on va stocker tous les liens contenu dans la page dans une liste
    #avec le nom
    links = []
    soup = BeautifulSoup(html)
    
    #la fonction find_all renvoie une **liste**
    #de plusieurs elements BeautifulSoup
    # qui sont manipulable en utilisant les fonctions de Beautifulsoup
    #on a besoin ici de récupérer le lein contenu de la balise a href="{{lien}}"
    #qu'on va stocker dans notre liste comme dans un tableau
    
    #ici on veut récupérer toutes les balises de type a sans filtre particulier
    tag_link_list = soup.find_all("a")
    #name est donc une liste d'element parsés de tags
    #on va donc derouler les élements contenu
    for element in tag_link_list:
        #l'url de la page est stocké
        #dans le corps de la balise
        #exemple <a href="http://lemonde.fr">Site du Monde </a>
        #pour le récupérer on utilise la fonction de Beautifulsoup get
        lien = element.get("href")
        #on ajoute le lien à la liste
        liens.append(lien)
    return liens
#ici la fonction qui permet d'extraire les informations interessantes
#pour un site particulier
def extract_data(url):
    #on télécharge le contenu de la page
    #avec une fonction qu'on a déjà écrite plus haut
    html = download(page)
    #on transforme le html en le parcourant (parsing) avec BeautifulSoup
    soup = BeautifulSoup(html)
    #on va stocker tous les futures informations 
    #dans une liste qu'on appelle data
    data = []
    #pour extraire les données on utilise les fonctions de BeautifulSoup
    #find_all renvoie une liste d'elements
    #find renvoie le premier élement
    
    #imaginons que nous voulons extraire toutes les videos de cette page
    #http://www.bbc.com/news/science_and_environment
    #elles sont contenues dans la balise suivante
    #<div id="comp-candy-asset-munger" class="distinct-component-group container-condor wide-only">
    #on peut découper la partie qui nous interesse
    #en utilisant find qui renvoie la première balise
    # et l'id qui permet de trouver cette balise particuliere
    colonne_videos = soup.find("div", {"id": "comp-candy-asset-munger"})
    #on peut ensuite appliquer les méthodes de BeautifulSoup à l'interieur de cette partie
    #recuperer toutes les images en utilisant find_all
    img_tags = colonne_videos.find_all("img", {"class":"responsive-image__inner-for-label"})
    #il s'agit encore d'une liste de tag
    #on va récupérer la source de cette image stockée dans src
    for img in img_tags:
        image_sources = img.get("scr")
        
        data.append([image_sources, )
    return data
Explanation: L'avantage d'écrire une fonction est qu'elle peut etre utilisée autant de fois
qu'on veut avec n'importe quelle variable c'est à dire pour cette fonction download
avec n'importe quelle url
End of explanation
#### Exemple d'un crawl simple à profondeur 1
Ici le code de base pour extraire tous les liens d'une page de départ:
on part d'une url de départ qu'on télécharge et dont on extrait les liens qu'on stocke dans une liste
url_de_depart='http://www.bbc.com/news/science_and_environment'
liens_page0 = extract_links(url_de_depart)
liens1 = []
# on déroule les urls de la page
for page in liens_page0:
    # pour chaque lien 
    for lien in extract_links(page):
        #on ajoute dans la liste
        liens.append(lien)
Explanation: Toutes ces fonctions toutes sont universelles et s'applique à n'importe quelle page html
sauf la derniere extract_data() qui extrait les données a partir de tag qui n'existent que pour ce site et cette page précise.
Vous pouvez télécharger la version propre et complete depuis ce fichier 
Maintenant nous allons appeler les différentes fonctions pour faire marcher notre crawler
End of explanation
nb_liens1 = len(liens1)
print nb_liens
Explanation: La liste de toutes les urls de cette page de départ est stockées dans liens1
pour savoir combien d'url on a récupéré on peut appeler une fonction standard dans python
len(uneliste) qui a partir d'une liste en parametres donne le nombre d'élements présents dans la liste
End of explanation
url_de_depart='http://www.bbc.com'
#liste d'url a traiter
to_do = []
#liste d'url traitées
done = []
starter = extract_links(url_de_depart)
# on déroule les urls de la page
for page in starter:
    # pour chaque lien 
    for lien in extract_links(page):
        #on l'ajoute à faire
        to_do.append(lien)
    #on ajoute la page dont les liens ont déjà ete extrait
    done.append(page)
#while est une instruction spéciale en python de la manière que for c'est une boucle
#while permet d'executer des instructions tant que la condition est remplie
#ici tant que la liste de to_do n'est pas vide
while len(to_do) != 0:
    #on enlève les éventuels doublons avec la fonction de python set() qui enlève les éléments en double
    uniq_to_do = set(to_do)
    for lien in uniq_to_do:
        for new_link in extract_links(lien):
            if new_link not in done:
                to_do.append(new_link)
        done.append(lien)
        to_do.remove(lien)
        
#ici on aura donc au final une liste de url crawlées stockées dans la liste done
Explanation: Crawl simple d'urls
Maintenant imaginons que nous soyons un simple crawler qui collecte toutes les url 
sans rien stocker de plus que des liens mais à profondeur infinie
On a besoin d'une liste d'url à traiter et d'une liste d'url déjà traitée pour s'assurer 
que le robot ne tourne pas à l'infini et qu'il ne crawl pas plusieurs fois une même url
pour la même raison il est utile aussi de vérifier qu'une url n'est pas en double dans les deux listes
End of explanation
<END_TASK>