Transcript for:

bienvenue dans cette formation complète sur le scrapping avec Python scrapping ça veut dire racler en français et c'est exactement ce qu'on va faire puisqu'on va venir récupérer des informations sur toutes sortes de sites web c'est une pratique ultra populaire dans le monde des développeurs parce que les données c'est le pétrole du 21e siècle et les personnes qui maîtrisent cette compétence sont très recherché avec le scrapping on va pouvoir récupérer par exemple les prix de billets d'avion ou d'objets qu'on souhaite acheter pour être averti lorsque le prix sera le plus bas possible le scrapping il est aussi utilisé par les plus grand nom de la tech comme le désormais bien connu open ai qui a utilisé de façon massive le scrapping plus ou moins légalement d'ailleurs on le verra dans cette vidéo pour entraîner ces modèles dia dans cette vidéo je vais vous montrer tout ce que vous avez besoin de savoir pour pouvoir faire du scrapping avec Python à l'aide de librairie bien connu comme request et beautiful soup mais également avec des outils plus récents et avancés comme selectolx ou encore playright on va également parler de tous les blocages qu'on peut rencontrer et de comment les contourner et quand on parle de contourner des restrictions vous vous l'aurez compris on doit aussi parler d'un point très important qui est rarement abordé dans les vidéos techniques sur le scrapping c'est le cadre légal dans lequel il s'inscrit je vois en effet beaucoup de développeurs qui n'osent pas se lancer dans le scrapping parce qu'ils pensent que c'est tout simplement illégal alors que c'est faux dans cette formation on va donc voir ensemble ce que vous avez le droit de faire ou non et comment contourner les obstacles qui vont se dresser face à vous cette formation elle est également sponsorisée par bright data qui est la solution la plus avancée sur le marché pour vous permettre de faire du scrapping sans être bloqué tout en effectuant un scrapping éthique j'ai ainsi obtenu un entretien exclusif avec le vice-président de la conformité et de l'éthique chez bright data qui vous expliquera toutes les mesures qu'ils ont mis en place pour assurer la viabilité de leur réseau à la fin de cette formation vous serez donc en mesure de réaliser des script de scrapping sur des sites réels et j'insiste j'ai préparé des heures d'exercices et de projets pour vous permettre de mettre en pratique ce que vous allez apprendre on va notamment récupérer des informations sur le site Airbnb pour vérifier le mois le moins cher dans l'année pour partir en vacances dans une ville spécifique c'est un cas réel d'un script que j'utilise moi-même régulièrement quand je planifie mes prochaines vacances on verra aussi comment être averti lorsune baisse de prix d'un article sur Amazon un cas d'utilisation très concret qu'on me demande très régulièrement vous l'aurez compris je n'ai pas fait les choses à moitié dans cette formation c'est la plus complète que vous trouverez en français sur le sujet et j'ai mis un point d'honneur à vous montrer des scripts avancés et fonctionnels toutes les formations existantes sur le sujet vous montrent des mises en pratique sur des sites d'exemples avec des scripts de quelques lignes qui ne fonctionnent que dans un environnement très précis dans cette formation on va voir des scripts réels qui sont réalisés sur des sites qui existent qui ne sont pas des sites d'exemple avec une fine gestion des erreurs et qui ne vont pas donc planter au moindre changement sur le site que vous allez scrapper on va mettre en place une gestion efficace des erreurs et du logging et voir la mise en production de NO script sur un serveur privé virtuel pour s'assurer qu'il fonctionne en continu j'espère donc que vous êtes prêts pour cette aventure je remercie de nouveau nouveau bright data de sponsoriser cette vidéo et pour vous mettre le pied à l'étrier vous trouverez dans la description un lien d'affiliation qui vous permet d'obtenir gratuitement des crédits pour pouvoir commencer à tester leur solution sans aucun engagement financier de votre part avant de rentrer dans le vif du sujet je vais passer quelques minutes à vous parler du programme de la formation cette partie est très importante avant de partir dans 10h de formation c'est bien important de savoir dans quoi on s'embarque notamment les trois premières parties qu'on va voir tout de suite après il y en a pour une petite dizaine de minutes en tout je vous conseille fortement de ne pas passer ces parties parce que c'est vraiment ça qui va vous permettre de comprendre ce qu'est le scrapping avec donc la première partie dans laquelle on va voir tout ce que recouvre le scrapping on va voir également dans une deuxième partie les prérequis pour suivre la formation là encore bien important de ne pas passer cette partie pour savoir ce que vous devez savoir faire avant de suivre cette formation ça va vous éviter des heures de problèmes par la suite si jamais vous vous embarquez sans avoir les outils nécessaires et troisième partie importante dans ces premières 10 minutes les obstacles à franchir là encore cette partie bien importante pour comprendre la suite de la formation et ce qu'on va mettre en place dans les différents scripts qu'on va réaliser même dans les scripts de débutants donc ces trois parties qu'est-ce que le scrapping les prérequis les obstacles il y en a pour une petite dizaine de minutes ne les passez pas et ensuite pour la formation qu'est-ce qu'on va avoir on va avoir quatre parties une première partie assez basique qui va tout simplement passer à travers les bases du scrapping une deuxième partie justement dans laquelle on va voir tous les obstacles et comment les contourner que ce soit les blocages volontaires ou encore les blocages techniques qui sont apparus ces dernières années avec les nouvelles technologies du web et ensuite on va avoir deux projets un premier projet sur Airbnb dans lequel on va voir vraiment un cas concret dans lequel on va récupérer les informations de prix sur Airbnb et la dernière partie bien importante que j'ai rarement vu dans des formations la mise en production et l'automatisation d'un script d'alerte Amazon donc encore un projet qui va être assez simple mais dans cette partie le but c'est surtout de vous montrer comment on peut faire un script qui va rouler 24h/ 24 7 jours sur 7 avec également une bonne gestion des erreurs pour avoir vraiment un script fonctionnel dans un cas là encore réel d'utilisation avec le site Amazon donc dans la première partie dans les bases on va passer à travers toutes les bases théoriques on va voir comment utiliser les deux bibliothèques les plus importantes en scrapping request et beautiful soup pour récupérer et analyser le contenu d'une page web on va ensuite passer sur des exercices simples pour que vous puissiez vous entraîner et un exercice un peu plus avancé dans lequel on va voir des bibliothèqu plus récente comme selectolax et l Guru et dans cet exercice avancé on va vraiment avoir un scrapping à plus grande échelle avec la récupération d'un très grand nombre d'informations sur un site web dans la deuxième partie on va s'intéresser aux obstacles on va également s'intéresser à tout ce qui concerne la légalité du scrapping bien important là encore on va passer en revue la jurisprudence de différentes affaires sur le sujet le rgpd le scrapping éthique et on va voir une entrevue également très intéressante avec Rony Shalit de Bright data dans lequel il va vous parler justement de tout ce qui concerne le scrapping et l'éthique du du scrapping bien important là encore pour être rassuré sur le fait que le scrapping n'est pas illégal tant qu'il est fait dans les bonnes conditions on va voir également les obstacles à franchir donc on va expliquer tout ça en détail d'où viennent ces obstacles pourquoi on a des blocages que ce soit technique ou volontaire avec cette partie vous allez vraiment comprendre pourquoi il y a ces blocages et on va voir ensuite bien entendu comment les contourner on va ainsi utiliser les outils de Bright data pour utiliser des réseau de proxy pour utiliser des bibliothèques un peu plus avancées également comme playwright pour pouvoir vraiment contourner tous les blocages qui seadresse face à vous et être assuré de pouvoir récupérer les données qui nous intéressent on va ensuite passer au projet Airbnb donc là on est vraiment dans le cas d'un script réel sur un site en condition donc dans cette partie l'heure n'est plus au démo avec des sites web bien formatés on va vraiment mettre les mains dans le campoui et récupérer des données sur un vrai site web et on va voir là encore comment s'assurer de ne pas être bloqué avec le scrapping browser de Bright data et playrightti et pour finir la 4è partie et non les moindres la partie dans laquelle on va créer le script pour récupérer des informations de prix sur Amazon on va récupérer le prix d'une carte graphique pour recevoir une alerte sur notre téléphone dans le cas où le prix chute d'un certain pourcentage on va pour cela utiliser l'application pushover qui nous permet de recevoir des alertes sur notre téléphone et on va mettre en place une gestion fine des erreurs avec la mise en production sur un VPS qui va nous permettre d'avoir un script qui peut fonctionner sans interruption pour ça on va donc utiliser un Chrone job et on va vooir la gestion des erreurs avec sentry qui va nous assurer en cas de problème qu'on peut facilement vérifier quels sont les problèmes et les régler au plus vite donc voilà pour le programme de cette formation je vous le répète n'oubliez pas de passer à travers les trois premières parties qui sont bien importantes comme vous le voyez c'est vraiment un programme très complet on va vraiment partir de zéro je vais vous présenter tous les outils que vous avez besoin de connaître toutes les bases théoriques technique et comment aller jusqu'au scrapping de données sur des vrais cas d'usage avec des scripts qui vont pouvoir rouler en production vous serez donc en mesure à la fin de cette formation de faire des scripts 100 % fonctionnels professionnels et sur des vrais cas d'usage dans cette formation vous m'entendrez parler du terme de scrapping qu'on traduit en français par moissonnage de données donc bien qu'il existe un terme en français il n'est que très rarement utilisé c'est pourquoi tout au long de cette formation j'utiliserai le terme de scrapping le scrapping de données c'est un processus qui est utilisé pour extraire des données à partir de site web cette technique elle implique l'envoi d'une requête à un site web le téléchargement et l'extraction de données à partir de la page on utilise le scrapping de données dans des centaines de domaines comme la finance la sociologie ou encore la recherche médicale ce qu'il est bien important de comprendre c'est que le scrapping de données il est rarement fait à la main même si c'est possible à la place vous l'aurez compris on utilise des scripts qui consistent à extraire automatiquement des informations à partir de sources numériques en suivant des formules préétablies donc desript historiquement ces sources comprenaient des documents et des bases de données mais avec l'avénement d'Internet le scrapping de données a principalement évolué pour cibler directement les sites Web qui contiennent ces informations avant de rentrer dans le vif du sujet je vais vous parler des quelques prérequis que vous devez avoir avant de commencer cette formation le premier prérequis le plus important c'est de faire pause tout de suite et d'aller mettre un pouce bleu en dessous de cette vidéo pour soutenir le travail gratuit qui vous est proposé également vous pouvez partager cette vidéo sur discord sur Linkedin sur Twitter peu importe faites du bruit autour de cette vidéo là encore c'est ça qui nous permet d'avoir des sponsors et de proposer ce contenu gratuit à la chaîne si vous ne faites pas ça de plus en plus le contenu sera payant donc c'est vraiment en faisant ces petites actions individuellement que l'on pourra continuer de proposer du contenu 100 % gratuit sur la chaîne et de cette qualité deuxièmement dites-moi pourquoi vous voulez faire du scrapping allez le mettre en commentaire je vais tout lire ça va me permettre de faire d'autres vidéos sur le sujet qui seront disponibles sur la chaîne et qui répondront à ces problématiques précises celles qui reviennent le plus souvent donc si vous voulez que j'aborde ces thématiques n'oubliez pas l'espace des commentaires dites-moi pourquoi vous voulez faire du scrapping c'est bien important également et maintenant je vais vous parler des prérequis techniques le premier c'est bien sûr de maîtriser un minimum python pas besoin d'être un expert on ne va pas aller dans tout ce qui est orienté objet on va rester sur des scripts assez simples qui vont quand même nécessiter la maîtrise des fonctions et des algorithmes par algorithme j'entends savoir faire des structures conditionnelles des boucles déclarer des variables des choses quand même assez basiques on ne va pas aller dans des choses beaucoup plus avancées la seule chose peut être un peu plus avancé mais qu'on va voir en détail dans cette vidéo justement c'est la gestion des erreurs donc par exemple les blocs try accept c'est bien si vous avez des notions de base à ce sujet mais ce n'est absolument pas essentiel puisqu'on va tout voir ça ensemble dans cette vidéo également je m'attends à ce que vous sachiez utiliser votre environnement de travail c'est-à-dire ouvrir un terminal installer des librairies avec PIP et également créer des environnements virtuels et exécuter votre script Python on va voir bien sûr tout ça en détail quand même dans la formation mais je n'utiliserai pas à chaque fois les trois os dans cette formation j'utilise MacOS qui est assez proche de Linux et pour Windows vous pouvez aller voir toutes les vidéos sur la chaîne qui parlent de comment configurer votre environnement de travail pour Windows il y a vraiment beaucoup de vidéos sur ce sujet sur la chaîne donc ça ne manque pas et pour ne pas avoir un tuto qui dure 20h ici je me suis concentré sur un seul os de toute de toute façon vous allez voir que les manipulations sont très simples c'est juste histoire d'installer des environnements virtuels des librairies et de lancer vos scripts avec cet [Musique] environnement dans cette formation on va réaliser plusieurs scripts de scrapping vous allez voir que la base théorique est assez simple et rapide à comprendre en quelques heures on peut apprendre tout ce qu'il faut pour récupérer des données à partir d'une page HTML la partie complexe du scrapping elle se situe à trois niveaux premièrement les blocages techniques ce sont des blocages qui sont dusû à l'évolution des tech teologie du web et notamment l'utilisation de plus en plus courante de JavaScript qui va nécessiter l'utilisation d'outils plus avancés qu'on va voir dans cette formation comme playwright pour récupérer le contenu généré dynamiquement par les sites web modernes deuxièmement on a les blocages volontaires c'est-à-dire les processus mis en place par les sites web pour éviter la collecte de données par des scripts et pour finir la partie automatisation et gestion des erreurs parce que le but d'un script et ça ne s'applique pas qu'au scrapping c'est de pouvoir fonctionner en toute autonomie sans aucune intervention humaine dans le cas du scrap scrapping la difficulté c'est qu'on n pas tout seul on va récupérer des données sur des sites Web qui sont constamment en évolution les scripts de scrapping ils vont donc avoir tendance à planter plus fréquemment qu'un script utilisé dans d'autres domaines et c'est bien important de le prendre en compte pour être averti en cas de changement ou de problèmes et s'assurer que nos scripts fonctionnent comme ils sont censés le faire dans cette formation on va voir comment adresser ces trois problématiques et pour le cas des blocages volontaires on va utiliser les outils du sponsor de cette vidéo bright data il faut savoir que vous pouvez faire du trapping jusqu'à un certain niveau sans débourser un centime mais si vous souhaitez faire des scripts robustes sur des sites très fréquentés et bien protégés comme Amazon ou Airbnb il faudra utiliser des solutions professionnelles comme bright data bright datata il propose plusieurs solutions qui vous permettent d'éviter ces blocages notamment un réseau de proxy résidentiel pour éviter les blocages par adresse IP un outil appelé web Unlocker pour résoudre les problèmes plus complexe comme les capcha et le scrapping browser un nouvel outil qui permet d'émuler le plus fidèlement possible un humain avec un vrai navigateur et les mêmes outils que le web Unlocker pour contourner les blocages bright data c'est aussi une entreprise qui a à cœur le côté éthique du scrapping et c'est un point très important autant pour moi que pour vous parce que le but c'est de rester dans les clous et la légalité c'est aussi une solution que j'utilise moi-même pour mes propres scripts de scrapping c'était donc tout naturel pour moi de vous présenter cette solution que j'utilise pour extraire les données de sitite web avec Python on dispose de différentes bibliothèques qui vont nous simplifier la vie ces bibliothèques elles vont nous permettre de récupérer et d'analyser le contenu HTML des sites web qu'on veut analyser on va travailler notamment avec deux bibliothèques request et beautiful soup qui sont des bibliothèques bien connues des développeurs python puisqu'elles existent depuis le début des années 2000 comme on peut le voir à leur magnifique logo alors c'est sûr que ça peut faire un petit peu peur comme ça si je vous montre la documentation de beautiful soup vous allez probablement vous dire que vous vous êtes trompé de de décennies personnellement j'ai l'habitude de faire confiance à ces sites un petit peu moches puisque je me dis que les développeurs qui font ces librairies mettent vraiment leur temps au bon endroit c'est-à-dire sur le développement et la maintenance de ces bibliothèques plutôt que sur l'aspect visuel des sites web de ces librairies donc ces bibliothèques elles ont été testées et approuvées depuis maintenant près de deux décennies donc je peux vous dire que c'est du solide alors qu'est-ce qu'elles vont nous permettre de faire ces bibliothèques elles vont nous permettre à la fois de récupérer le html de site web et de l'analyser on peut également citer la bibliothèque httpx qui peut être utilisée à la place de request elle est très très similaire à request dans le code vous verrez que c'est très facile de passer de l'une à l'autre httpx apporte notamment la gestion des requêtes asynchrones et utilise des nouveautés du protocole HTTP mais dans la plupart des cas vous pouvez vous contenter de request et nous c'est request qu'on va utiliser dans cette formation donc si on revient à nos deux bibliothèques request et beautiful soup on va voir que elles n'ont pas la même utilité request sert notamment donc à effectuer des requêtes HTTP vers des sites Web pour ensuite récupérer le code HTML de ces sites web et ce code html on va pouvoir ensuite l'analyser avec beautiful soup donc beautiful soup permet d'analyser et de naviguer dans le DOM ça va nous permettre donc de plus facilement récupérer les infos qui sont contenus à l'intérieur de la structure HTML qui aura été récupérée avec request mais il faut bien comprendre que on peut très bien utiliser beautiful soup sans forcément utiliser request si vous avez des fichiers html sur votre disque dur vous pouvez directement les analyser donc beautiful soup c'est ce qu'on appelle un parseur en bon français donc qui veut dire un analyseur si vous voulez donc ça va juste en fait analyser et comprendre le html pour pouvoir naviguer à l'intérieur de cette structure facilement avec du code Python et request lui ça va juste nous permettre de récupérer les informations du site web donc généralement on utilise l'un avec l'autre puisque c'est rare qu'on fasse juste de l'analyse de fichiers statique sur notre disque dur ce qu'on veut c'est généralement aller récupérer les dernières informations à jour d'un site web pour pouvoir ensuite les analyser et vérifier s'il y a eu des modifications ou des choses qui nous intéressent qu'on peut ensuite stocker ou envoyer pour faire des alertes par exemple à des clients donc si on rentre un petit peu plus dans le détail on va voir que request nous permet donc de faire des requêtes comme son nom l'indique donc imaginons qu'on souhaite récupérer le code HTML de Google on va donc faire une requête vers le site de Google gole et on va récupérer du texte tout simplement qui est du code html avec les balises donc par exemple la balise du titre une balise de titre et ici un paragraphe donc quelque chose de très simple et on va ensuite pouvoir ramener notre ami beautiful soup qui lui va nous permettre de comprendre cette structure puisque ce serait un petit peu pénible sans cet outil d'aller chercher à l'intérieur des balises donc de devoir faire une recherche du texte H1 on peut le faire directement avec du python avec des search et cetera mais ça ne serait pas très pratique donc là ce qu'on va faire avec beautiful soup c'est utiliser les outils de la bibliothèque pour par exemple aller chercher la balise TITLE et récupérer le titre de cette balise qui dans ce cas-ci est littéralement le titre de la page mais on peut aller beaucoup plus loin comme je le disais puisqu'on va pouvoir traverser ce Dom ce document object model et récupérer des objets donc là par exemple si on souhaite récupérer les enfants du body on peut faire une boucle et afficher tous les enfants donc tous les child qui sont dans la L e de Children donc children c'est les enfants du body dans ce cas-ci on a deux enfants on a le titre H1 et le paragraphe et comme je vous ai dit là on travaille avec des objets Document Object Model donc là ici ce n'est pas juste du texte ça va être un objet qui va contenir des attributs si vous connaissez Python et l'orienté objet vous savez que les objets contiennent des attributs et qu'on peut afficher ces attributs dans ce cas-ci l'objet qui nous est retourné par beautiful soup va contenir un attribut texte et ça va nous permettre donc de récupérer le texte à l'intérieur de ces balises et d'enlever le H1 avec les symboles de plus grands et plus petit donc les balises HTML pour récupérer uniquement le texte qui est contenu à l'intérieur donc voilà pour les fondamentaux vous allez voir que beautiful soup est beaucoup plus puissant que ça on peut cibler très précisément des parties de la page en fonction des ID des classes ou de plein d'autres choses comme ceci ce qui va nous permettre d'aller récupérer très précisément l'information que l'on souhaite pour pouvoir ensuite l'utiliser comme on le souhaite pour pouvoir utiliser request dans notre script il va falloir l'installer car il n'est pas inclus avec la bibliothèque standard de python dans un terminal avec notre environnement virtuel on va donc installer request avec PIP donc PIP install request je valide avec entrée c'est assez rapide et on va pouvoir ensuite l'importer dans notre script donc on va faire import request et on va créer notre première requête avec request.get alors faites bien attention de ne pas oublier le S c'est une erreur que je vois très très souvent les gens pensent que en fait c'est le module request sans s donc moi je fais bien attention de dire requests avec un s à la fin pour qu'on s'en souvienn donc on va pouvoir faire une requête GET on peut faire également des requêtes post et on peut faire plein d'autres choses avec request nous dans notre cas on va se contenter de simple recket get pour aller récupérer les informations d'une page donc on va prendre l'exemple de Google et on va mettre tout ça dans un objet qu'on va appeler response et je vais mettre ici donc tout simplement l'adresse de Google donc h gtps 2.//ww.google.com et je vais faire un print de cette réponse pour vous montrer ce que ça retourne donc je lance le script et là on a bien une réponse avec un code de 200 donc on peut afficher ce code avec point status code et on va récupérer directement un nombre entier qui correspond au code de la requête HTTP donc le code retour qui dans ce cas-ci nous indique que la requête a été correctement effectuée si on souhaite récupérer le contenu de la page on peut utiliser utiliser point texte et on va récupérer tout le code HTML de la page donc vous voyez qu'il y a pas mal de choses donc là on sen rend peut-être pas bien compte mais c'est parce qu'en fait tout le code est sur la largeur comme ceci puisqu'il n'est pas formaté correctement dans le terminal donc là on a tout qui est dans un gros bloc et on voit bien du code html avec un Doct type HTML ici la balise HTML et plein d'autres choses et même du javascript à l'intérieur de cette page une chose qu'il est bien important de garder en tête c'est que quand on fait des requêtes vers un site web il y a plein de cas de figur dans lesquels on peut avoir des erreurs donc quand on fait des scripts un peu plus avancés il va être important de gérer ces erreurs ces erreurs on peut les vérifier donc soit avec le status code comme on a vu donc en faisant un print du status code on peut vérifier si on a un code de retour qui est par exemple 200 201 202 et cetera donc les codes de succès on peut vérifier si on a un code plutôt d'erreur comme les 404 les 500 et cetera on a également une fonction qui s'appelle raise for status qui va nous permettre de lever une erreur dans le cas où on a un problème avec la requête donc là si je relance mon script dans ce cas-ci on Nura pas d'erreur de lever donc je ne suis pas obligé de faire un print là j'ai fait un print de ce raise donc ça me retourne non mais on peut juste faire donc raise for status dans ce cas-ci il n'y a pas eu d'erreur de Lev puisque l'URL fonctionne mais si je fais une modification par exemple si je mets une autre URL par exemple on va mettre cette url n'existe pas en espérant qu'elle n'existe vraiment pas je vais relancer donc mon script et là cette fois-ci on va bien avoir une erreur qui est levée dans ce cas-ci une connection error donc on peut gérer beaucoup d'erreurs comme ça je vais vous mettre un petit exemple d'un script ici avec différents codes d'erreur pour vous montrer toutes les différentes erreurs qu'on peut avoir il y en a plus que ça mais ça c'est les erreurs classiques qu'on va retrouver donc on va avoir des erreurs directement sur le protocole HTTP avec hTTP Error on peut avoir également des erreurs de timeout donc ça c'est par exemple s'il y a un site web qui met trop de temps à répondre donc ça veut dire que la requête va fonctionner on ne va pas avoir une erreur comme ici avec cette URL qui n'existe pas mais mais on va avoir un timeout c'est-à-dire que la requête prendra trop de temps à être effectuée et au bout d'un moment request va arrêter d'essayer et dans ce casci on va se retrouver avec cette erreur de timeout donc dans les différents cas de figure à vous de voir quelles erreurs vous avez besoin de gérer et vous pouvez donc lever ces erreurs avec raise for status ou comme on l'a vu vérifier avec le status code et ensuite vous pouvez faire une structure conditionnelle ou passer par des blocs try accept comme ici avec les exceptions et le raise for status donc si je reviens sur notre exemple avec Google on va pouvoir donc récupérer ce code html et le sauvegarder très facilement sur notre disque dur avec la gestion de Python des fichiers donc par exemple ici on va faire un wi open on va le mettre dans le même dossier donc on va faire un chemin relatif ici index.html pour créer le fichier dans le même dossier que notre fichier python on va ouvrir ce fichier en mode écriture et on va l'ouvrir en tant que F et faire un f.wite de response.text puisqu'on avait vu tout à l'heure response.text va nous retourner tout le le code HTML de la page donc si je relance le script on va voir qu'on a bien un fichier index. HTML qui a été créé ici et on voit qu'on a bien le code qu'on avait tout à l'heure dans le terminal donc comme je vous disais c'est un petit peu brouillon ici pour y voir un petit peu plus clair on peut faire un reformatage donc si on va dans code ici on peut faire reformat file et ça va un petit peu tout remettre en ordre avec les bons retours à la ligne les bonnes tabulations et là on voit qu'on a quelque chose qui ressemble donc un peu plus à une page html on a le Head ici le body on va avoir un script ici on va avoir ensuite des divs qui vont correspondre probablement voilà donc là moi je suis au Portugal donc on a la pesquisa ici qui est donc la recherche qu'on souhaite faire donc avec un input probablement quelque part ici pour faire notre recherche voilà un input il y en a probablement d'autres sur la page qui corresponde là on a un input hidden donc on a probablement pas mal de choses ici qui servent à faire fonctionner Google et un input qui est l'input principal qui nous permettent d'effectuer notre requête donc vous voyez c'est très très simple en quelques lignes de code la plupart du temps on va faire une requettete get vers un site pour ensuite récupérer le response.text vous pouvez également utiliser le point JSON si vous faites des requêtes vers des points d'API qui vont retourner des données au format Jason et avec le response.json vous aurez directement les données qui vont vous être retourné sous le format d'un dictionnaire en python donc c'est plus facile si vous souhaitez comme ça naviguer à l'intérieur cette structure de données en JSON dans notre cas on va récupérer le texte qui est donc du code HTML et on va ensuite utiliser la bibliothèque beautiful soup pour lire ce HTML et passer à travers les différentes balises et récupérer les informations que l'on souhaite extraire de la page web dans les prochaines parties pour illustrer les parties théoriques de cette vidéo on va utiliser un site web éducatif bien connu des étudiants en scrapping books.touscrape.com ce site web il est parfait pour s'entraîner mais ça fait longtemps que je fais des formations et je sais bien qu'il est très risqué pour un formateur de s'appuyer sur des outils ou des sites web sur les lesquels il n'a pas la main pour prendre les devants au cas où ce site Web ne soit plus disponible dans le futur j'ai créé une copie conforme de ce site Web que vous pouvez retrouver sur docstring l'URL c'est docstring.fr/api/bookstoscrape/index.html donc à part le début de l'URL qui est forcément différent tout le reste est exactement pareil donc on a bien la page index.html qui est la page d'accueil si vous allez sur la page d'un livre vous allez voir qu'on a bien l'url/catalog/l nom du livre/index.html là encore de la même façon que sur bookst to scrape/catalog /le nom du livre/index.html donc bien sûr en premier lieu utiliseer ce site web books.tuscript.com mais si jamais au moment où vous regardez cette formation il n'est plus disponible vous pouvez vous rabattre sur la copie conforme que je maintiens sur docstring tout est exactement pareil bien évidemment au niveau du HTML donc vous pourrez suivre cette formation sans aucun souci je vous mets le lien en description de la vidéo si jamais il change dans le futur je mettrai à jour la description de la vidéo pour que vous ayez toujours le bon lien mais pour l'instant c'est docstring.fr/api/boxtoscrape/ / index.html dans cette partie on va voir comment installer et utiliser beautiful soup pour analyser et naviguer à l'intérieur de notre HTML qu'on a récupéré grâce à la bibliothèque request donc la première chose qu'on va faire c'est installer beautiful soup donc pour ça j'utilise là encore PIP et il faut bien mettre la version 4 ici il y avait la version 3 qui est une version assez vieille qui fonctionnait avec Python 2 la dernière version en date c'est la version 4 donc n'oubliez pas de le spécifier quand vous faites PIP install tout en minuscule ici beautiful soup 4 vous appuyez sur Entrée pour valider là encore ça va être assez rapide et on va pouvoir l'utiliser en l'important donc le nom du package c'est BS4 donc on va faire from BS4 et on va importer la classe beautiful soup qui va nous permettre de créer un objet beautiful soup qu'on va appeler généralement soupe vous allez voir ça très souvent revenir dans les scripts donc ça c'est juste une variable qu'on va créer on pourrait l'appeler n'importe comment dans notre cas on va l'appeler soupe parce que c'est ça qu'on voit revenir très souvent et cette variable donc on va la créer à partir de beautiful soup et cet objet beautiful soup donc cette classe on va créer une instance à partir de cette classe on va lui passer le html donc je pourrais tout simplement lui passer du HTML ici comme ça que je ferai dans une chaîne de caractère ça n'a pas beaucoup d'intérêt nous ce qu'on va vouloir faire c'est récupérer le HTML à partir d'une URL et en guise d'exemple on va utiliser un site bien connu des étudiants en scrapping de données qui s'appelle books.touscrape.com qui est un site d'exemple avec plein de données qui a l'avantage d'être assez simple et qui permet de comprendre les fondamentaux du scrapping de données donc pour récupérer et analyser les données donc on va copier cette url ici books.uscrape.com on va revenir dans notre script ici on va mettre cette URL dans une variable URL et on va ensuite faire une requête avec le module request que j'ai importé au-dessus une requête GET tout simplement vers cette url on récupère tout ça dans un objet response et on va passer le texte de cette réponse donc response.text à notre objet beautiful soup on va pouvoir ensuite spécifier à la suite le parseur qu'on souhaite utiliser donc le parsur c'est en fait la méthode d'analyse de notre fichier il faut savoir que beautiful soup dispose de trois parsur qui permettent d'analyser différemment les documents le premier parseur c'est un parseur qui s'appelle lxml-xml donc comme son nom l'indique c'est un parseur qui permet d'analyser les fichiers XML alors XML c'est un langage de balisage qui est générique qui est encore plus générique que le html les deux se ressemblent beaucoup donc c'est un langage qui de la même façon que HTML est basé sur des balises donc les fameuses balises qu'on a par exemple avec le body et cetera sauf que en XML on va pouvoir utiliser pas mal n'importe quoi en fait c'est nous qui définissons les balises donc on pourra mettre par exemple template ici ou Patrick le fameux Patrick et le html si vous voulez c'est une version du XML qui est un peu plus cadré avec des balises très classiques qu'on connaît tous comme le body le H1 le P et cetera donc c'est des balises qui sont définies par le langage le XML c'est plutôt utilisé pour échanger des données entre différents systèmes pour stocker des données pour faire des fichiers de configuration et cetera donc ça c'est le premier parseur qui est disponible qu'on peut utiliser donc aussi avec beautyful soup si jamais vous voulez analyser ces types de fichiers les deux autres parseurs qui existent ce sont spécifiquement des parseurs pour analyser du HTML donc on a l'analyseur html.parseur qui est un analyseur intégré à Python qui va iser la bibliothèque HTML parsur il est plus rapide que le deuxième qu'on va voir parce que il écrit en C mais il est un peu moins tolérant aux erreurs qu'on peut avoir dans du formatage HTML donc ça fonctionne très bien si vous avez un document qui est très très bien formaté mais si vous avez des erreurs par exemple des balises qui sont mal fermées ou des choses du genre et bien ça va moins fonctionner que l'autre parseur qui est HTML 5 lib comme ceci qui est donc une bibliothèque externe qui est écrit en Python donc c'est c'est un petit peu plus lent que le C mais il est un peu plus tolérant aux erreurs de formatage donc si vous savez que vous allez avoir un document HTML qui est pas forcément très bien structuré vous pouvez préférer ce parsur personnellement je préfère toujours commencer par le html.parseur puisqu'il est plus rapide et si jamais je vois que j'ai des problèmes et qu'il y a un fichier HTML un peu plus complexe je peux passer sur l'autre si jamais vous vous souvenez pas des différents parseur qui sont disponibles vous pouvez faire un contrôle B ou command B sur MacOS ou faire un clic droit sur la CL class beautiful soup alleer dans go to et declaration or usage et là ça va vous ramener donc dans la dans la classe tout simplement beautiful soup ici à l'intérieur du module et vous allez retrouver ici dans le param features ici les différents parseurs qui sont disponibles donc on retrouve les trois ici en fait il y en a quatre pour le lxml on a lxml ici et lxml- XML et ensuite on a HTML parsur et HTML 5 clip donc voilà si jamais vous ne vous en souvenez plus un moyen rapide de les retrouver et donc une fois qu'on on a créé cette instance on va pouvoir l'afficher donc je vais faire un print et on a une méthode bien pratique qui s'appelle pretttify qui nous permet d'afficher ce HTML sous une façon un peu plus facile à lire donc je vais exécuter le script pour vous montrer et là vous voyez qu'on a vraiment une page qui ressemble 100 % à du html avec pretttify qui va nous permettre de garder les indentations les retours à la ligne et cetera si j'enlève le pretttify vous allez voir que c'est un petit peu moins dig geste on va avoir des choses qui sont un petit peu moins bien vous voyez là il y a pas forcément des indentations ici on a tout qui est sur la même ligne donc c'est un petit peu plus difficile à lire qu'avec le prettyy si je vous le refais vous allez voir qu'à la fin avec les articles ici vous voyez il y a beaucoup plus d'indentation donc c'est un peu plus facile à lire en général avec pretttify et le pretttify vous pouvez le faire à n'importe quel endroit sur différentes nodes qui vont vous être retourné par beautiful soup donc quand je parle de node en fait ça va être les différents objets qui vont constituer notre HTML je vous ai fait un petit exemple ici pour vous montrer avec une fonction récursive comment on peut facilement traverser le DOM donc je vous mettre tout ça dans les sources on a donc cette fonction qui va nous permettre de parcourir récursivement l'arbre Document Object Model on va à chaque fois récupérer le nom de l'élément s'il existe puisque vous allez voir que des fois il y a des éléments comme des retours à la ligne ou des tabulations justement qui n'ont pas de nom donc ça va être des éléments qui vont pas être très utiles pour nous nous ce qu'on veut c'est juste récupérer les éléments comme le body le H1 les paragraphes les images et cetera et donc si on a un sur l'élément on va l'afficher et ensuite si on a un attribut children sur l'élément donc c'est-à-dire que si l'élément contient des enfants on va passer à travers chaque enfant de element point children donc on va passer sur chaque enfant et réappeler cette fonction travers Dom donc c'est là le paramètrre de récursivité et on va incrémenter le niveau et ça en fait qu'est-ce que ça va faire ben ça va tout simplement nous afficher de nouveau toute la structure de la page html donc si je lance le script vous allez voir qu'on a quasiment la même chose que ce qu'on avait précédemment avec le prtify sauf que là on a juste le nom des balises donc on n pas le texte on n pas les attributs juste le nom des balises et vous voyez de cette façon avec cette fonction récursive qu'on est bien ici en présence d'objets python avec des attributs et qu'on a bien donc ce document qui est analysé par beautiful soup et qui nous permet de naviguer à l'intérieur de la structure HTML donc c'est pour ça que beautiful soup est très très apprécié des développeurs qui font du scrapping parce que ça va vraiment nous permettre de naviguer à l'intérieur de cette structure facilement là je vous ai montré juste un petit aperçu de ce qu'on peut faire mais on va voir dans les prochaines parties comment on peut facilement récupérer des éléments en les ciblant grâce notamment aux classes ou au nom des balises pour récupérer par exemple toutes les images ou tous les titres d'une page web dans cette partie on va voir un peu plus précisément comment on peut récupérer des informations avec beautyful soup et naviguer à l'intérieur de la structure HTML de notre page donc dans ce cas-ci toujours le site books.toscrape.com qui contient différents livres qui contiennent des informations comme le prix les nombres d'étoiles et cetera donc la première chose que vous allez remarquer très certainement quand vous faites un soup point c'est qu'on a beaucoup beaucoup de fonctions ici et notamment on a quelque chose d'assez bizarre c'est-à-dire qu'on a deux nomenclatures donc on a une nomenclature en lower case comme ça donc par exemple si je prend la méthode find all vous voyez qu'on a find tiré du bas all mais on a aussi find all comme ça avec une majuscule sur chaque mot donc le snake case ou Pascal case si mes souvenirs sont bons donc vous vous demandez probablement pourquoi on a ces de nmanclatur est-ce qu'il y a une différence entre les deux donc pas du tout moi je vous conseille d'utiliser cette façon de faire donc qui est la nouvelle façon de faire qui suit les recommandations de la PEP 8 pour Python avec les noms des méthodes qui sont comme ça en lower case donc la seule raison pour laquelle on a encore accès au final comme ça avec une majuscule et non pas les tirer du bas c'est tout simplement pour des raisons de rétrocompatibilité à avec les précédentes versions de beautiful soup donc c'est sûr que ça fait un petit peu fouilli à chaque fois que vous tapez F comme ça ici vous allez voir qu'il y a beaucoup de choses comme ça avec à chaque fois des doublons donc faut pas vous en faire moi je vous conseille vraiment tout le temps de faire F tirer du bas pour comme ça filtrer et avoir automatiquement toutes les versions avec le lower case qui sont directement visibles donc une fois qu'on a dit ça maintenant qu'est-ce qu'on peut faire avec ces différentes méthodes vous allez voir qu'on a pas mal de méthodes mais il y en a qu'on utilise un peu plus que d'autres notamment find et find all donc la différence entre les deux c'est que find va nous retourner un seul élément donc imaginez qu'on ait plusieurs paragraphes sur la page si je fais find p comme ça il va nous retourner uniquement le premier paragraphe qui va trouver sur la page donc si je fais un find de body par exemple dans ce cas-ci ça va nous retourner le body et il n'y en a qu'un donc ce n'est pas un problème je peux utiliser find comme ça et si je fais un print du body vous allez voir qu'on a finalement toute la page qui est afficher comme je vous ai dit à chaque fois qu'on va récupérer quelque chose sur la page on peut faire un prettyy sur tous ces éléments donc sur tous ces nœuds du HTML à chaque fois on a ce pretttify qui est disponible qui va nous permettre de mettre en forme les données qui nous sont retournées avec les tabulation les retours à la ligne et cetera donc là on a récupéré le body si on fait un find all dans ce cas-ci avec le body vous allez voir que ça ne change pas grand-chose sauf que plutôt que d'avoir directement tout le texte on va avoir une liste et quand je dis tout le texte en fait même si là ça nous affiche du texte il faut bien comprendre que comme on l'a vu c'est des objets donc c'est des objets avec des attributs on peut les retourner si on les convertit en chaîne de caractère avec string sous forme de texte donc là dans ce cas si ça ne fonctionnera pas avec le findall ou plutôt ça nous retournera la liste en forme de texte puisque là vous avez vu à la fin on a un crochet pourquoi et bien parce que find all va toujours nous retourner une liste même si on a qu'un seul élément donc là si je fais un print type de body vous allez voir ici qu'on a un result set donc c'est un élément beautiful soup même si ça ressemble à une liste c'est pas 100 % une liste bien sûr ça ressemble à une liste mais c'est un objet beautiful soup qui est dans ce cas-ci un result set qui contient donc différents éléments si je fais un find par contre juste sur le body on va relancer pour afficher le type là vous voyez qu'on a un élément tag donc on a juste le tag body donc juste la balise BODY et quand on fait donc avec le find all on va se retrouver avec plusieurs éléments donc avec le body ça n'a pas trop d'intérêt mais si par exemple je fais un find all sur les images là on va pouvoir récupérer toutes les images de notre site donc je vais changer le nom ici pour que ce soit un peu plus explicite on va mettre image je relance et là vous allez voir qu'on a une liste avec toutes les images de notre notre page web si vous voulez les afficher un petit peu mieux avec un print on peut utiliser la fonction pprint du module pprint donc from pprint import payprint comme ceci avec 2p et ça va vous afficher la liste d'une façon un peu plus claire et là on voit bien qu'on a donc toutes les images qui sont retournées donc toutes les images de notre page web donc ça c'est très pratique c'est le premier qu'on voit revenir le plus souvent pour récupérer par exemple toutes les balises P toutes les balises H3 on peut récupérer tous les éléments comme ça de notre page avec le find all et on peut aller plus loin en filtrant sur certains attributs notamment un attribut bien pratique qui est l'attribut classe donc dans ce cas-ci on va mettre un tiret du bas puisque là si j'enlève le tiret du bas vous voyez qu'on a une colorationation syntaxique qui nous indique bien qu'on est avec le mot-clé réservé par python classe qui permet de créer des classe donc pour ne pas avoir un clash entre les noms ils ont décidé de rajouter ici un tirer du bas et ça nous permet ici de préciser une classe donc si on va voir sur le site par exemple si je vais voir ici en faisant un clic droit inspect on va voir qu'on a ici une un tag donc une balise article avec une classe product pod donc je vais grossir un petit peu pour qu'on ait bien ici donc product pod donc je peux utiliser ce nom de cette classe pour filtrer tous les articles donc là je crois que les articles c'est uniquement pour les livres ici et qu'il n'y a pas d'autres articles mais imaginez qu'on est des articles qui n'est pas cette classe et bien il ne serait pas récupéré si je le mets ici donc là je vais prendre la balise article et on va dire qu'on veut filtrer uniquement les articles donc les balises articles qui ont comme classe product pod donc je garde le le findall on va garder le nom image ici je relance et là on va bien avoir tous les articles de notre page donc là c'est un petit peu fouill ici mais on voit bien qu'on retrouve les H3 avec les icônes donc pour les étoiles l'image quelque part voilà image container et l'article ici avec la classe product pod donc vous voyez qu'il y a beaucoup d'options comme ça on va pas toutes les voir dans cette partie il y a beaucoup de choses qu'on va voir par la suite avec des cas un peu plus concret mais vous voyez que très facilement avec quelques lignes de code ici on peut récupérer des éléments très précis de de notre page et comme on l'a vu également on peut naviguer à l'intérieur de cette structure donc par exemple ici sur mon site on va voir une barre sur le côté avec un aside donc je peux cibler ce aside avec un find donc on va dire aside = soup.f et on va dire qu'on veux récupérer le aside et ensuite je peux par exemple afficher tous les children donc si je fais un aside point children vous allez voir qu'on a un truc qui est pas très digeste on va voir tout simplement un list itérator donc c'est un itérateur un itérateur il va falloir boucler dessus pour pouvoir afficher les différents éléments et les récupérer donc je vais dire pour child inaside.children et on va afficher child.name je relance le script et là vous voyez que comme je vous avais dit des fois on a des non donc les non qu'est-ce que c'est c'est tout simplement quand on a des retours à la ligne par exemple ou des tabulations donc là si on prend notre side on voit que dans les children on a bien le premier div ici avec les promotions left et le deuxième div qui est les catégories et entre les deux on a des non qui correspondent à des éléments donc qui n'ont pas de balise définie qui sont par exemple des retours à la ligne ou des tabulations donc dans ce cas-ci on a bien les deux div si on veut pas afficher ces éléments non on peut dire tout simplement if child.name et si donc c'est égal à non ici on ne va pas rentrer dans cette structure conditionnelle je refais impr print de child.name et là on aura bien uniquement les deux div et on peut continuer comme ça on peut y aller de plus en plus on peut refaire des find à l'intérieur de tout ça également donc imaginons que je souhaite récupérer le div qui contient la classe side Catégory à l'intérieur de mon side et bien je peux faire un nouveau find dessus donc je veux dire side categories = aside.find et là on va dire qu'on souhaite chercher le div avec la classe qui est égale à Side categories et là si je fais un print de Side categories vous allez voir qu'on retrouve bien donc la liste de toutes les catégories qui sont sur la barre de navigation sur le côté donc on retrouve bien notre div ici avec le la liste donc unorder list ici avec les books et toutes les catégories travel mystery et cetera et vous voyez qu'on peut donc continuer comme ça avec des find ou des find all donc dans ce cas-ci probablement ici que je vais vouloir récupérer les les a par exemple donc là je pourrais par exemple faire une variable links et faire site categories.find All cette fois-ci et cibler toutes les balises a et afficher tous les links ici donc je vais faire un pprint pour que la liste s'affiche un petit peu mieux et là on voit qu'on récupère bien les liens de toutes les catégories dans la barre de navigation donc vous voyez comme ça ça permet de cibler des choses très spécifiques plutôt que de récupérer tous les liens sur la la page puisque là si on retourne sur la page on a des liens un petit peu partout on a le lien ici on a le lien pour home ensuite on a le lien de tous les livres ici le lien pour ajouter au panier donc nous par exemple si on veut uniquement les liens de cette barre de catégorie et bien on peut aller cibler ce aside ici donc cette balise aside et ensuite naviguer à l'intérieur de tout ça avec des find ou avec des children vous allez voir si vous explorez un petit peu tout ça qu'on a pas mal d'autres choses qui sont disponibles par exemple on peut faire find next sibling on peut récupérer également le parent donc si je fais un print de ite point parent et que je continue comme ça bien un moment je vais me retrouver sur le body là je continue et vous voyez que si je remonte tout en haut on va probablement arriver pas loin du body donc là je reviens on est sur le container fluide et je peux continuer comme ça et c'est comme ça qu'avec par exemple des boucles while on peut remonter dans un sens ou dans l'autre pour par exemple récupérer le parent ou les enfants tant qu'on a un parent qui est disponible ou tant qu'on a un enfant qui est disponible donc on a vraiment ici toutes les notions de récursivité si vous souhaitez naviguer comme ça ou si vous souhaitez rester sur quelque chose de plus simple et que vous savez précisément ce que vous cherchez et bien vous pouvez utiliser find ou find all pour naviguer à l'intérieur de cette structure HTML dans cette partie on va récupérer des informations spécifiques sur la page donc on va le faire ensemble dans cette partie et par la suite je vais vous laisser tester par vous-même pour chercher d'autres informations dans notre cas ici on va vouloir récupérer deux choses à savoir le nom de toutes les catégories qui sont dans la barre ici à gauche et également toutes les images qui sont sur cette page d'accueil ça va me permettre de vous montrer d'autres techniques pour récupérer des informations notamment ici pour récupérer l'attribut source des balises images de notre page html donc la première chose qu'on va vouloir faire c'est récupérer ici le nom de toutes les catégories donc là j'ai un petit peu réorganisé mon espace de travail on a en bas ici l'aperçu du HTML donc ça vous pouvez faire un clic droit et inspect vous avez ces outils sur la plupart des navigateurs comme chrome brave Firefox et cetera donc ça nous permet d'afficher ici le html et de naviguer pour voir comment on peut récupérer les informations dont on a besoin donc nous on voit qu'ici on a un a side qui correspond à la barre de navigation sur le côté et on va avoir différents niveau ici qui vont être imbriqués les uns dans les autres et au dernier niveau ici avec les li on va avoir le titre de chaque catégorie donc si je déplie le li ici on voit qu'on a un lien et à l'intérieur de ce lien on a bien le nom de la catégorie donc vous voyez ici qu'on va devoir descendre dans notre HTML donc là il faut bien analyser à quel niveau on peut se placer on pourrait se dire qu'on va aller directement vers le UL avec la classe nav list ça peut être un bon point de départ à voir s'il n'y a pas d'autres endroits sur la page où il y aurait une autre UL avec navelist donc là on peut faire une recherche je fais contrôle C contrôle F pour faire une recherche contrôle V et là on voit qu'on a juste un élément donc on voit one of one ici donc ça veut dire qu'il n'y a qu'un seul élément avec la classe navlist sur toute la la page donc on pourrait commencer directement ici si on veut être un petit peu plus sûr puisqu'il faut toujours penser sur le long terme on peut se dire que ce site en fait va évoluer et que par la suite les développeurs du site pourraient choisir de rajouter d'autres barres de navigation avec cette même classe donc ça peut être un petit peu risqué de cibler ce nav list moi je trouve qu'ici le div avec la classe side categories ça me semble un meilleur choix puisqu'on risque de n'avoir qu'un seul élément ici avec cette classe side categories si vous voulez être le plus spécifique possible vous vous pouvez chercher un ID puisque les ID ils vont être uniques sur la page dans ce cas-ci on ne voit pas d'ID spécifique donc moi je vais me baser sur ce div avec cette classe sideite categories qui me semble être un bon indicateur qui va rester unique même si le site évolue donc je vais cibler ce div ici je reviens dans mon code Python et je vais faire soup.f et on va chercher le div qui a la classe qui est égale à Side categories on va vérifier tout de suite si on a bien récupéré ce qu'il faut donc je vais le mettre dans une variable que je vais appeler aside et je vais faire un print de ce side je lance le script et là normalement je devrais récupérer le UL donc la classe UL avec le nav List qui est juste en dessous voilà donc on a bien notre site categories et le nav List qui va nous permettre de récupérer les catégories donc on va descendre on va faire une variable qu'on va appeler categgories et on va faire aside.find et on va chercher le UL qui est à l'intérieur donc je ne vais pas spécifier le nav list ici on a qu'un seul UL et ensuite on va descendre comme ça puisque à l'intérieur de ce UL on a un i qui correspond à cette classe books ici donc là on a un premier lien books et ensuite on a un autre U avec tous les li qui correspondent à toutes les catégorie donc on va descendre comme ça là on est au niveau du premier UL on va avoir un seul li ici donc je vais pouvoir faire un seul find et non pas un find all juste un find et ensuite on a là encore un seul UL donc on va descendre comme ça on va faire point find et là on va chercher le li et ensuite on va chercher le UL à l'intérieur de ce li donc je vais faire un print de catégories pour voir si on est bien au bon endroit donc je fais un print je reviens tout en haut ici et on voit qu'on est bien au niveau du UL qui contient tous les li des catégories et donc à l'intérieur de ces lii on va pouvoir cibler le texte donc récupérer le texte puisque si je viens ici on voit qu'on a un lien et que dans ce lien on a un texte qui correspond au nom de la catégorie donc là je vais faire une boule je vais dire pour catégorie in categorieschildrun donc on va boucler sur les enfants de cette catégorie là si je fais un print de catégorie point texte vous allez voir que on va avoir directement le nom de toutes les catégories le seul petit problème qu'on a ici c'est que on a pas mal de bruit autour donc par bruit en fait j'entends tout simplement des espaces ici puisque si on retourne voir dans le HTML à l'intérieur du lien on voit qu'on a le Travel mais le Travel il est à la ligne avec des espaces et donc c'est ça qu'on a ici on a tous les espaces qui sont autour donc pour enlever ces espaces on peut utiliser cette fois-ci une méthode de Python qui est la méthode strip qui va enlever tous les espaces au début et à la fin de notre chaîne de caractère puisque catégorie point texte ici nous retourne un objet de type chaîne de caractère donc on peut utiliser le Strip dessus donc là si je relance mon script on voit que cette fois-ci on a bien enlevé les espaces qui étaient avant et après mais si vous regardez bien il y a encore un truc qui devrait vous surprendre c'est qu'on a ici des des espaces en fait comme des retours à la ligne alors qu'est-ce que c'est est-ce que ça vient encore là d'espace qui n'ont pas été correctement enlevés et bien là en fait ce n'est pas ça si vous vous souvenez bien je vous avais dit que il y a pas mal d'éléments sur nos pages qui vont être des objets non puisque on va avoir des retours à la ligne des tabulation et plein d'autres choses qui ne correspondent pas à des balises HTML donc ça comment on peut vérifier et bien on peut vérifier si on fait un print de catégorie point name et bien on va avoir soit le nom de la balise soit non puisque l'objet qu'on va récupérer de beautiful soup n'aura pas de nom donc les balises HTML elles ont un nom comme li a UL divide et cetera et si on est en présence d'un élément qui n'est pas une balise HTML ce nom sera égal à non donc là si je relance le script vous allez voir qu'on va alterner entre les li qui contiennent le nom des catégorie et les non qui correspondent à des retours à la ligne donc on va pouvoir utiliser ça pour faire une structure conditionnelle on va dire if categgory.name on va faire un print de catégorie.text.strip je relance et là vous allez voir que on a plus ces espaces entre chaque nom de catégorie et on récupère bien uniquement le texte à l'intérieur des li donc tout ce code ici on peut le simplifier avec une compréhension de liste là on a une boucle avec un IF on va simplifier tout ça et on va dire categories div ici et on va faire une autre variable categgory qui va être égale à une compréhension de liste donc je vais me donner un petit peu plus d'espace ici pour qu'on puisse voir tout le code sur la même ligne donc qu'est-ce qu'on va faire on va commencer par faire notre book donc je vais juste faire child for child in categories div.childen donc là on fait juste récupérer l'enfant pour chaque enfant dans categories.children et on va faire le if tout de suite donc if child.name donc seulement si on a un child.n donc là on avait mis categories on peut mettre child c'est plus générique ici donc là on va récupérer les enfants enfant pour chaque enfant dans les enfants de categories.d si on a un nom associé à l'enfant donc on va enlever tous les n comme ça et nous ce qu'on veut c'est par récupérer l'enfant mais le texte avec le Strip ici donc on va copier tout simplement cette partie là et la mettre à la suite de notre child donc là on récupère le texte de l'enfant sur lequel on a fait un stript pour chaque enfant sur categories div.children si on a un name associé à cet enfant donc ça va donner normalement la même chose là je vais faire un pprint de ma liste categories je relance le script et là on va avoir exactement la même chose qu'on avait à l'intérieur de notre liste donc on a bien récupéré ainsi toutes les catégories de notre site à scrapper donc vous voyez ici qu'avec seulement ces trois lignes de code on a pu récupérer le texte de toutes les catégories du site et maintenant je vous avais dit qu'on va pouvoir également récupérer des attributs sur des balises donc on va faire le test avec les images si j'inspecte ici une image on voit que l'image elle est contenu à l'intérieur du source donc de l'attribut src ici on a aussi le Alt et on a aussi la classe nous ce qui va nous intéresser ici c'est le SRC donc ce que je vais faire c'est récupérer toutes les images pour ça je vais faire un findall directement sur le soup donc sur l'intégralité de notre page html et je vais cibler toutes les images puisque si on regarde ici vous voyez que on a en fait juste les images des livres donc là encore si vous voulez avoir quelque chose qui va être un peu plus euh pérenne sur le long terme vous pourriez cibler un peu plus précisément donc là par exemple regardez où est-ce qu'on est donc là on a une section et euh c'est tout ce qu'on a on a une section avec un div qui n'a pas classe et on a ensuite des OL donc des order list avec des rangées donc vous voyez que là il y a pas grandchose qu'on peut cibler on pourrait cibler directement la section faut voir s'il y a d'autres sections à l'intérieur de la page donc là je fais une recherche pour la section on voit qu'on a une seule balise section sur toute la page donc on pourrait déjà faire un find de section et ensuite à l'intérieur faire un find all de image si on voulait s'assurer de cibler uniquement les images à l'intérieur de cette partie sinon vous pouvez faire un find all de toutes les images avec le risque que si par la suite les gens qui développent le site rajoutent des images par exemple ici un logo et bien on récupère également le logo et pas juste les images de livre donc moi je vais garder ça comme ça ici et on va faire donc une boucle pour image in image on va faire un print de la source de l'image donc pour récupérer un attribut c'est facile il suffit de faire comme avec les dictionnaires en python c'est-à-dire rajouter des crochets et mettre le nom de l'attribut qu'on souhaite récupérer donc là je vais mettre le nom SRC je lance le script et là on va avoir les sources de toutes les images à intérieur de cette section attention cependant avec cette nomenclature c'est exactement comme avec les dictionnairees de Python si l'attribut src n'existe pas on va avoir une erreur donc pour illustrer ça je vais sauvegarder le html dans un fichier donc on va faire with open et on va ouvrir donc le index.html qui va être dans le même dossier que mon script Python on va ouvrir en mode écriture et on va ouvrir ça en tant que F et faire un f.write de response.text donc je commande tout ça pour l'instant j' n'en ai pas besoin je veux juste écrire le fichier je vais aller dans mes fichiers ici on va aller voir le index.html on vérifie qu'on a bien tout notre Doct type ici donc c'est bon et on va faire une recherche pour les images donc là on a par exemple l'image du premier livre et ce que je vais faire c'est enlever cette source ici pour enlever l'attribut source sur cette première image donc qui correspond au premier livre je sauvegarde le fichier et là cette fois-ci ce qu'on va faire c'est que plutôt que d'aller chercher le html depuis le response.text donc depuis le résultat de la requête qui a été effectuée avec le module request on va aller le chercher à l'intérieur de notre fichier donc là on va faire with open et on va ouvrir le fichier index.html en mode lecture as f on va créer une variable HTML qui va être égale à f.read donc ça va lire l'intégralité du fichier index.html là je peux enlever ces lignes de code puisque je n'ai plus besoin dans ce cas-ci d'aller chercher le html sur internet je l'ai directement sur mon fichier et à la place du response.text ici je vais passer ma variable HTML et donc là ce qu'on on va avoir comme problème c'est que sur la première image on a plus l'attribut source et quand on passe par cette façon de faire avec les crochets vous allez voir que ça ne va pas fonctionner on va avoir une erreur de quiy error donc comme avec les dictionnaires quiy error qui indique que on n pas trouvé d'attribut SRC donc là si vous voulez éviter ça on utilise point get et ça va être là encore exactement comme les dictionnaires le point get va nous retourner la valeur si elle existe et va nous retourner non si elle n'existe pas donc je relance et là on voit qu'on a plus d'erreur sauf que sur la première image on a bien le non qui nous est retourné donc voilà pour récupérer un attribut à partir d'une balise là encore on pourra mettre tout ça dans une compréhension de liste donc je vous laisse le faire si vous souhaitez vous entraîner avec les compréhensions de listes pour le moment moi je m'arrête ici vous voyez qu'on a pu récupérer donc à la fois le texte à l'intérieur de balises HTML mais également des attributs qui sont présents sur ces balises puisque il faut savoir que le langage HTML utilise énormément ces attributs qui sont placés sur les balises et qui dans le cas des images nous permettent d'accéder à la source de l'image dans cette partie c'est à vous de jouer je souhaite que vous récupérier le titre de tous les livres qui sont sur la page d'accueil de notre site bookstoscrip.com alors vous pouvez partir du fichier index.html que je vais mettre dans les sources et utiliser donc with open comme ça pour lire le contenu de ce fichier si vous souhaitez avoir exactement la même chose que moi normalement le site ne change pas beaucoup mais comme ça vous êtes absolument sûr d'avoir exactement la même chose que ce que je vais faire dans cette partie dans la correction sinon vous pouvez donc utiliser l'URL pour aller chercher le HTML au moment où vous faites l'exercice il se peut que si le site a changé entre le moment où j'enregistre cette formation et le moment où vous faites l'exercice vous ayez quelque chose d'un petit peu différent donc à vous de voir quelle version vous préférez moi je vais partir avec le index.html et donc l'objectif c'est de récupérer le titre complet donc j'insiste sur complet puisque vous voyez par exemple ici sur le premier nom on a des points de suspension puisque il y a des titres qui sont assez longs et qui sont donc tronqués dans la page d'accueil donc à vous de voir comment vous pouvez récupérer le titre complet analyser le html vérifier où est le meilleur endroit pour récupérer le titre complet que ce soit sur les balises dans les attributs je vous laisse regarder ça et nous on se retrouve tout de suite pour la correction alors la première chose à faire comme d'habitude c'est d'aller analyser notre HTML donc on voit que pour chaque livre on a une balise article ici qui va contenir l'image le rating donc le nombre d'étoiles sur 5 on voit qu'on a trois étoiles par exemple et on va ensuite avoir une balise H3 avec le titre qui va être contenu dans un lien pour qu'on puisse cliquer dessus on a ensuite le prix et d'autres informations par exemple le stock et on va voir un article comme ça pour chaque livre sur la page donc la première chose à faire c'est essayer de trouver où à l'intérieur de cette balise article on va pouvoir retrouver le titre comme je vous l'avais dit si on regarde le titre on va voir que ici dans le texte on a des points de suspension donc on n pas le titre au complet mais on va trouver le titre au complet à 10 différents endroits notamment juste avant donc dans cette balise a qui est un lien on va voir un attribut title qui lui contient le titre au complet vous avez probablement remarqué également que sur l'image dans le alt on a le titre également moi je vais faire un petit peu moins confiance à ce alt puisque des fois il n'est pas présent ou alors on pourrait avoir quelqu'un qui va mettre quelque chose de différent là moi j'ai plus confiance dans l'attribut TITLE ici qui est assez explicite et qui contient le nom complet de notre livre donc moi je vais passer par ça je vais retourner dans mon fichier main.py ici et là comme d'habitude avec la programmation et encore plus avec le scrapping ici il y a plein de façons de faire donc moi je vais vous montrer différentes façons je vais vous montrer une première façon qui est probablement une façon plus proche de ce que vous avez fait et on va voir dans la suite une façon un peu plus avancée avec une technique qu'on a pas encore vu qui va permettre de cibler des éléments sur la page en fonction d'un attribut spécifique qu'ils ont donc dans ce cas-ci ça nous permettra de récupérer les liens qui contiennent un title donc un attribut title et et uniquement cela donc je vais commencer par la première façon de faire qui va être de cibler toutes les balises articles qui contiennent la classe product donc si on remonte ici on a tous les articles ici avec cette classe on va les cibler et à l'intérieur de ça on va chercher les balises a et on va récupérer la balise qui contient le titre pour récupérer l'attribut qui contient donc le titre du livre donc ce que je vais faire ici c'est récupérer déjà tous les article donc on va faire une variable article et on va faire soup.f all on va cibler les balises articles et on va cibler la classe product pod comme ceci et ensuite on va boucler donc sur ces articles donc je veux dire pour article sans s in Article donc articles ici avec un S on va récupérer tous les liens donc je vais faire une variable links on va faire articlef all et on va chercher le lien je pourrais faire un find mais le find ça va récupérer uniquement le premier lien et dans ce cas-ci le premier lien c'est ici le lien qui contient l'image donc moi ce que je veux c'est le deuxième donc ce que je vais faire c'est que je vais faire un find all et là diff différentes façons de faire on peut faire les crochets et mettre -1 puisqu'on considère que on a une liste avec deux liens et que le titre est le deuxième lien donc on pourrait mettre l'indice 1 pour récupérer explicitement le deuxième lien puisqu'on commence à compter à partir de 0 vous le savez en programmation donc là différentes façons de faire je prends le dernier en sachant qu'on a que deux liens et que le deuxième lien qui est le dernier est le titre ou alors je cible spécifiquement le deuxiè lien donc là si je fais cette récupération directement ici je peux enlever le S là c'est à vous de voir le niveau de gestion d'erreurs que vous souhaitez faire là je pourrais mettre un links comme ça et faire une vérification en faisant un IF line de links et supérieur ou égal à 2 et bien là ce qu'on va faire c'est qu'on va récupérer le Link et on va dire que links est égal à crochet 1 et ensuite on peut afficher sur ce link l'attribut TITLE donc faire un print de link.get title donc là j'utilise get au cas où on n pas cet attribut pour ne pas avoir d'erreurs donc là si je lance le script normalement on devrait récupérer les titres de tous les livres donc on les a bien ici avec les titres au complet qui ne sont pas tronqués donc ça c'est une première façon de faire comme je vous dis on peut simplifier ça en fonction du niveau de gestion d'erreur que vous souhaitez à voir là avec cette façon de faire avec la structure conditionnelle je suis sûr que ici ça ne va pas planter puisque on aura forcément au moins deux éléments dans notre liste donc on va pouvoir récupérer le deuxième élément et ensuite avec le GET je m'assure que même si on a pas d'attribut title on aura pas d'erreur dans notre script et on aura juste none qui va nous être retourné donc après à vous de gérer ça si vous souhaitez ajouter tout ça dans une liste pour vérifier si on a un élément qui est retourné dans ce link.get title et si on n pas d'élément donc si on a un non de ne pas l'ajouter dans votre liste donc ça c'est la première façon de faire qui nécessite pas mal de lignes de code ici et la deuxième façon de faire que moi je préfère qui va tenir en deux lignes de code c'est d'utiliser une façon de faire qu'on a pas encore vu donc ne vous inquiétez pas si vous n'avez pas fait ça donc je vais faire une variable que je vais appeler title tags et on va faire un soup.f all de tous les liens sur notre page et là le problème c'est qu'on va récupérer les liens également de l'image et on pourrait avoir d'autres liens sur la page puisque si on remonte ici si vous vous souvenez bien on a des liens également pour les catégories on va voir le lien sur la barre de navigation du site également donc là ça va nous poser problème mais on peut spécifier qu'on souhaite récupérer uniquement les liens qui contiennent un attribut title donc là encore à vous d'analyser le html pour vous assurer qu'il n'y a pas de title sur d'autres liens du site on pourrait très bien imaginer qu'ici on est un title qui corresponde au nom de la catégorie sur ces catégories donc là si on avait ça ne marcherait pas moi j'ai analysé le html et j'ai remarqué que on avait cet attribut title uniquement sur les liens qui correspondent au titre de chaque livre donc ça ne pose pas de problème et ce qu'on peut faire pour spécifier qu'on souhaite récupérer uniquement les balises de lien qui contiennent un attribut title c'est rajouter un paramètre ici en disant title égal à true donc là on envoie en argument true à title on peut le mettre directement ici avec une virgule après le nom de la balise et on pourrait même spécifier une valeur spécifique si on souhaitait par exemple récupérer uniquement les balises a qui contiennent le title qui est égal à light in theatic on pourrait mettre ici une chaîne de caractère et si je lance le script là vous allez voir qu'on va récupérer uniquement donc là si je fais un print bien sûr si je fais un print vous allez voir qu'on va récupérer uniquement ce lien qui contient light in theiatic ce qu'on peut faire c'est donc à la place de mettre une valeur précise mettre true et là ce qu'on va faire c'est récupérer uniquement les balises a qui contiennent un attribut title qui contient quelque chose donc là si je relance on retrouve bien ici tous nos liens avec à chaque ch fois un title pour récupérer ensuite les valeurs de ce title je peux faire là encore une compréhension de liste donc je vais dire a et je vais mettre entre crochet title donc là je ne suis pas obligé de mettre un get je peux le faire si je souhaite éviter les erreurs mais là comme on dit qu'on souhaite explicitement récupérer uniquement les balises qui contiennent un attribut title on ne devrait avoir aucun problème ici puisque on aura forcément un attribut title sur ces éléments donc là je vais dire a title for a in Title tags et ainsi on va pouvoir récupérer direct directement la valeur de l'attribut TITLE si je refais un pprint de titles ici cette fois-ci on se retrouve bien avec directement la valeur enchaîne de caractère de l'attribut TITLE sur tous les liens de notre page qui contiennent un attribut title donc vous voyez comme ça c'est très rapide avec juste ces deux lignes de code ici on peut récupérer les titres de tous les livres sur la page si on voulait encore plus réduire ce code on pourrait mettre directement le soup.fle ici et se retrouver avec une seule ligne qui nous permet de tout récupérer et là on a une bonne question des erreurs également puisqu'on va cibler spécifiquement les éléments qui ont un title égal à true donc si jamais par la suite on modifiait le html pour enlever cet attribut title et bien on se retrouverait tout simplement ici avec une liste vide et on ferait une compréhension de liste sur une liste vide et donc on aurait tout simplement une liste vide à la fin donc on aurait tout simplement pas d'erreur on aurait bien sûr pas les titres mais là il suffirait de changer votre script pour vous adapté aux changements qui ont été faits sur le site mais voilà avec cette solution vous avez tous les titres en une seule ligne de code bien bien sûr je le répète il y a plein de façons de réaliser cet exercice vous pouvez partir d'un peu près n'importe où sur la page vous pouvez faire des parents des children vous pouvez récupérer à partir du body et descendre partir d'autres éléments comme on l'a vu dans la première façon de faire là moi je trouve que cette façon de faire ici avec le ciblage directement sur le title c'est la façon la plus précise comme je l'avais dit on pouvait aussi partir sur les images de ce que j'ai vu les titres sont exactement les mêmes dans le alt de l'image si vous voulez vous entraîner pour pratiquer avec cette façon de faire je vous conseille d'essayer à la place d'utiliser les liens de cibler les images pour récupérer l'attribut ALT et ainsi la valeur du titre en partant des images de la [Musique] page dans les parties qui vont suivre on va réaliser trois exercices à partir du site sur lequel on a vu tous les exemples précédents je vous conseille vraiment de bien regarder les deux premiers exercices et notamment les corrections de ces exercices parce que on va utiliser ce qu'on va apprendre dans ces deux premiers exercices pour réaliser le trisème exercice qui va être beaucoup plus long dans lequel on va faire un script réellement bien fait pour gérer les erreurs et ajouter un niveau de logging on va également dans les prochaines parties voir d'autres bibliothèques un peu plus avancées et récentes comme selectolx qui va remplacer beautiful soup et qui va nous permettre de faire une analyse beaucoup plus rapide de la page web bien sûr on va voir tout ça ensemble dans les exercices et je vous montrerai également comment faire avec beautiful soup donc vous ne serez pas perdu c'est vraiment juste pour vous montrer d'autres façons de faire avec des outils plus récents essayez de faire ces exercices de votre côté notamment les deux premiers qui sont assez simples ne vous inquiétez pas il y a plein de façons de faire ces exercices le but n'est pas forcément d'arriver à la même solution que la mienne comme toujours en programmation il y a plein de façons de faire la même chose donc le but de ces exercice c'est juste de vous permettre de pratiquer et de tester de votre côté tout ce que l'on a vu dans les parties précédentes j'en profite pour faire une petite parenthèse de 10 secondes si tu souhaites te former à Python une seule adresse docstring.fr tu peux te créer un compte c'est gratuit et tu auras beaucoup de contenu des exercices des quiz des glossaires des formations des projets des parcours cré-toi un compte tu vas pouvoir découvrir tout ça et n'hésite pas également à nous rejoindre sur le serveur discord de doc string on a des challenges toutes les semaines des vocaux des salons d'aide donc rejoins-nous tous les liens sont dans la description dans cet exercice votre objectif va être de trouver les catégories de livres qui ne contiennent pas suffisamment de livre le but étant ici de permettre au librair de renforcer ses catégories si on va voir par exemple en bas dans la liste dans short stories vous voyez qu'ici on a un seul livre alors que d'autres catégories comme par exemple musique en contiennent bien plus le but de cet exercice est donc de parcourir toutes les catégories qui se trouvent dans la barre de navigation ici à gauche et de vérifier le nombre de livres contiennent chaque catégorie vous devrez permettre avec votre script de définir un seuil par exemple nous on va mettre 5 donc c'est-à-dire que notre script va nous retourner le nom de toutes les catégories qui contiennent moins de 5 livres et vous devrez être en mesure de changer ce seuil pour pouvoir voir ajuster et récupérer le nom des catégories qui contiennent en dessous d'un certain nombre de livres donc le but ça va être de passer à travers toutes ces catégories ici et de récupérer à chaque fois le nombre de livres et d'afficher cette information à l'écran le script devra également commencer de la page d'accueil c'est-à-dire que vous prendrez cette url avec la page d'accueil qui contient les catégories à gauche et la première page de tous les livres et c'est à partir de cette page d'accueil que vous allez devoir récupérer les liens de toutes les catégories ainsi que les noms des catégories et ensuite récupérer sur chacune de ces pages ici donc naviguer vers chacune de ces pages pour récupérer le nombre de livres et afficher un message dans le cas où le nombre de livres est inférieur ou égal au seuil que vous aurez défini si vous allez voir également les pages de certaines catégories vous verrez qu'on a des catégories qui contiennent beaucoup de livres et qui ont notamment une pagination donc dans cet exercice en fait on va considérer un seuil en dessous de 20 donc on va considérer que le libraire va juste vouloir vérifier des catégories qui contiennent moins de 20 livres donc ça ça va changer en fait votre façon de d'aborder ce script je vous le dis par avance puisque là par exemple pour une page comme ça on a 32 résultats ne commencez pas à essayer de faire de la navigation pour cet exercice on va juste se considérer sur des catégories qui contiennent moins de 20 éléments donc c'est-à-dire que par exemple une catégorie qui aurait 19 éléments donc qui aurait une seule page d'afficher et qui ne serait pas donc rempli on aurait seulement 19 éléments sur les 20 possible et bien c'est vraiment le cas le plus extrême qu'on va aller chercher essayez donc avec un seuil par exemple de 5 et 10 et retourner donc toutes les catégories qui ne contiennent pas suffisamment de livres donc en dessous de 20 livres donc 19 et moins donc voilà pour les indications bon courage et pour ceux qui souhaitent voir tout de suite la solution ou qui ont déjà réalisé l'exercice on continue tout de suite avec ma proposition de solution donc j'ai divisé mon écran en deux ici on se trouve d'un côté avec mon script donc un script très simple main.py et la page ici que je dois scrapper la première chose qu'on ce qu'on va devoir faire c'est donc récupérer les URL de toutes les catégories à partir de cette url de base alors ce qu'on va commencer par faire c'est importer les librairies dont on va avoir besoin donc on va avoir besoin de request pour effectuer des requêtes vers la page et récupérer le code HTML et on va utiliser beautiful soup pour récupérer le contenu de l'arbre du Document Object Model pour pouvoir naviguer facilement à l'intérieur du HTML je vais faire également une fonction que je vais appeler tout simplement main pour l'instant on va mettre un pass dedans et avec pycharm je peux mettre une condition ici très facilement en tapant juste main et en appuyant pour valider avec entrée et ça va me mettre cette fameuse condition ici if name = main qui va me permettre d'exécuter cette fonction uniquement quand je lance le script donc on va écrire tout notre code ici à l'intérieur de cette fonction main pour l'instant on ne va pas gérer les erreurs on va faire le script le plus simple possible et dans les prochains exercices vous verrez qu'on fera des scripts beaucoup plus avancés qui vont gérer tous les cas de figures possibles pour que le script ne s'arrête pas de fonctionner en cas de problème donc dans ce cas-ci qu'est-ce qu'il faut que je fasse je vais déjà commencer par analyser mon site ici donc la page de base je vais copier l'URL d'ailleurs et je vais la mettre dans une constante ici que je vais appeler base URL dans une chaîne de caractère et ici je vais tout simplement donc inspecter cette catégorie ici donc je vais faire un clic droit et faire inspect pour ouvrir les outils de développement de Chrome vous pouvez faire la même chose sur n'importe quel navigateur ouvrir les outils de développement et vous aurez sensiblement les mêmes ici moi j'utilise ici chrome puisque c'est celui qui est le plus utilisé dans le monde donc on va se trouver ici avec la catégorie sur laquelle j'ai cliqué et si on monte un petit peu au-udessus on a un UL avec une classe nav et navlist ici donc c'est ce qu'on va vouloir récupérer pour récupérer donc le html de cette page je vais faire une requête vers l'URL que j'ai défini donc on va faire une requête qu'on va récupérer dans une variable response et on va utiliser le module request pour faire une requête GET vers cet URL on va ensuite faire un beautiful soup à partir du contenu de cette requête donc comme je vous dis là on ne va pas gérer les erreurs donc on pourrait faire un resp race for status pour lever une erreur en cas de problème là dans ce cas-ci on va faire vraiment le plus simple possible donc on va créer un objet soupe donc une variable souple qui va être créée à partir de beautiful soup auquel on va passer le texte de la réponse donc response.text et pour le parseur on va passer le parsur html donc entre chaîne de caractère ici en deuxième argument à beautiful soup donc ici on crée une nouvelle instance de beutyful soup avec le contenu et le parseur je vais juste réduire un petit peu la police d'écriture pour qu'on puisse voir tout sur la même ligne comme ça ce sera plus simple pour vous pour suivre le code donc qu'est-ce qu'on va faire ensuite et bien on va récupérer les éléments donc tous les liens qui se trouvent à l'intérieur de cette navigation donc on va avoir ici un premier lien qui est books qui correspond en fait tout simplement à la page d'accueil si je me trompe pas effectivement on se retrouve exactement avec la même page donc nous ce qui va nous intéresser c'est pas le premier lien mais on va continuer un petit peu ici on a le index effectivement avec les books et ensuite on a un UL avec un autre Ie alors là je vais vous montrer une autre façon de sélectionner des éléments avec beautiful soup on va pouvoir utiliser la méthode Select à la place de la méthode find ou find all qu'on utilise généralement select c'est une méthode qui va nous permettre de sélectionner des éléments grâce au CSS donc grâce aux identifiants CSS donc je vais vous montrer les deux façons de faire la première façon avec les méthodes classiques find et find all et la deuxième façon avec le Select donc la première façon de faire ça va être de faire un soup point find pour récupérer la barre de navigation donc c catégorie ici donc on va récupérer l'élément UL avec les classes nav et nav list donc pour ça on fait un find de UL donc ça c'est le nom de la balise et pour les classes on va le spécifier dans le paramètre classe ici avec un tiret du bas puisqu'il ne faut pas que ça clashche avec le nom classe qui est défini par python donc ça c'est vraiment le nom du paramètre classe tire du bas et on va lui passer l'élément qu'on souhaite chercher donc dans ce cas-ci c'est les classes nav et nav list donc je mets un espace entre les deux on veut que cet élément UL ait à la fois le nav et le nav list donc c'est deux classes comme on les retrouve ici et ensuite ce qu'on va faire et bien c'est qu'on va tout simplement récupérer tous les liens à l'intérieur de cette UL donc ce qu'on pourrait faire également puisque bien sûr il n'y a pas qu'une seule façon de faire c'est après ça en fait descendre un petit peu et cibler le li et ensuite le UL et ensuite seulement les lii à l'intérieur de ce UL donc descendre un petit peu comme ça pour éviter d'avoir le premier lien moi dans ce cas-ci ce que je préfère faire c'est rester ici récupérer tous les liens et éviter juste le premier en considérant que le premier lien ici c'est le lien de la page d'accueil donc ce que ce que je vais faire c'est à partir de ce UL là on a fait un find donc on va avoir un seul élément on va avoir cet élément ici à partir de cet élément unique on va faire un find all pour récupérer tous les liens donc on va tout simplement faire find all et mettre entre guillemets le a qui correspond aux balises de lien donc là ça va nous retourner toutes les balises a donc la balise ici avec l'index et toutes les balises qui se trouvent à l'intérieur donc même si elles sont à l'intérieur d'autres balises comme ici le UL et le li ça va quand même descendre toute la structure pour retourner tous les liens qui sont à l'intérieur de ce UL donc on va récupérer comme ça tous les liens de toutes les catégories il suffira donc d'exclure le premier lien ici pour ne pas avoir la page d'accueil donc ça c'est la première façon de faire vous voyez que ce n'est pas forcément la façon la plus simple on a deux méthodes qui s'enchaînent ici on doit spécifier dans différents arguments donc en premier ici le nom de la balise et ensuite spécifier qu'on souhaite chercher la classe et cetera et cetera après on a un autre findall donc ça fait beaucoup de choses à la suite vous allez voir que la méthode alternative donc je vais mettre ici alternative ça va être d'utiliser les sélecteurs CSS donc on va utiliser select on a Select et select one qui correspondent respectivement à find et à find all ou plutôt l'inverse en fait on a select qui va être l'équivalent de find all puisqu'il va sélectionner tous les éléments et select one qui va être l'équivalent de find qui va sélectionner juste le premier élément qui est trouvé si vous voulez voir une bonne référence pour le CSS vous avez ce site qui est très connu qui s'appelle w3schools.com et vous avez ici dans les CSS selector un tableau qui répertorie tous les sélecteurs que vous pouvez utiliser donc vous allez voir que c'est très détaillé il y en a beaucoup qu'on peut utiliser et on va pouvoir faire ainsi tenir tout dans une seule ligne donc là vous voyez par exemple si on souhaite cibler un élément avec une classe on va juste mettre point et le nom de la classe si on souhaite sélectionner un élément qui a à la fois une classe et une autre on va mettre point name 1 point name 2 comme ça tout collé et on a plein d'autres choses comme ça ici par exemple si on souhaite sélectionner un élément qui a une classe sur un élément spécifique comme un paragraphe on peut mettre le nom de l'élément et on peut mettre aussi le nom de l'élément point et le nom de la classe donc nous c'est ce qu'on va utiliser je vais fermer ça je vais le remettre ici à droite nous ce qu'on va utiliser dans ce select donc c'est pas le select one on va vouloir récupérer tous les liens donc on va juste faire un select et ce qu'on va faire ici c'est une seule chaîne de caractère on va dire qu'on souhaite sélectionner l'élément UL donc comme on l'avait ici jusque-l ça change pas grand-chose et ensuite on va dire qu'on souhaite sélectionner l'élément qui a la classe nave et aussi la classe nav list donc on les met les deux à la suite comme ça collé sans aucun espace donc on cherche un élément UL qui a à la fois la classe nav et la classe nav list donc là encore comme ici et ensuite ce qu'on va faire c'est c'est un espace et dire qu'on souhaite récupérer tous les éléments à à l'intérieur de cet élément qui a été trouvé donc juste un espace pour spécifier que à l'intérieur de cet élément on souhaite récupérer tous les liens peu importe leur niveau donc ça va pas être forcément juste le premier niveau si on souhaitait avoir juste le premier niveau il y a une façon de le faire ça va être avec un symbole plus grand que là vous voyez avec le symbole plus grand que ça nous dit que ça va sélectionner tous les paragraphes dont le parent et le div nous ce qu'on veut ici ce n'est pas sélectionner uniquement les liens dont le parent et le UL on veut sélectionner vraiment tous les liens peu importe que les liens et comme parent directement le UL ou un autre parent qui est enfant du UL donc pour ça on met un espace et si on retourne voir notre référence ici vous allez voir ici on a le div espace P et on nous indique que ça va sélectionner tous les éléments P à l'intérieur de l'élément div donc finalement ces deux façons de faire sont assez équivalentes les débutants préfèrent généralement passer par F puisque c'est plus explicite on va spécifier explicitement ici qu'on cherche la classe alors que avec le Select il faut connaître un peu plus le CSS et c'est peut-être moins évident de Prim à bord à quoi va correspondre cette chaîne de caractère ici mais vous allez voir qu'avec la pratique généralement on préfère utiliser Select et utiliser nos connaissance en selecteur CSS pour simplifier ici finalement le code et tout faire avec select ou select one donc là on va avir les catégories qu'on va récupérer je vais commenter cette ligne moi je vais passer par l'alternative ici et je vais récupérer toutes les catégories dans une variable categgories donc pour l'instant on va pas aller plus loin on va juste faire un print de categgories et on va voir ce que ça donne donc je lance le script je fais un clic droit ici et je clique sur run main ça va créer automatiquement une configuration et ça va m'afficher le contenu de toutes mes catégories donc là on voit qu'on a bien une liste avec ici toutes les catégories qui sont à l'intérieur donc on a le lien avec l'attribut href le nom de la catégorie et on a donc toutes les informations dont on a besoin ici pour pouvoir ensuite accéder à chaque page de ces catégories donc ce que je vais faire ici c'est une compréhension de liste pour récupérer directement toutes les URL donc pour ça je vais faire une boucle donc je vais déjà faire la boucle simple categgory for category in categories donc là pour l'instant on ne fait absolument rien on récupère l'élément sans le changer moi j'aime bien faire cette méthode pour ceux qui sont pas trop habitués aux compréhension de liste ça permet de bien voir notre boucle ici avec les crochets et ensuite on va spécifier ce qu'on veut donc qu'est-ce qu'on veut nous ici on veut l'attribut href donc je vais mettre des crochets comme si on accédait à la valeur d'une clé d'un dictionnaire on pourrait également utiliser point get ici pour ne pas avoir d'erreur donc là c'est encore une fois exactement comme avec les dictionnaires donc moi je vais récupérer ainsi tous les liens et si je reviens ici je peux faire un print de categories relancer le script et vous allez voir que cette fois-ci ici on va voir uniquement les liens de toutes les catégories je pourrais aller récupérer je crois le title aussi qui va m'afficher le nom alors là on n pas le title je vais aller voir en faisant un inspect qu'est-ce qu'on a d'autre sur ces catégories donc on a juste le lien ah oui c'est le le texte qu'il faudra aller chercher en fait donc je peux faire catégorie.texte tout simplement et là si je relance on va voir cette fois-ci le nom alors on a des n partout je vais faire un texte pointstrip pour enlever les éléments au début et à la fin donc je relance et là on a bien le nom avec tous les éléments superflus qui ont été été supprimé donc on retrouve bien books travel mystery et cetera et nous comme on avait dit on va récupérer tous les éléments à part le premier vous voyez que là on récupère books qui correspond au premier élément et on avait dit que c'était la page d'accueil et qu'on ne le voulait pas donc là ce qu'on peut faire c'est faire un categories et filtrer pour commencer à partir de 1 et aller jusqu'à la fin de la liste donc là on fait un splice à l'intérieur de notre compréhension de liste pour récupérer les éléments uniquement à partir du deuxème élément donc on met 1 ici si on mettait zéro on commencerait au début là on met 1 et donc on évite le premier élément donc si je relance là on devrait commencer à travel et on a bien ici travel en premier je vais enlever le texte pointstp puisque nous c'est pas ce qu'on veut on veux le lien et je relance pour vérifier et là on a bien le book travel 2 qui correspond à la première catégorie travel donc ça fonctionne parfaitement je vais renommer ma variable je vais la rendre un peu plus explicite et on va l'appeler categories URL et ensuite qu'est-ce qu'on va faire bien on va tout simplement naviguer à travers chacune de ces catégories donc je vais faire une boucle pour catégorie URL in categories URL on va naviguer à travers ces catégories alors là vous allez voir que il y a un petit souci c'est que ces URL ce sont des URL relatives c'est-à-dire qu'elles sont relatives à la page sur laquelle on se trouve donc la page d'index ici et donc il va falloir les concaténer avec notre URL de base pour ça alors on peut faire bien sûr une concaténation simple c'est-à-dire enlever par exemple le index.html ici pour avoir juste l'URL du site et ensuite concaténer avec un plus ou avec une F string donc il y a différentes façons de concaténer des chaînes de caractères en python nous ce qu'on va faire c'est util utiliser une bibliothèque qui est dans la bibliothèque standard de Python qui nous permet de concaténer des chaînes de caractères qui correspondent à des URL donc ça va gérer beaucoup de choses en arrière-plan pour s'assurer qu'on va pas avoir de problème notamment on va pouvoir lui passer l'URL directement avec le nom ici du fichier index.html et ça ne va pas le rajouter donc ça va l'enlever et ça va bien concaténer avec la catégorie donc si on retourne voir ici dans notre run ça va avec le catalogue pardon catalogue categgory donc ça va bien enlever cet élément et ça va nous éviter de faire des manipulations donc peut-être que vous de votre côté si vous ne connaissez pas cette cette librairie qu'on va utiliser tout de suite peut-être que vous l'avez fait directement en faisant des splits donc c'est possible bien entendu mais ça rajoute beaucoup de manipulation de chaînes de caractère alors qu'on peut le faire directement avec cette librairie donc cette librairie en question c'est URL lib.parse et on va importer à partir de ce module la fonction URL joint qui va nous permettre de faire cette concaténation entre différentes URL donc ce qu'on va faire ici c'est concaténer notre URL de base avec l'url de la catégorie qu'on récupère dans notre boucle donc ce que je vais faire c'est créer une variable qui va s'appeler full URL et qui va être égale à URL join et on va joindre donc notre URL avec catégorie URL je vais faire un print de full URL ici et vous allez voir que on aura bien l'URL complète donc si je reviens ici vous voyez comme je vous avais dit que on a enlevé automatiquement le index. html et qu'on a une url valide qui va nous permettre d'accéder à la page de chaque catégorie pour être encore plus explicite je pourrais l'appeler plutôt absolute URL puisque là on parle d'une URL relative et on la rend absolue avec l'url de base du site donc qu'est-ce qu'on va faire ensuite et bien une nouvelle requête vers cette page donc on va refaire une variable response avec un request.get vers cette url absolu et on va récupérer là encore avec beautiful soup les éléments de cette page donc on va refaire un objet soup qui va être égal à betiful soup de response.text et on remet le html.parsur pour récupérer le Document Object Model dans notre objet soup ici donc qu'est-ce qui nous reste à faire et bien maintenant on va récupérer les différents livres qui sont sur la page donc là vous voit par exemple que pour la première catégorie on a 11 résultats alors là encore il y a différentes façons de faire comme d'habitude pas une seule façon de gérer les choses on pourrait se basé sur ce résultat ici donc faire un clic droit inspect et voir ici qu'est-ce qu'on a donc on a un for méthode on a le page header le 11 ici vous voyez qu'il est dans un une balise strong mais on a pas grand-chose d'identifiable autour on a un formulaire mais j'imagine que les formulairees il y en a peut-être plusieurs vous voyez que là on a un résultat sur 12 donc on a plein de formulaires dans la page donc ça va être un petit peu difficile ai aussi de les cibler avec ça donc personnellement je trouve que ce cet élément ici n'est pas très facile à identifier on pourrait bien sûr essayer de remonter un peu plus en avant d'aller dans ce div mais là encore c'est des classes bootstrap si je me trompe pas et ça pourrait très facilement changer si le site évolue donc moi je préfère passer sur autre chose c'est-à-dire tout simplement compter le nombre de livres qu'on a sur la page donc pour ça si on reprend notre notre outil de sélection ici on va aller voir les cardes qu'on a ici et on voit que chaque livre semble être contenu donc dans un article donc ça c'est bien c'est une bonne sémantique HTML donc un article avec une classe product pod et si je fais un search là-dessus on voit qu'on a 12 match donc là on voit qu'on a 11 résultats et pourtant 12 matchs donc il y a une petite incohérence entre les deux donc je vais essayer de voir où se retrouve ce product pod ailleurs que pour les articles qui correspondent à des livres et là en fait non je vois qu'on a 1 sur 11 donc il y avait peut-être un un petit problème de de rafraîchissement je vais refaire un search et oui effectivement là on a bien 11 donc ça fonctionne parfaitement et donc on va pouvoir tout tout simplement cibler ces articles avec cette classe product pod pour vérifier combien de livres on a sur la page donc je vais faire ça tout de suite là encore différentes façons de faire on peut repasser par le find all chercher les balises articles et utiliser le classe avec le tiret du bas ici donc le paramètre classe pour vérifier les product pods on peut aussi comme vous l'avez vu donc passer par le Select pour récupérer tous les éléments qui sont des articles avec la classe product pod donc moi comme je vous dis plus j'avance plus je préfère cette solution que je trouve moins verbeuse donc je vais supprimer et passer directement dans ce cas-ci par le soup. Select donc là qu'est-ce qu'on va faire bien on va récupérer tout ça dans une variable et il suffit de compter le nombre d'éléments qu'on a ici donc je peux faire un print de laine de books et ça va ainsi m'afficher le nombre d'éléments qui ont été trouvés sur la page et donc le nombre de livres donc là je vais lancer mon script et on va voir ce que ça donne on devrait voir les nombres ici le premier devrait être égal à 11 donc ça semble bien fonctionner puisque cette première catégorie avait bien 11 livres et si je continue on a 20 pour la deuxème donc je vais aller voir dans Mystery alors là on a 20 livres et on a 32 résultats donc notre méthode fonctionne à part le fait que quand on a plus que 20 résultats effectivement ça pose problème dans le sens où si on mettait un seuil de 25 par exemple et bien là nous on dirait qu'il y a juste 20 livres alors qu'en fait il y en a 32 donc c'est la limite de passer par cette façon de faire là moi je vais considérer que dans le cas de figure que je vous ai donné en fait le seuil va être assez bas donc va être en dessous de 20 on va chercher par exemple des catégories qui ont 5 10 peut-être 15 livres maximum pour pouvoir rajouter plus de livres donc si vous vous voulez avoir un script qui fonctionne avec plus que 20 éléments donc avec un seuil au-delà de 20 il faudrait probablement ici passer par le result là donc le nombre de résultat ici qui est plus explicite ou alors naviguer sur les pages mais là ça me semble encore un peu plus compliqué je pense que le mieux ce sera de passer ici par le résultat donc moi je vais garder cette façon de faire ici avec un seuil qui va être inférieur à 20 donc ce seuil d'ailleurs on va tout de suite le définir je vais faire un paramètre que je vais appeler threshold en bon français donc c'est un paramètre qui va signifier le seuil qu'on souhaite définir threshold signifie iant seuil en anglais je vais mettre une valeur par défaut qui va être égale à 5 et je vais le définir ici aussi donc je vais dire dans le Main que on va mettre 10 ici on va envoyer une autre valeur un peu plus grande que celle qu'on a par défaut et on va pouvoir utiliser cette valeur ici pour vérifier les catégories qui n'ont pas assez de livre donc ce qu'on va faire ici c'est tout simplement une structure conditionnelle je vais faire une variable intermédiaire avant pour que ce soit bien explicite on va faire une variable number of books qui va être égale à l'INE de books et on va faire donc if number of books est plus petit ou égal au esold alors on va faire un print qui va indiquer que la catégorie ne contient pas assez de livrees donc la seule chose qui nous reste à récupérer ici c'est le nom de la catégorie puisque pour l'instant on l'a pas récupéré donc là je vais essayer de trouver le nom de la catégorie on va faire un clic droit et un inspect sur le nom ici et là on voit qu'il est dans un H1 donc ça tombe bien les H1 normalement ils sont uniques sur la page et si je fais un search ici de ce tag H1 effectivement j'ai bien un sur 1 donc un seul résultat donc on va pouvoir utiliser ce H1 sur la page pour récupérer le titre de la catégorie donc je vais faire une variable catégoryie title qui va être égale à soup.select et on va sélectionner un seul élément cette fois donc on va faire un select one et sélectionner le H1 et sur cet élément on va sélectionner le texte tout simplement donc là on va faire dans notre F string ici on va dire la catégorie et on va insérer le nom de la catégorie donc catégoryie title ne contient pas assez de livres et là on va insérer le nombre de livres entre parenthèses pour avoir un indicatif donc on va reprendre notre variable number of books et on termine par un point et je vais mettre des guillemets autour de la catégorie pour qu'on l'identifie bien ici comme ceci donc voilà normalement on a tout ce qu'il faut on va essayer donc avec le thresold de 10 on va mettre 15 même comme ça la première catégorie ne contiendra pas assez de livres donc je relance mon script en cliquant sur la petite flèche et là voilà on a bien la catégorie travel donc ne contient pas cette livre on en a 11 ensuite celle qui suit c'est philosophie donc si on va voir mystery on en a 32 26 75 effectivement philosophie on a 11 11 classique en la 19 donc c'est bon et donc ça semble bien fonctionner on a notre script qui nous affiche tout ce qu'il faut on va essayer de changer le threshold ici là on était à 15 donc on a quand même pas mal de catégories on va essayer avec juste une donc on va voir quelle catégories n'ont qu'un seul livre donc ça c'est vraiment des catégories qu'il va falloir renforcer et là vous voyez probablement que le script n'est pas super rapide donc là quand on a beaucoup de requêtes comme ça à la suite avec la même session on va pouvoir utiliser justement un objet qu'on va appeler une session qui va éviter de refaire une requête à chaque fois donc ça c'est ça fait partie des optimisations que vous pouvez faire qui vont vraiment le plus grandement améliorer les performance de votre script donc là on voit qu'on a deux TR quatre catégories donc les catégories qui sont qui commencent à paranormal donc paranormal ici voilà et voilà là on a fini le script mais vous voyez que ça prend peut-être une petite minute pour passer à travers tous ces liens alors qu'il y en a pas énormément il y a peut-être une trentaine de catégorie donc là ce qu'on va pouvoir faire pour terminer le script je vais enlever cette cette ce commentaire ici si ce qu'on va faire c'est qu'on va faire une session donc on va faire avec un context manager une session avec request comme ça ça va éviter de créer une nouvelle requête à chaque fois on va garder la même session d'ouvert donc c'est un petit peu si vous voulez la même chose que si à la main en fait à chaque fois on fermait chrome on rouvrait chrome on fermait chrome et cetera vous êtes d'accord que ça prendrait beaucoup de temps à chaque fois de rouvrir le navigateur pour naviguer vers la page donc là ce qu'on va faire c'est avec un context manager créer un objet session à partir de request. session donc attention il y a bien une majuscule ici c'est une instance donc on crée une instance en tant que session ici et tout simplement à la place de faire un request ici et bien on va utiliser notre objet session donc je vais prendre tout ça je vais le décaler à l'intérieur de mon context manager et je vais remplacer les request.get par session.get et on va descendre ici pareil avec ce request ici et là vous allez voir que ça devrait être beaucoup plus rapide on va mettre un else ici pour voir et pour afficher en fait en disant que la catégorie contient assez de livres et on va mettre le nom de la catégorie là encore hop comme ça on l'INT catégorie title et on va mettre ça en F string donc vous allez voir la différence entre les deux là je vais mettre un thresold on va mettre 5 je relance le script et là vous allez voir que ça va assez vite ça défile et peut-être en on va dire une petite dizaine de secondes voilà en une petite dizaine de secondes vous voyez qu'on est passé à travers tous les liens alors que si j'enlève donc si je commande cette ligne et qu'à la place des sessions je mets un request et on va enlever notre indentation vous allez voir que ça prend pas mal plus de temps donc je relance et là c'est vraiment quelque chose qu'on peut voir à l' unu donc ça vous montre vraiment la différence de rapidité là vous voyez pour passer à travers tout ça on va peut-être mettre une trentaine de secondes par rapport à 10 ou 15 secondes donc ça va littéralement deux à trois fois plus vite on pourrait faire des tests de performance mais par habitude je vous le dis vraiment c'est la première chose que vous pouvez faire si vous souhaitez grandement améliorer les performances de votre script donc vous voyez là on est peut-être même à 40 secondes pour passer à travers tout ça donc ça fait une grosse grosse différence donc je vais remettre ma session ici avec le context manager et voilà normalement donc ça ça fait le tour on a bien récupéré donc le nom de la catégorie le nombre de livres et on a une indication à chaque fois qui nous indique si la catégorie contient assez de livrees ou non avec cette structure conditionnelle et le scrapping qu'on a fait de chaque page de la catégorie donc voilà pour cet exercice comme vous le voyez il y a plein de façons de le faire on peut utiliser des moyens un peu plus avancés ici comme le URL join qui nous permet de nous faciliter la tâche mais on pourrait très bien le faire avec de la concaténation plus classique donc avec DF strings et cetera de la manipulation de chaînes de caractère pareil pour les sessions là encore c'est des choses un petit peu plus avancées mais vous voyez que ça change pas mal au niveau des performances au niveau de beautiful soup là encore on peut utiliser select on peut utiliser find all ici on a pas fait du tout de gestion d'erreur donc ça veut dire que dès qu'on va avoir le moindre petit souci par exemple si il y a un élément qui n'existe pas sur la page donc si on n pas de href ici sur les liens si on a pas de barre de navigation ou quoi que ce soit ici le script va planter on verra dans les prochains exercices comment faire une gestion des erreurs beaucoup plus avancée pour pouir pouvoir gérer toutes ces qure figure dans ce cas-ci on a un script qui est fonctionnel avec le site qu'on a et qui nous permet de vérifier les catégories pour lesquelles le libraire devra mettre plus de livres en stock dans cet exercice cette fois-ci le but du libraire est d'enlever de sa page d'accueil les livres qui ne sont pas bien notés à savoir les livres qui n'ont qu'une seule étoile vous voyez ici sur la page d'accueil par exemple on a sur la première ligne uniquement déjà deux livres qui n'ont qu'une étoile on en a un autre a ici un autre ici à la troisème ligne et peut-être un autre oui deux autres également à la dernière ligne donc le but du libraire c'est de montrer sur sa page d'accueil uniquement des livres bien notés et donc on veut lui spécifier quel livre sur sa page d'accueil quand il publie des nouveaux livres sont problématiques donc le but ici ça va être de récupérer ces livres et de ne pas seulement récupérer le nom mais également l'identifiant de ces livres alors si je fait un clic droit sur le nom du livre vous allez voir que dans le lien vers le livre on a donc catalogue slash le nom du livre en Slog donc avec que des lettres minuscules et des tirets entre les espaces et on a après juste après ici un tiret du bas et un numéro à trois ou quatre chiffres les livres il y en a 1000 donc ça va jusqu'à 1000 si je prends le premier ici je crois que c'est le numéro 1000 voilà et on descend comme ça 1999 et cetera donc ils sont en ordre décroissant et nous ce qui nous intéresse c'est donc de récupérer en plus du livre cet identifiant puisque le but ici serait de passer par la suite automatiquement ces identifiants à la p du libraire qui lui permettrait d'exécuter ce script tous les jours pour enlever de son site de façon automatisée les livres les nouveaux livres qui ont été ajouté à sa librairie et qui ne comporte qu'une seule étoile en page d'accueil donc on a deux choses à récupérer ici déjà les livres qui n'ont qu'une seule étoile et ensuite sur ces livres spécifiquement le numéro l'identifiant ici qui est un nombre qui peut aller de 1 à 1000 donc si je vais plus loin sur les pages par exemple si on va sur la page 45 je vais aller ici sélectionner le dernier livre là vous voyez qu'on a un index de 100 10 on va aller encore un petit peu plus loin et on va voir si on a un padding ce qu'on appelle un padding donc par exemple est-ce qu'on a 0 101 0099 et cetera et vous voyez que ça ne semble pas être le cas donc on a un nombre ici un identifiant du livre qui va pouvoir comprendre de 1 à qure chiffres donc de 1 à 1000 et donc il va falloir récupérer cette information une autre chose qu'on va rajouter dans cet exercice c'est la gestion des erreurs puisque sur mon site on va considérer que le libraire il arrive en fait que quand le stagiaire mettre des nouveaux livres en place il oublie parfois des informations et que ETH bien des fois on n pas ici le nombre d'étoiles ou qu'on n pas l'identifiant ou d'autres choses comme ça donc par exemple là je reviens sur mon inspection on pourrait avoir une URL ici qui ne contient pas l'identifiant du livre et donc dans ce cas-ci je veux pouvoir notifier le libraire qu'il y a un problème non pas uniquement d'avertir le libraire qu'il y a des livres avec une étoile en page d'accueil mais également si jamais il y a le moindre problème que ce soit sur cet affichage donc si on n arrive pas à récupérer ces informations formtion si on a le moindre problème lors de l'exécution du script je veux pouvoir avertir le libraire et donc je veux faire planter le script pour que il puisse voir qu'il y a eu un problème donc là encore il y a plusieurs façons de faire je vous redirige vers nos deux articles l'article sur la méthode EAP et l'article donc de glossaire sur la méthode lbyl que vous retrouverez donc sur le glossaire de docstring donc lbyyl look before you leap qui consiste à utiliser plutôt des structures conditionnelles comme des IF à la place try accept et le E AFP easier to ask for forgiveness than permission qui lui à la place va utiliser des blocs try except plutôt que des IF else donc je vous laisse lire ces deux articles si vous voulez en savoir plus sur ces deux façons de faire moi vous allez voir que dans ma solution je vais privilégier les blocs try accept et donc je vous laisse avec toutes ces informations et on se retrouve tout de suite pour ma solution à cet exercice alors comme d'habitude la première chose qu'on va faire c'est importer les bibliothèques dont on a besoin donc request et beautiful soup comme d'habitude et on va refaire notre structure de base donc avec le main et le Main ici qui va appeler cette fonction main donc jusque-l rien de bien compliqué et je vais ici faire une requête toute simple vers la page d'accueil donc puisqu'on ne veut pas aller au-delà de la page d'accueil on veut juste vérifier cet URL donc je reprends l'URL de la page d'accueil et je fais une requête donc un request.get pour récupérer la réponse on fait un objet beautiful soup là encore rien de bien compliqué on va donner le response.text et on va mettre le html.parsur alors première chose qu'on va faire ici c'est gérer le C de figure dans lequel on a une erreur avec cette requête donc là ce que je peux faire c'est un response.raise for status et raise for status ça va me retourner une erreur me lever une erreur en fait pas juste la retourner si on va voir la définition de cette fonction vous allez voir que si on tombe sur un status code donc un un code de statut qui nous est retourné qui est entre 400 et 500 ou 500 et 600 on va faire un race donc lever une erreur hTTP Error qui hérite de request exception donc nous on va faire un bloc try accept pour vérifier dans quel cas on tombe sur cette erreur donc ce que je vais faire ici c'est un try pour essayer cette requête ensuite on fait un response.raace for status qui va lever une erreur si on a un code de statut qui nous est retourné entre 400 et 600 et là on va cibler donc le request exceptions request exception donc c'est l'exception qui nous indique qu'il y a eu un problème avec la requête et qu'est-ce que je vais faire ici et bien je vais lever de nouveau cette erreur donc vous allez voir qu'on va faire ça souvent dans ce script alors pourquoi on lève de nouveau cette erreur alors là il y a beaucoup d'étudiants dans ces cas de figure qui ne savent pas exactement ce qu'il faut faire qu'est-ce que je dois faire quand j'ai une erreur et bien j'ai envie de vous dire qu'en fait comme d'habitude il y a pas une seule bonne réponse puisque ça va dépendre de ce que vous voulez faire est-ce que dans ce cas-ci vous voulez considérer que il y a un problème avec la requête mais que c'est pas grave en fait on va aller sur une autre solution une solution à alternative on va par exemple utiliser une API potentielle qu'on pourrait avoir ou faire d'autres choses ou alors vous considérez que c'est foutu si on arrive pas à faire cette requête et bien ça ne sert à rien d'aller plus loin là dans ce cas c'est exactement ça qu'on va faire par contre on va quand même avertir le propriétaire de la librairie qu'on a eu un problème ça peut être en effet une information très importante pour la personne de savoir qu'on n pas réussi à faire une requête réussie vers son site il y a peut-être un autre problème sur le site qui fait qu'il n'est pas accessible au moment où on lance le script donc qu'est-ce que je veux faire ici je veux lever une erreur et je veux avertir l'utilisateur que il y a eu un problème donc là dans ce cas-ci je vais faire juste un print mais imaginez qu'on puisse faire un envoi d'email ou qu'on puisse appeler une autre API ou faire quoi que ce soit qui va déclencher une alerte quelque part dans ce cas-ci je vais juste faire un print donc je vais dire ici print et on va dire qu'il y a eu un problème lors de la requête il y a eu un problème lors de l'accès aussi tout simplement et qu'est-ce que je vais faire une fois que j'ai alerté la personne donc là avec un simple print qu'il y a eu un problème et bien on va va de nouveau faire un raise donc raise qui va lever une exception puisque là si je fais rien si je mets juste le print en fait la requête ne va pas réussir mais ensuite on va continuer avec le script et c'est ce qui nous est indiqué ici si j'affiche les avertissements là vous voyez qu'on a une variable local response qui est référencé avant un assignement donc le problème ici c'est que si on passe dans le except response ne va pas être défini on va essayer ça ici mais s'il y a une erreur on va en fait on ne va pas déclarer cette variable et par la suite si on fait juste mettre un print ici on va passer sur cette ligne et on va essayer d'utiliser response et donc on aura une erreur puisque ça va nous dire que response n'est pas défini je peux vous le montrer ici si je modifie par exemple HTTPS ici que je mets un une autre chaîne de caractère ça va provoquer une erreur et si je lance mon script ici vous allez voir que on a unbound local error donc ça veut dire que la variable ici n'est pas définie et on a également le print qui nous affiche qu'il y a eu un problème lors de l'accès au site donc là ce qui est bien important c'est après ce print de lever l'erreur de nouveau donc on va va faire pour ça un raise et on va indiquer qu'il y a eu un problème et on va lever la même erreur donc request exception donc request avec un S point exception request exception et là on peut également lier les deux erreurs ensemble si je fais juste ça ici je vais remettre dans mon HTTP des chaînes de caractères aléatoire pour que ça plante si je fais juste ça vous allez voir que quand je lance le script là on a un request exception error donc c'est normal et on a ici l'autre exception qui est un invalide schema et il n'y a pas vraiment de lien entre les 2 si par contre ce que je fais c'est que je récupère cette erreur on va la récupérer en faisant un As e et donc là e c'est une variable on pourrait mettre error on pourra mettre Patrick on peut mettre n'importe quoi en général vous allez souvent voir la lettre E qui va être utilisée et là ce qu'on peut faire c'est faire un from E donc là vous allez voir la différence c'est que si je relance le script là vous allez voir qu'il y a une différence en fait il nous dit que l'exception au-dessus donc cette exception invalid schema était la cause directe de l'exception qui suit donc l'exception qu'on a rajouté request exception qui nous indique qu'il est eu un problème lors de l'accès au site si j'enlève cette information ici vous allez voir que le message va être différent on aura pas de lien entre les deux donc si je relance là vous voyez que ça nous dit que lors de le du handling donc lors du processus qui a géré qui a fait cette exception en fait on a une autre exception qui est arrivée another exception donc vous voyez là il ne fait pas le lien entre les deux il dit ok là on a eu un problème avec cette requête donc on a levé une erreur avec le race for status qui a débouché sur cette request exception et nous ensuite on a levé une autre exception raise request mais quand on ne met pas le from E comme on l'a fait il y a quelques instants il considère ces deux erreurs comme séparé il y a eu un premier problème ici et on fait un autre problème ici donc là dans ce cas-ci c'est important de mettre as e et from E parce que on va dire que ce problème ici ce request exception il est lié directement à ce premier qu'on a provoqué en fait avec le race for status donc c'est bien important là quand on va faire du debug de voir que les deux problèmes sont liés on aurait pas le problème si on faisait juste un return puisque là si je relance le script et bien on ne va pas lever une erreur on aura juste le print qu'on a fait et on a juste le script qui continue dans ce cas-ci qui fait juste un return mais on ne lève pas une nouvelle exception donc vous voyez il y a différentes façons de gérer les choses on peut la gérer avec un try except en disant en cas d'erreur on fait quelque chose et on continue le script donc soit on le continue là avec un return ou alors comme je vous disais on peut faire quelque chose d'autre on peut dire ici comme je vous disais aller chercher les informations à partir d'une API ou quoi que ce soit d'autre là dans ce cas-ci nous ce qu'on souhaite c'est pas continuer comme si de rien était c'est on veut vraiment qu'il y ait une erreur on veut également avertir la personne donc c'est pour ça que là on fait le print et on relève l'erreur mais en indiquant donc avec le as e et le from E qu'on veut bien lier les deux informations ensemble et le E ici également il va contenir l'erreur si jamais vous voulez le mettre dans votre print vous pouvez très bien donc faire un f string ici je mets un F et on peut dire ici avec des accolades qu'on va mettre l'erreur à l'intérieur de notre message d'erreur et si je relance le script vous allez voir que cette fois-ci donc on a bien le le message qui nous dit que cette erreur a provoqué l'erreur juste en dessous et là on a bien donc le message il y a eu un problème lors de l'accès au site no connection adapters were found for et tout ça et donc ça on peut comme ça envoyer ce message à quelqu'un qui est chargé de la maintenance du site pour l'avertir qu'il y a eu un problème lors du scrapping du site donc moi je vais laisser ça comme ça là comme ça on a une gestion bien faite des erreurs selon le cas de figure là encore une fois je le précise de ce que je souhaite faire et là vous voyez que l'avertissement sur response a disparu puisque si jamais on ne récupère pas l'objet response on ne va pas plus loin on fait planter le script et donc on n jamais on aura jamais le problème d'arriver ici avec un response qui n'est pas défini ce que vous pouvez faire aussi c'est mettre ce code dans un else le else ne sera exécuté que si le try a réussi donc là c'est à vous de voir ça peut être plus explicite de dire que ce code en fait dépend directement de la réussite de celui-ci c'est plus clair avec un else après ça fait des niveaux d'indentation en plus forcément donc ça à vous de voir moi je pense que là comme j'ai mis un raise et que j'ai juste ce cas ce cas de figure qui est pris en compte je je vais juste mettre tout ça à la suite puisqu'on va voir pas mal de code qui va continuer après ça après le après la récupération de la requête donc ici qu'est-ce que je fais je récupère mon soupe comme d'habitude à partir du response.text et ce qu'on va faire c'est récupérer les éléments qui n'ont qu'une seule étoile donc si je retourne sur mon site on va refaire un petit inspect avec un clic droit on va essayer de voir qu'est-ce qui nous permet de vérifier qu'un élément n'a qu'une étoile donc là on voit que on a même sur un élément qui n'a qu'une étoile on a quand même cinq balises i ici donc on va pas pouvoir compter le nombre de balises pour voir combien il y a d'étoiles par contre si on remonte sur le P là on voit qu'on a une classe star rating et que on a un mot en toute lettre qui nous indique le nombre d'étoiles qu'on a si je vais voir sur l'élément par exemple qui a trois étoiles ici on voit que là on a three qui indique qu'on a bien trois étoiles donc on va pouvoir se baser là-dessus on va pouvoir tout simplement chercher les éléments qui contiennent ces deux classes donc je vais faire un contrôle F pour vérifier là on voit qu'on a un résultat sur 6 et si je me souviens bien on avait effectivement vu qu'il y avait à peu près 6 livres je vais les compter là on en a de sur la première ligne 3 4 5 et 6 euh oui 5 et 6 c'est ça et si on les fait défiler effectivement on devrait arriver sur tous ces éléments donc effectivement ça semble être suffisant pour pouvoir vérifier le nombre d'éléments qui ont une seule étoile donc ce que je vais faire c'est récupérer dans une variable que je vais appeler par exemple one St books ces éléments avec un select on va faire soup point select là encore on pourrait faire un find all à la place je vais rester sur l'utilisation du Select et qu'est-ce qu'on va faire et bien on va vérifier les classes point St rating et point one donc là on vérifie bien les deux qu'on est à la fois le star rating et à la fois le point one on met tout ça on n'oublie pas la majuscule ici sur le One et on va vérifier déjà ce que ça nous donne donc je vais faire un print de One Star book en fait on va même faire un print de la longueur de oneestar book et normalement ici ça devrait nous retourner 6 je vais également remettre en forme mon HTTPS pour pas qu'on ait d'erreur je relance et là on a bien 6 qui est affiché donc c'est exactement ce que on s'attendait à avoir maintenant qu'est-ce qu'on va faire on va vouloir récupérer comme je vous disais on arrive à la deuxième partie on va vouloir récupérer l'identifiant de ces livres pour pouvoir le passer un script qui fera automatiquement le travail de les enlever de la page d'accueil donc l'identifiant il est dans l'URL si je me souviens bien on va voir ici effectivement on a le 999 ici alors je vais voir s'il est pas ailleurs quand même on va essayer de chercher 999 et il est effectivement un autre endroit donc on a le le a ici qui correspond à l'image et on a le a du H3 donc moi je suis sur le star rating ici je je pense que je vais alors là on peut aller dans les deux directions en fait on peut soit remonter à l'élément parant donc le image container à partir de cet élément P pour euh récupérer ensuite l'URL à partir de là ou alors descendre et récupérer le H3 qui contient le euh le a ici et je pense que je pense que je vais plutôt me diriger vers le H3 parce que j'ai plus d'informations intéressantes sur l'image ici j'ai il faudrait que je récupère si je veux récupérer en fait le titre que je récupère également l'image et ensuite le l'attribut alt alors que avec le H3 3 si je veux récupérer ici le le titre en fait je peux récupérer le texte je peux récupérer l'attribut TITLE directement à partir du lien donc j'ai plus d'ination ici au même niveau donc ce que je vais faire c'est aller au prochain élément et je vais préciser aussi mon code puisque là en fait j'ai mis euh directement tous les éléments qui peuvent contenir star rating one je vais préciser en mettant le P ici puisqu'on voit que sur le sur cet élément ici c'est un élément de paragraphe donc ça va me permettre de vraiment être beaucoup plus spécifique sur les éléments qui contiennent ces cl class c'est toujours bien là on a vu que c'était uniquement sur les livres mais si jamais par la suite je sais pas on rajoutait enfin le le libraire rajoutait un élément avec ses classe sur par exemple un div qui contiendrait le la note moyenne de tous les livres de la bibliothèque et bien si on ne spécifie pas avec le P ici ça irait récupérer tous les éléments que ce soit des div des liens peu importe là on spécifie bien qu'on veut aller chercher le paragraphe donc maintenant que j'ai ça j'ai une liste en fait donc une liste de nœuds ici dans mon soup je vais pouvoir boucler dessus puisqu'on va vouloir chercher sur chaque livre l'ID identifiant du livre donc on va dire pour book in one star books et ici ce que je vais faire c'est utiliser le find next donc on va faire un print de book.f Next vous allez voir que find next ça permet de chercher le prochain élément dans la hiérarchie à partir de là où on est donc là on va être sur le P ici le prochain élément qui va correspondre à ce qu'on va donner comme élément ici donc là dans ce cas-ci on va chercher 1 H3 et ça va nous trouver le prochain H3 qui est après le rating ici donc je vais vérifier qu'on a pas d'autes H3 ici mais ça semble pas être le cas ici on a des i pour les les icônes de des étoiles et après directement après ici on a le H3 donc je veux dire find next on va récupérer le prochain H3 je vais lancer le script avec le print pour voir ce que ça donne et là voilà on récupère bien donc le H3 avec le lien et à l'intérieur de ce H3 et bien du coup je vais faire on peut faire un find on pourrait faire le Select là encore je vais faire juste un find pour trouver l'élément unique là on en a qu'un on a qu'un seul lien donc c'est ce qu'il nous faut donc je relance le script pour vous montrer là on va descendre on arrive au niveau du du a et ce que je veux moi c'est récupérer le le href ici l'attribut href donc là je vais faire un crochet avec le nom en chaîne de caractèr de l'attribut que je souhaite récupérer et on va voir tout de suite après comment on va pouvoir gérer les erreurs pour l'instant je récupère les informations et là ça fonctionne on récupère bien le l'URL en fait de chaque livre et nous ce qu'il va falloir faire c'est par la suite récupérer donc ce numéro donc pour l'instant on va se concentrer sur la gestion d'erreur et par la suite on va voir comment on peut récupérer cet identifiant à l'intérieur de l'URL donc là ce que je vais faire c'est créer une variable on va l'appeler book link par exemple et on va provoquer en fait les erreurs qui peuvent arriver Paris que là il y a beaucoup de choses qui sont enchaîner à la suite on a le find next on a le find et ensuite on a les crochets ici pour récupérer la valeur de l'attribut alors il y a plein de choses qui peuvent ne pas fonctionner ici et pour vérifier quel type d'erreur on a et les récupérer avec un bloc try accept il faut provoquer ces erreurs pour voir quel type d'erreur on peut avoir on peut également les deviner là dans ce cas-ci quand on a des crochets comme avec un dictionnaire ça va être probablement un quiy erreur mais le mieux c'est de provoquer ces erreurs pour voir les cas de figure qu'on peut avoir et les gérer on pourrait également adopter une autre approche l'approche lbyl look before you leap qui serait un peu plus verbeuse ici puisque'en fait il faudrait décomposer chaque élément donc par exemple commencer par le find next vérifier si on a quelque chose ici si c'est le cas donc faire un IF if donc si on a quelque chose ici on continue avec le find si on a quelque chose avec le find on continue avec le href et ainsi de suite moi je préfère ici adopter le EAP donc c'est plus facile de demander euh pardon que de demander la permission donc en gros on va faire toute cette ligne ici on va faire tous ces éléments à la suite et on va gérer les cas de figures qui peuvent arriver donc on va y aller un petit peu bourrin on va dire ok essaie de faire cette ligne si ça marche tant mieux ça veut dire qu'on a récupéré le lien et par contre s'il y a eu tel type d'erreur alors tu V dire ça s'il y a eu tel type d'erreur tu vas faire ça et on va gérer ça donc avec un bloc try accept donc je mets le try ici j'essaye tout ça ici et je vais mettre un except et là l'erreur que je vois la plus la plus souvent qui est une erreur très très classique des déb débutant c'est de faire un block try except simple comme ça et par exemple ici de mettre un continue donc de dire bon si si on a pas réussi à faire ça on continue le problème de ça c'est qu'on va masquer toutes les erreurs donc là si je lance le script je vais faire un print de booklink ici pour voir que on va dans ce cas si bien récupérer les liens donc je lance ok ça fonctionne on a les liens par contre imaginez que je change là je mets un H4 avec un script comme ça en fait on va pas avoir les erreurs on aura rien ici dans le output mais on a pas d'erreur donc là si on met un script comme ça le libraire pourrait se dire bon bah en fait ça va je n'ai pas de L avec une seule étoile sur ma vitrine donc je peux continuer ma vie tranquillement le problème c'est qu'ici en fait on voit bien que ce n'est pas le cas il y a des livres qui n'ont pas le nombre d'étoiles suffisant mais comme on a masqué les erreurs ici avec un except et un continue on ne voit pas le problème donc là ce qu'on va faire comme je vous disais c'est à la place vérifier quelle erreur on va avoir donc je vais provoquer ces erreurs alors qu'est-ce que je vais faire ici à la place du except on va récupérer toutes les exceptions pour commencer et on va refaire juste un raise de exception donc ça va permettre à avec le exception ici c'est l'erreur la plus générique qui va couvrir toutes les exceptions possibles en fait à part deux exceptions si je me souviens bien qui sont des exceptions qui sont provoqué volontairement donc quand on va par exemple interrompre le script si je lance le script et qu'ensuite je fais un contrôle C dans le terminal ça va provoquer un key error quelque chose qui bord d'erreur si je me souviens bien et donc c'est des des erreurs volontaires mais toutes les autres erreurs des erreurs voilà qu'on pourra avoir avec des attributs des qui erreur des value erreur attribut erreur et cetera ça va être récupéré par cette exception ce qu'on peut faire aussi c'est enlever pour l'instant le bloc try accept et juste remettre ces lignes avec le l'indentation lancer et là on va provoquer cette erreur donc on voit bien ici qu'on a un attribute error mais c'est un petit peu pénible de devoir enlever notre notre bloc ici try except qu'on a commencé à faire donc à la place je vais juste faire except exception et refaire un race d' exception donc là si on lance on va voir notre notre exception qu'on a levé à la fin et si on monte un petit peu on voit l'exception qui a provoqué cette autre exception donc c'est ici un attribute error donc l'attribute error c'est en fait quand on va faire un find puisque là là le find next ne va rien trouver donc ici qu'est-ce qu'on va vooir comme résultat en gros un non et donc c'est comme si on faisait non point find et c'est exactement ce que ça nous dit ici l'objet non n'a pas d'attribut find donc là on va pouvoir gérer cette erreur précise on va dire accept attribute error et comme vous vous souvenez on va faire la même chose que auparavant c'est-à-dire qu'on va dire que cette erreur donc l'erreur qu'on va lever ici découle de l'erreur d'attribut erreor ce qu'on va faire c'est juste entre-temps faire un print et dire par exemple ici impossible de trouver la balise euh H3 ou la balise a et donc là j'ai mis H4 pour provoquer l'erreur mais après on remettra la balise H3 et si jamais donc on a cette balise H3 ou cette balise a qui sont inexistante ça veut dire qu'on aura un problème et et en fait non je j'ai pas besoin de mettre la balise a si je me trompe pas ici puisque si on a un problème donc si on trouve quelque chose sur le H3 et que en fait on a un problème ici ça va être un autre problème donc avec les crochets ici comme je vous ai dit je pense que ça va être un key error euh mais en fait on pourrait oui le le find ici pourrait nous retourner un non aussi et donc dans le cas de non href je suis pas sûr ce que ça va nous nous retourner donc là encore je vais lancer le script et dans ce cas-ci c'est un type error donc vous voyez qu'on a une autre erreur à gérer donc là la première erreur qu'on peut avoir qu'on a identifié c'est sur ce segment ici qui serait potentiellement égale à non et dans ce cas-ci on a un attribute error si par contre on a quelque chose sur le find next mais que c'est après ici qu'on se retrouve avec le find qui nous retourne non là dans ce cas-ci c'est un type error donc là je vais pouvoir rajouter mon exception ici et je vais refaire j'oublie pas de faire un raise de attribute error from E ici et on va gérer donc le deuxième cas de figure on va faire un accept type error as e là on va dire queon a donc un problème donc on va dire alors là j'ai mis un f string mais j'en ai pas besoin donc on va dire impossible de trouver la balise a à l'intérieur du H3 et là donc on va tester on va refaire un raise de type error from E et là donc pour provoquer le problème je va mettre par exemple ici une balise qui ne fait pas de sens je relance et là on a bien le type error donc Imposs possible de trouver la balise a donc je vais mettre peut-être d guillemets pour que ce soit plus clair que c'est la balise a comme ça et la balise H3 ici aussi je vais mettre comme ça la balise H3 donc là vous voyez qu'on a les deux premiers cas de figure qui sont correctement gérés on va mettre H4 ici là on a bien le attribute error avec le print voilà qui est quelque part ici donc impossible de trouver la balise H3 si je remets mon H3 et que je relance là on va avoir cette fois-ci le type error impossible de trouver la balise a et le dernier donc là on va mettre autre chose on va mettre une autre balise qui ne sera pas trouvée je relance et là dans ce cas-ci qu'est-ce qu'on a on a un key error donc le Ky error puisque comme je vous disais en fait ici on aura quelque chose donc on va avoir le nœud qui correspond au lien mais on va pas réussir à récupérer cet élément on peut faire un point get comme je vous disais la différence c'est que le point get ne va pas lever d'erreur s'il n'y a rien donc si je relance là vous voyez qu'on a juste non donc c'est là encore une fois exactement comme avec les dictionnaires si on met get on a pas d'erreur si on met les crochets donc on aura une erreur et moi c'est ce que je préfère c'est provoquer dans ce casci cette erreur dans le cas où la tri attribut n'est pas à l'intérieur de ce a donc si on avait un lien vide sans attribut href donc je vais rajouter cette exception ici except et dans ce cas-ci qui error as e et là on va faire un print on va dire euh impossible de trouver l'attribut href et on refait un raise de Key error from E donc là voilà vous voyez ça fait beaucoup de choses mais on a tous les cas de Figur qu'on a identifié qui sont gérés on a bien le key error ici si je remonte impossible de trouver l'attribut href et donc vous voyez ça fait beaucoup de lignes de code mais là au moins tous les cas de figures sont géré avec à chaque fois un print qu'on pourrait modifier comme je vous dis pour faire par exemple un fichier de log ou pour envoyer un avertissement à quelqu'un pour qu'il puisse vérifier qu'il n'y a pas de problème sur le site et je me répète mais je le précise encore une fois c'est à vous de décider ce que vous souhaitez faire avec ces erreurs vous n'êtes absolument pas obligé de refaire un raise ici vous pourriez vous dire ok c'est pas grave je n'ai pas trouvé l'information que je veux ici donc je n'ai pas trouvé le href mais on va essayer d'autres cas de figure on va pas faire de raise on va juste continuer le script en vérifiant d'autres choses en essayant de trouver l'information ailleurs sur sur la page par exemple là dans ce cas-ci moi je veux vraiment que ça provoque une erreur et que ça m'affiche un texte avec le print dans le cas où ces informations ne sont pas trouver donc on touche au but là si je fais un print dans ce casci de book link après ça donc je vais enlever mon print ici je vais le faire après mon block try je relance et là normalement je crois que j'ai tout remis comme il faut c'est bien on a donc tous les liens des livres qui n'ont qu'une seule étoile donc là ce qui reste à faire c'est de trouver cette élément ici qui va contenir de 1 à quatre chiffres on l'a vu les ID donc les identifiants vont de 1 à 1000 et donc là ce qu'on va faire nous c'est utiliser une expression régulière pour récupérer cela donc pour utiliser les expressions régulières il faut importer le module qui va nous permettre de les faire donc pour ça on le met tout en haut de notre script ici on va faire import re donc regular expression on va le mettre avant request et beautiful soup et SP paré d'un espace puisque le module re fait partie de la librairie standard de Python et ensuite request et beautiful soup ce sont des bibliothèques qu'on a importé qu'on a installé en fait avec PIP en plus donc qu'est-ce que je vais faire ici je vais vouloir chercher dans mes URL ici l'identifiant alors là encore il y a plein de façons de faire on pourrait passer à travers chaque caractère de la chaîne de caractère et ne pas utiliser le module rej mais ça serait peut-être un petit peu lourd de devoir faire cette boucle à chaque fois on peut essayer de supprimer tous les caractères qui ne sont pas juste des nombre mais ça va poser problème par exemple avec ce dernier exemple qui est très bien placé puisqu'on voit que là on a best science fiction entre 1800 et 1849 donc là on a le le dernier élément le dernier nombre qui est bien l'identifiant du livre mais là on a d'autres nombres qui ne sont pas liés à l'identifiant du livre donc là il faut trouver un motif un pattern comme on dit en bon en bon Fran anglais un pattern qui va être unique qui va permettre d'identifier cet identifiant comme je vous l'ai dit ici on a le Slug les slugs ça va contenir toutes les lettres sans les caractères spéciaux tout en minuscule et les espaces vont être séparés par un tiret du milieu et nous qu'est-ce qu'on voit ici à la fin ça a été bien fait on a un tiret du bas qui sépare en fait le nombre ici de du reste de de l'URL alors l'autre façon de faire sans les réject ça serait de faire des splits donc de faire un split sur ce tirer du bas un split sur le slash et de récupérer ce qui est au milieu c'est une première façon de faire qui peut être assez intéressante qui évite d'utiliser les expressions régulières qui peuvent être un petit peu compliquées moi ce que je vais faire c'est donc utiliser à la place ce module reux et pour ça on va utiliser donc une expression régulière qui va chercher un tiret du bas et une suite de 1 à qu nombres précisément donc entre 1 et 4 1 2 3 ou 4 et on va chercher précisément cette suite dans la chaîne de caractère donc soit un tiret avec qu'un nombre soit un tiré avec deux nombres de chiffres en fait trois ou quatre chiffres donc cette expression régulière ici je vais la faire déjà dans une chaîne de caractère pour cibler les nombres on va faire/ash d pour cibler le tirer du bas on met tout simplement le tirer du bas et pour cibler un nombre d'occurrence entre 1 et 4 on va mettre un élément entreacolade ce qui va nous permettre ici les accolades de spécifier le nombre d'occurrences qu'on souhaite avoir et pour spécifier le nombre d'occurrence on met 1,4 comme ceci donc ça peut aller de 1 à 4 c'est-à-dire que si on a un seul nombre c'est bon si on en a deux c'est bon si on en a trois c'est bon et si on en a quatre également c'est bon et donc on a ici toute notre expression régulière vous voyez que ça peut faire un petit peu peur si vous êtes pas habitué à aller voir des formations sur les expressions régulières on en a sur doc strring mais voilà vous voyez que là dans ce cas-ci c'est une expression régulière assez simple donc c'est pour ça que j'aime bien l'utiliser et je vais mettre un r devant pour que ce soit bien un RW string donc pour qu'il n'y ait pas de caractères qui soit interpréter différemment ça c'est un classique aussi des expressions régulières et ensuite je vais donner tout ça à la méthode find all du module re donc find all qui va me permettre de trouver toutes les occurrences de ce motif à l'intérieur de ma chaîne de caractère et je vais récupérer ça pour l'instant dans une variable que je vais appeler book ID et on va lui passer ensuite en deuxième argument la chaîne de caractère à travers laquelle on souhaite chercher donc dans ce cas-ci ça va être booklink donc je vais pas aller plus loin je vais faire un print de book ID et on va voir ce que nous retourne ce findall donc là on va chercher toutes les occurrences de cette expression régulière dans booklink je lance le script et on voit ce que ça donne et là vous voyez que magie on a a bien une liste avec en premier élément l'identifiant donc qui contient ici le tirer du bas donc il va falloir l'enlever bien sûr mais on a bien réussi à trouver ce qu'il nous fallait là encore on va faire de la gestion d'erreur puisque on pourrait avoir des chaînes de caractères qui ne contiennent pas cette information donc je vais vous montrer là encore on va provoquer cette erreur pour l'instant on va juste résoudre ce ce petit problème puisque là on a une liste avec un élément et on a le tiré du bas donc ce que je vais faire c'est prendre le premier élément de la liste là encore j'y vais en mode bourrin c'est-à-dire qu'on considère que tout marche bien qu'on a tout ce qu'il nous faut on récupère le premier élément et ensuite on va refaire un crochet et faire un de points pourquoi on fait un de points ici donc là encore on fait un slice ça va être pour récupérer tous les éléments à partir du deuxième caractère donc on évite le premier et on prend tous les éléments à partir du deuxème donc ce que je vais faire pour tester tout ça pour vérifier que ça fonctionne bien c'est refaire un print de mes URL donc de book link ici et je vais les mettre dans une liste pour juste vérifier avant que ça fonctionne bien donc j'ai tout ça je vais en prendre un ici donc le premier et je vais recréer en fait ma variable ici pour en fait défaire ce qu'on a fait ici donc on pourrait le faire en dehors de cette fonction pour ne pas faire un request à chaque fois d'ailleurs ce serait peut-être un peu plus un peu plus simple donc je vais le faire à la place du main ici je vais créer une variable donc qui est tout simplement cette chaîne de caractère je vais me faire un petit peu de place aussi et on va faire notre find all pour vérifier quel type d'erreur on peut avoir donc là si je fais un print de book ID je lance mon script qu'est-ce qu'on a on a bien 999 donc ça fonctionne là dans ce cas-ci on a exactement le cas de figure qu'on souhaitait avoir c'est-à-dire une une URL valide avec le tiret du bas 999 on récupère l'identifiant et ensuite comme je l'ai dit on peut envoyer cet identifiant à une API qui va se charger de retirer ce livre de la page d'accueil maintenant qu'est-ce qui se passe si par exemple ici on a CIN éléments je vais mettre 44 devant je relance qu'est-ce qui se passe on a 4 4 99 donc notre expression régulière fonctionne puisqu'on a dit qu'on voulait de 1 à 4 donc là ce n'est pas un identifiant qui est valide selon notre expression régulière si jamais on souhaitait adapter notre expression pour qu'elle fonctionne avec des bibliothèques qui pourrai comp conttenir par exemple 150000 livres dans ce cas-ci on peut enlever le 4 et dire qu'il faut qu'il y en ait de 1 à un nombre infini donc là vous allez voir que si je relance le script cette fois-ci on va bien récupérer tous les nombres à l'intérieur de cette chaîne de caractère donc 44999 dans ce cas-ci on avait que 1000 éléments dans notre bibliothèque mais je pense que ça peut être bien de prévoir et se dire que par la suite on pourra avoir par exemple 10000 livres sur la bibliothèque et donc on va enlever le 4 pour gérer ce cas de figure imaginons maintenant que je n'arrive pas à trouver une occurrence de ce que je cherche donc par exemple à la place du tirer du ban on va mettre un tiret du milieu je relance et là qu'est-ce qu'on a on a notre première erreur index error list indexed out of range et avec les dernières versions de Python en plus on a un petit dessin ici qui nous indique très clairement où est le problème ce qui n'était pas le cas avec les versions antérieures à la 3.11 ou 3.12 si je me souviens bien les développeurs de Python ont ajouté plein de petites choses comme ça assez sympas avant on nous disait juste en fait list index out of range et on savait pas en fait si l'erreur était ici par exemple ou sur le deuxième splice qu'on a ici donc là c'est très clair que que le problème se situe ici et donc qu'est-ce qu'on a comme problème on a un problème de index error donc on va pouvoir retourner ici dans notre fonction et gérer ce 4 figure donc je vais enlever mon booklink je vais décommenter ça et je vais faire un try except vous commencez à connaître donc try except donc except en cas de index error as e on va dire print donc là encore on peut envoyer une alerte on va dire impossible de trouver l'idée du livre voilà et on va refaire un raise index error from E et je vais enlever le 4 que j'avais ici donc voilà pour cette erreur qu'on a géré et avant de terminer on va réfléchir à ce deuxième élément ici est-ce qu'on peut avoir une erreur dans ce cas-ci alors soit on n pas réussi à récupérer quelque chose ici et dans ce cas-ci l'erreur va être sur le crochet zéro ici donc le index erreur qu'on vient de faire si par contre on arrive à récupérer quelque chose normalement les SPLI ici ne devraient pas poser de problème parce que même si on récupère en fait une chaîne vide ou une chaîne qui comprend plein d'autres choses le slice va juste récupérer tout ce qu'il y a on va faire un test ici j'ai un petit doute mais si je mets une chaîne de caractère comme ça qui est videite par exemple je vais faire un print de tout ça juste pour vérifier j'enlève le book ID je relance là vous voyez qu'on a pas d'erreur je peux mettre n'importe quoi ici je peux mettre 500 je peux mettre - 50 je peux mettre 50 - 50 à 60 on peut faire à peu près tout ce qu'on veut comme ça avec un slice même si peu importe ce qu'on a en fait ici je peux mettre une chaîne de caractère je peux mettre n'importe quoi à chaque fois vous allez voir qu'en fait on va on va voir un résultat et on aura pas d'erreur là si j'enlève aussi si je mets tout ça on va voir juste exactement la même chose si je mets un élément qui finit ici si je mets car 40 - 50 et cetera donc en fait on peut pas faire planter le le script ici peu importe ce qu'on récupère comme chaîne de caractère donc si on passe l'étape du index error donc si on n' pas d'erreur d'index ici avec le crochet zéro on va récupérer donc une chaîne de caractère puisque find all va nous retourner des chaînes de caractères et donc on pourra faire le slice à partir de ça donc après bien sûr on pourrait faire d'autres vérifications pour s'assurer avec notre API à laquelle on enverrait cet identifiant que l'identifiant est bien dans la bibliothèque et cetera mais là ça sort du cadre de cet exercice donc là vous voyez qu'on a un script qui est un petit peu plus long le cœur du script avec le request.get et ensuite les différents beautiful soup le Select le fin next ça représente peut-être quatre ou cinq lignes de code maximum mais là au moins ce qu'on a c'est vraiment quelque chose qui va être 100 % Bullet proof là encore comme on dirait en bon français c'est-à-dire qu'on va gérer tous les cas de figure qu'on a pu identifier pour avertir les personnes compétente du problème qu'on a eu lors du scrapping et donc dans ce cas-ci moi ce qui m'intéresse comme on l'avait dit c'était les book ID donc je peux faire c'est tout simplement une liste on va dire book IDS on va faire une liste vide et là à la fin ici et bien je vais mettre dans le else là on va le lier on va faire bookids. append book ID donc là je le mets dans le else pour bien qu'on comprenne que c'est lié à ce try donc là le else en fait va être exécuté si on a aucune erreur qui se passe donc si on passe dans le try on va également passer dans le else après être passé dans le try et à la fin je vais tout simplement faire un return de books de book IDS comme ceci et on va mettre des annotations de type pour terminer hop pour que ce soit bien clair on va dire qu'on retourne une liste de nombre entier donc si je relance mon script je vais faire un petit reformat de tout ça vous voyez qu'on a une quarantaine une bonne quarantaine de lignes de code là on n pas refactoré on a tout fait dans une seule fonction on verra dans le dernier exercice qui va être pas mal plus long comment on peut organiser bien mieux tout ça mais pour l'instant je vais rester avec une seule fonction ici on s'est plus concentré sur la gestion des erreurs donc je relance et on va voir si on a bien ce que je veux donc là j'ai pas fait de print bien sûr donc on ne voit rien d'affiché mais si je relance on a bien les identifiants qui sont des chaînes de caractères on pourrait là encore les convertir en in si on souhaitait en faisant une petite conversion int ici pour relancer voilà et là on aurait tous les identifiants en nombre entier des livres qui posent problème qu'il faudrait enlever et ça serait même plus raccord avec ce que j'ai mis ici puisque j'ai dit que je retournais une liste de nombres entier donc si je ne convertis pas en int ici je vais avoir une différence avec mon annotation de type ici qui indique qu'on retourne bien une liste de nombres entiers et là avant de terminer je viens de me rendre compte ici ici qu'on peut simplifier grandement cette expression régulaire en mettant un plus le plus ça va être 1 à l'infini donc ça revient en fait exactement au même que de faire les accolades avec le 1 viru et rien après donc j'avais commencé avec le 1,4 donc là ça avait du sens mais si on met 1 à l'infini on a un caractère spécial pour ça qui est le plus qui correspond donc à une occurrence jusqu'à l'infini donc voilà pour cette correction de l'exercice qui consistait à récupérer les identifiants des livres notés une étoile sur la page d'accueil de la librie [Musique] dans les parties qui vont suivre on va réaliser un exercice ensemble qui va être un peu plus avancé que ce qu'on a vu précédemment vous pouvez bien sûr essayer de le faire de votre côté mais je vais aussi vous montrer comment le faire de façon accompagnée avec des vidéos détaillées pour chaque étape et on va également dans ce script voir comment réaliser une séparation des responsabilités très importantes avec plusieurs fonctions qui vont chacune avoir un rôle très précis et qui vont pouvoir également gérer les erreurs potentiels qui peuvent' arriver lors de l'exécution de ce scrapping on va également mettre en place un système de logging pour écrire sur le disque des fichiers de log qui vont rendre compte de tout ce qui s'est passé pendant l'exécution du script autant du côté de ce qui a bien marché que du côté des erreurs pour pouvoir avoir une trace de ces erreurs et les régler par la suite dans le cas où celle-ci arrive pour cet exercice l'objectif est assez simple il s'agit de récupérer le prix total de la valeur de l' bibliothèque par exemple ici on voit que on a le prix du premier livre du deuxième livre et cetera mais ce qu'il faut savoir c'est que on a plusieurs livres en stock pour avoir cette information il faut se rendre sur la page de chaque livre et vous allez voir que on a l'information ici et également ici en bas de la page qui nous indique que il y a dans ce cas-ci 22 exemplaires de ce livre en stock donc ce qu'il faut faire dans ce cas-ci pour avoir la valeur de ce livre c'est multiplier le prix du livre par le nombre de livres en stock donc 51.77 x 22 et il faut faire ça pour tous les livres livre de la bibliothèque donc tous les livres que vous avez ici il y a une cinquantaine de pages il faut récupérer la multiplication de ces données donc le prix multiplié par la quantité en stock pour tous les livres de la bibliothèque pour avoir ainsi une idée de la valeur totale de la bibliothèque donc vous voyez que l'objectif est assez simple et maintenant il y a plusieurs façons de faire donc voilà pour les instructions donc je vous laisse regarder comment vous pouvez faire ça vous pouvez faire un script très simple ou essayer déjà de faire un script avec une bonne gestion des erreurs et un logging si vous voulez voir comment on peut faire ça Ave vous n'avez pas envie de trop vous casser la tête vous pouvez continuer avec ma solution qui arrive tout de suite dans la prochaine partie pour réaliser ce projet j'ai décidé de vous présenter deux nouvelles bibliothèques qui sont plus récentes qui sont également plus performantes notamment pour l'une d'entre elles qui va remplacer l'utilisation de beautiful soup alors dans cette partie je vais vous montrer ces bibliothèques comment les installer et également comment les utiliser de façon sont assez basique mais vous allez voir que le fonctionnement en tout cas pour selectol AX qui est la bibliothèque qui va remplacer beautiful soup est assez similaire à ce que l'on a vu avec l'utilisation des sélecteurs CSS donc l'utilisation de ces bibliothèques est assez simple ce qu'il faut vraiment apprendre à maîtriser finalement comme dans tout avec le scrapping c'est arriver à sélectionner les bonnes informations en fonction du HTML et également du CSS de la page donc pourquoi je vous montre ces bibliothèque pour le cas de selectolx parce qu'elle est beaucoup plus rapide vite que beautiful soup et dans cet exercice on va faire beaucoup d'analyses de code HTML et selectolx va de 10 à 20 fois plus vite que beautiful soup bien sûr pour cet exercice vous pouvez quand même le faire avec beautiful soup si vous souhaitez ça va pas changer grand-chose là encore c'est vraiment juste quelques lignes de code à changer donc pour installer ces bibliothèques on va ouvrir un terminal et on va utiliser tout simplement PIP avec PIP install donc la première c'est selectax comme ceci tout en minuscule je valide avec entrée dans mon cas je l'ai déjà installé donc elle est déjà dans dans mon environnement virtuel je vais également installer donc l' Guru qui est l'autre bibliothèque que je vais installer là encore avec PIP install donc PIP install log Guru c'est juste une bibliothèque qui va nous permettre de créer des logurs plus facilement puisqu'il y a pas mal de choses qui sont un petit peu difficiles à retenir je trouve avec le module logging là encore si vous êtes à l'aise et que vous souhaitez utiliser le module logging donc sans avoir aucune dépendance puisque le module logging est disponible dans la bibliothèque standard de Python vous pouvez très bien bien le faire donc je vais vous montrer déjà l Guru donc je vais dire from L Guru import Logger vous allez voir que là encore ça va être assez semblable à ce qu'on fait avec le module logging la première chose que je vais faire c'est enlever le logger par défaut donc je vais faire logger.rove puisque je vais vouloir faire deux loger un premier loger qui va écrire sur le disque dans un fichier qui va être un fichier ici que vous voyez books.log et un autre loger qui va écrire directement dans le terminal pour qu'on puisse voir ce qu'il se passe quand on lance le script donc je vaux enlever le loger par défaut avec donc logger.remove et je vais en ajouter un autre avec logger.ad le premier argument qu'on va passer ici c'est le nom du fichier donc je vais l'appeler books. log tout simplement et on a pas mal d'options assez intéressantes notamment le fait de pouvoir faire une rotation du fichier à partir d'un certain moment alors la rotation ça va être avec l'argument rotation et on va donner en valeur une chaîne de caractère avec la taille qu'on ne souhaite pas dépasser donc si je mets par exemple 500 KB ça va faire en sorte que nos fichiers ne feront pas plus de 500 KB donc ça nous permet d'éviter d'avoir des fichiers trop volumineux je vous laisse aller voir la documentation de l Guru si vous voulez voir plus de paramètres disponibles vous avez également retention qui permet de dire qu'à partir d'un certain moment on souhaite ne plus conserver les fichiers de log donc on peut dire par exemple qu'au bout d'une semaine on souhaite passer à d'autres fichiers et supprimer les anciens qu'on avait là aussi ça peut être pas mal pour éviter d'avoir des fichiers qui grossissent trop et qui restent sur le disque et le dernier argument qu'on va mettre bien entendu c'est le niveau qui là ne va pas changer par rapport au module logging de Python donc dans notre cas on va le mettre en warning pour le loger qu'on va mettre sur le disque donc dans books.log c'est-à-dire qu'on ne veut afficher que les éléments qui vont vraiment poser problème on ne veut pas afficher tous les éléments d'information on veut juste dans le log pouvoir lire les problèmes avec donc warning avec error ou avec critical qui sont les trois niveaux à partir de warning donc warning qui signifie avertissement et on va ajouter un autre logueur donc pour écrire dans le terminal donc pour ça je vais importer le module 6 et je vais rediriger donc ce logger avec logger.ad vers le 6.stdr donc stdr c'est quoi c'est standard error donc c'est l'output dans lequel on va loguer les erreur qui va être dans le terminal et je vais mettre le level ici à info c'est-à-dire qu'on va afficher beaucoup plus de messages dans le terminal puisqu'on souhaite voir ce qui se passe quand on va exécuter notre script et pouvoir voir les différentes opérations par lesquelles on va passer ce qui n'est pas le cas du loger sur le fichier pour lequel on souhaite juste avoir les problèmes et maintenant pour selectolx on va utiliser donc le module selectolx et on a à l'intérieur un module parser et on va importer HTML parser donc le html parcur c'est exactement comme le beautiful soup quand on fait from BS4 import beautiful soup ça va être exactement la même chose c'est-à-dire qu'on va par exemple faire une requête alors je vais faire import request je vais aller chercher l'URL vers books to scrap et je vais vous montrer si on fait une requête donc si je fais r = request.get vers cette url on peut récupérer un arbre avec HTML parser alors généralement dans la documentation les exemples vous allez voir le nom de variable qui va être utilisé qui est différent qui est tree à la place de beautiful soup où généralement on voit soup donc moi je vais utiliser ces deux noms de varibl pour ces deux méthodes pour rester un peu près cohérent avec ce qu'on voit sur le net mais vous pouvez mettre n'importe quel nom de variable bien entendu donc avec HTML parser là encore c'est très facile on va lui passer rtexte et on a pas besoin de spécifier comme on le fait avec beautiful soup le parseur qu'on souhaite utiliser et avec beautiful soup du coup on l'a déjà vu on fait r.tex et on spécifie le parsur qu'on souhaite utiliser la plupart du temps html.parser donc ça ça va être vraiment identique les deux deux vont vous permettre d'accéder à un arbre qui va permettre par la suite donc sur soupe ou sur tree d'accéder à différents éléments de la page et ensuite pour récupérer des éléments avec select AX on va beaucoup passer par les selleecteurs CSS donc c'est un peu la même chose que ce qu'on avait vu avec le soup. Select et select one donc on va avir soup. Select et soup. select one avec beautiful soup qui nous permet de sélectionner tous les éléments ou un élément donc par exemple on pourrait récupérer tous les liens ou juste le premier lien qui est trouvé sur la page on pourrait faire la même chose avec le H1 ou n'importe quelle autre balise HTML et avec l'arbre on va faire tree. CSS et vous avez CSS et CSS first donc qui correspondent respectivement au Select et au select one donc là si je récupère le premier lien ici et le CSS force avec le lien ça va donner la même chose donc je va vous montrer on va faire un all links soup ici et un First link soup et on va faire la même chose ici avec all links tree et first link tree ici et je vais faire un print ou plutôt on va faire un dbug donc je vais mettre mon point de debug ici et je vais lancer le script en mode Debug et vous allez voir ce que l'on va récupérer dans ces quatre variables donc on a bien dans le cas de beautiful soup un set donc result set ici avec une liste en fait de nodede avec le tree on va voir le même nombre d'éléments donc 94 avec des noes ici et pareil donc avec first link soup on a ce qu'on appelle un tag qui correspond à l'élément qu'on va récupérer donc le premier élément et ici on a une node avec force link tree et vous voyez donc par exemple pour selectol AX on va voir les attributs donc par exemple pour accéder à l'attribut href qu'on aurait également avec le First link soup si on va voir dans atttrs ici donc pour attributes on va également pouvoir récupérer le href donc vous voyez c'est assez similaire il y a pas grand-chose de différent donc là encore je vous laisse aller voir la documentation de selectolx si vous choisissez de l'utiliser pour cet exercice sinon vous pouvez donc comme vous l'avez vu puisque vous êtes plus habitué avec beautiful soupueer avec beautiful soup moi dans la suite de cette formation je vais utiliser selector AX pour vous faire découvrir ce nouvel outil et pour pour que vous puissiez l'utiliser sur vos projets ça vous permettra de l'apprendre en pratiquant sur cet exemple et vous allez voir on fera des petits tests à la fin des petits benchmark que la différence est monumentale donc dans le cadre de cet exercice dans lequel on va scrapper des centaines voire des milliers de pages la différence est loin d'être négligeable dans cette partie on va préparer un petit cahier des charges de notre scrapping c'est quelque chose que je conseille très souvent aux étudiants que ce soit pour des scripts de scrapping ou des scripts Python en général c'est important avant de mettre les mains dans le code d'écrire un petit peu un plan d'attaque de ce qu'on va faire parce que ça peut grandement impacter les décisions que vous allez prendre par la suite et vous permettre d'éviter des erreurs ou de faire des choses qui ne seraient pas utiles et de partir dans la mauvaise direction surtout dans ce cas-ci dans lequel on a quand même un script qui nous attend qui va être assez conséquent donc c'est bien important de passer par cette étape personnellement je suis assez partisan de ne pas non plus aller trop dans le détail je vois souvent des étudiants qui ont des profs ou qui sont dans des écoles où vraiment ça va je trouve un peu trop loin on leur demande de faire des graphes de faire des des documents de 20 pages avant de commencer un script là on va pas aller jusque-là quand même moi je préfère rester quand même assez minimaliste et juste préparer un petit plan dans lequel dans ce cas-ci je vais indiquer les fonctions que je souhaite coder donc je vais ouvrir trois guillemets ici donc pour faire une chaîne de caractèrees multiligne et je vais indiquer ici les fonctions que je souhaite coder donc on va analyser un petit peu qu'est-ce qu'on peut faire qu'est-ce qu'on doit faire ici dans le cas de cet exercice ce qu'on veut c'est récupérer donc le prix total de la bibliothèque on a donc des livres qui sont disponibles en différentes catégories alors on pourrait se dire qu'on va aller dans chaque catégorie mais peut-être qu'il y a des livres qui ne sont pas dans une catégorie donc je pense que le mieux dans ce cas-ci vous voyez que sur ce site on a 1000 résultats et on a 20 livres par page et si on descend en bas on voit qu'ici on a un bouton Next qui nous permet de passer à la prochaine page donc on va on va analyser un petit peu tout ça on va regarder là je suis sur la page principale qui dispose d'une URL donc bookstoscrap.com/index et si je m'en vais sur la page 2 je vois que j'ai une URL qui change avec cette fois-ci une URL catalogue/page-2.html donc déjà la bonne indication c'est qu'on a un tiet 2 dans le nom de l'URL donc j'imagine que si je change le 2 pour un 3 je vais me rendre à la 3isème page donc c'est déjà une bonne indication on va en même temps faire une petite analyse pour voir les différentes techniques qu'on pourrait utiliser donc ce qu'on peut faire c'est soit en fait partir de l'URL donc on a une URL qui est différente pour la page 1 et pour la page 2 mais et c'est là que vous allez voir que c'est très important d'analyser la page si vous cliquez sur previews donc si vous n'allez pas trop vite et que vous essayez un petit peu de tester tout sur le site quand on clique sur previews et qu'on clique une deuxième fois pour revenir sur la première page on se rend compte et vous pouvez vous en rendre compte également en essayant de changer l'URL que la page 1 est également accessible donc la page d'accueil en mettant cette url donc page-1.html donc ça veut dire qu'on peut accéder à la première page soit avec cette URL qui va avoir un motif différents des autres soit on peut y accéder ici avec page-1.html donc là vous voyez déjà qu'on a deux façons de de faire cette navigation on peut soit partir directement de page 1 et changer juste le numéro donc faire 1 2 3 comme ça jusqu'à donc je sais pas combien de pages on en a 50 donc on peut aller comme ça jusqu'à 50 et j'imagine qu'à 51 on va se retrouver avec une erreur donc à 50 effectivement on arrive à la dernière page et à 51 j'imagine on aura une erreur 404 c'est exactement ça qui se passe donc là vous voyez deux choix soit on se dit ok j'ai 50 pages j'en aurai jamais plus et je vais juste faire une boucle for par exemple qui va itérer de la page 1 à la page 50 ça peut marcher le risque de ça c'est que si jamais la librairie change de nombre de pages si on a 51 page 52 pages il faudra adapter votre script donc moi ce que je vais préférer faire c'est utiliser ce bouton Next c'est-à-dire que je vais faire un script qui va partir de la première page et qui va à chaque fois chercher l'URL de la page suivante jusqu'à ce qu'il n'y ait plus de page à consommer donc en fait on va arriver jusqu'à la page 50 et arrivé à la page 50 il n'y aura plus de bouton Next et on va pouvoir utiliser cette condition pour pour s'arrêter en fait et pour dire que voilà on a parcouru toute la bibliothèque donc à partir de ça j'ai plusieurs informations que je vais prévoir et notamment plusieurs fonctions que je vais devoir coder donc on va avoir une fonction pour récupérer l'url de la page suivante alors je vais faire un petit peu de place pour qu'on voit bien tout ce que j'écrit sur une seule ligne donc déjà on va avoir une fonction à créer pour à partir d'une page récupérer la page suivante donc là ensuite on pourrait spécifier on pourrait spécifier qu'il faut récupérer à partir d'une page ou à partir d'une URL donc là c'est là où on va peut-être pas forc forcment trop rentrer dans le détail peut-être que ça c'est quelque chose qu'on va déterminer lors de l'implémentation donc je vais juste mettre en forme de question récupérer à partir donc du HTML directement ou de l'URL point d'interrogation donc on n'est pas encore sûr quelle méthode on va utiliser mais on sait qu'on va devoir récupérer cette url de la prochaine page ensuite pour calculer le prix d'un livre qu'est-ce qu'on doit faire si on retourne sur la page principale ici sur la page principal on a juste l'information du prix et le fait que le livre est en stock ou non mais on n pas la quantité de livre en stock pour ça ça il faut se rendre sur la page de livre et là on va voir la quantité à deux endroits ici donc s'il est en stock on a inst stock et le nombre d'unités disponible et on va l'avoir également dans le tableau d'information ici avec availability instock 22 available ici donc on a cette cette information à deux endroits mais il faut vraiment se rendre sur la page du livre donc là encore différentes façons d'aborder le problème comme toujours en programmation il y a pas une seule façon de faire les choses donc qu'est-ce qu'on peut faire on peut se dire que en premier lieu je vais récupérer les URL de tous les livres de la bibli te et ensuite dans un second temps je vais accéder à chacune de ces URL pour aller sur la page et récupérer le prix total de chaque livre ça c'est une première façon de faire l'autre façon de faire c'est à chaque page de vraiment interrompre entre guillemets la la recherche de la prochaine page et juste commencer directement sur la première page récupérer le premier livre revenir là récupérer le deuxième et cetera moi je pense que je vais préférer une approche qui va consister à récupérer déjà dans un premier temps toutes les URL de tous les livres de la bibliothèque je préfère faire ça en deux temps et une fois qu'on a toutes les URL et bien donner ça à une autre fonction qui va elle naviguer sur chaque page pour récupérer le prix du livre donc déjà là je viens de le dire il me faut une fonction qui à partir d'une URL donc à partir de l'URL d'un livre va calculer le prix et là je peux spécifier encore une fois on va devoir récupérer donc ça va peut-être une fonction séparée et je pense que je vais déjà le mettre dans une fonction séparé parce que là encore directement en faisant cet exercice on peut commencer à penser de façon donc avec le S de solide qui est separation of concern donc d'essayer de ne pas avoir trop de de choses qui se passent dans la même fonction donc moi je veux une fonction qui à partir de l'URL d'un livre va calculer le prix et donc ça ça veut dire que je vais devoir aller sur l'URL récupérer le contenu de la page et également récupérer ces informations donc à savoir le prix et la quantité en stock donc moi je vais faire une fonction pour récupérer le prix et là je vais dire à partir du HTML donc là dans ce cas-ci pas à partir d'e URL mais directement à partir du du HTML et pareil pour la quantité donc fonction pour récupérer la quantité disponible à partir du HTML donc vous voyez on commence déjà à avoir plusieurs fonctions on a déjà quatre fonctions d'identifier et si je reviens donc sur la page d'accueil qu'est-ce que je vais avoir besoin de faire d'autres donc il faut on a on va avoir toutes les URL donc récupérer l'url de la page suivante non en fait il manque effectivement une fonction ici qui va nous permettre de récupérer toutes les URL de la bibliothèque donc on va dire fonction pour récupérer les URL de tous les livres et là vous voyez donc pour récupérer les URL de tous les livres comme on a un système de pagination il va déjà nous falloir une fonction pour récupérer les URL d'une page donc fonction pour récupérer les URL sur une page spécifique donc là vous voyez en fait je veux même pas le mettre comme ça en dépendance ça va être deux fonctions séparées donc une fonction on va lui donner tout simplement le HTML d'une page donc là aussi on pourrait spécifier si c'est à partir du HTML ou à partir de l'URL là encore je pense que je vais laisser ça pour l'implémentation va voir comment se construit petit à petit notre script et qu'est-ce qui fait le plus de sens pour chaque fonction euh donc fonction pour récupérer les URL de tous les livres de la bibliothèque et une fonction pour récupérer les URL sur une page spécifique donc comme ça en fait on va pouvoir arriver sur la première page récupérer les URL de tous les livres sur la page récupérer l'url de la page suivante avec cette fonction ici ensuite récupérer euh passer à la page suivante donc on va à partir de cette url qu'on a récupéré passer à la page suivante récupérer de nouveau les les URL sur une page spécifique et comme ça petit à petit construire une liste de tous les URL de la bibliothèque donc qui sera dans cette fonction ici et après une fois qu'on a ça et bien on va pouvoir boucler sur les URL donc à partir de l'URL d'un livre récupérer le prix récupérer la quantité là je pense que le calcul entre les deux on le fera à l'intérieur de cette fonction donc on pourrait essayer de séparer encore mais je pense que là ça deviendra un petit peu trop puisqu'il faut pas aller trop non plus il faut pas trop séparer les choses à la fin on se retrouve des fois avec des fonctions qui font une ligne le but ici c'est de pas avoir ir une seule fonction qui fait tout mais de pas non plus avoir des fonctions qui masquent juste une ligne de code donc là je pourrais peut-être faire une fonction qui calcule le prix total à partir du prix du livre et la quantité mais comme je vous dis en fait ça c'est juste une multiplication donc je pense que je vais le faire directement à l'intérieur de cette fonction donc je pense que ça commence à être pas mal il me semble que on a tout ce qu'il nous faut je réfléchis encore un petit peu mais là j'ai fait vous voyez dans ma tête le processus qu'est-ce que je ferais si j'étais un humain en fait si j'étais un humain probablement que je ferai la PR première façon de faire c'est-à-dire que je viendrai ici je prendrai le total donc 51.77 x 22 je reviendrai ici et je ferai la même chose pour chaque livre et une fois que j'arrive en bas je vais sur Next si je suis une machine je vais plutôt récupérer déjà tout ce que j'ai besoin ici là on l'a vu les deux façons de faire sont valides moi je préfère déjà tout récupérer ici pour bien séparer les choses et ensuite à partir des URL directement aller sur cette url ensuite ne pas du coup revenir sur la page d'accueil mais juste aller à la suite sur chacune des URL récupérer tous les prix ici et ensuite faire une grosse édition de tout ça pour récupérer le prix total de la bibliothèque donc on va commencer avec ça je pense qu'on a déjà de quoi s'occuper et comme je vous l'ai dit le but n'est pas de faire 100 % du script déjà à l'écrit l'idée c'est juste de ne pas avoir le syndrome de la page blanche et de commencer avec quelque chose donc là on a déjà de quoi s'occuper et probablement que par la suite on va remodifier tout ça peut-être que là il y a des choses auxquelles on n pas pensé des choses qu'on va pouvoir fusionner ensemble des fonctions qui vont faire comme je l'ai dit une seule ligne et qu'on va pouvoir donc fusionner donc là l'intérêt c'est vraiment juste de ne pas être confronté à la page blan et d'avoir quelque chose à se mettre sous la dent donc on va commencer avec ça avec la prochaine partie dans laquelle on va à partir de ces fonctions déjà créer la base des fonctions sans écrire encore le code à l'intérieur mais juste créer le squelette du script si vous voulez qui va correspondre à notre script final alors maintenant qu'on a défini notre plan d'attaque et qu'on sait un peu mieux les fonctions qu'on va devoir créer pour notre programme on va créer ce que j'appelle le squelette du script ça va nous permettre de de commencer sans trop rentrer dans le code là encore d'avoir une meilleure idée des fonctions qu'on va utiliser notamment des paramètres qu'on va donner à ces fonctions pour définir déjà ce qu'on avait commencé à faire ici par exemple pour cette fonction pour récupérer l'url de la page est-ce que pour récupérer l'url de la page suivante on va donner à cette fonction directement le html sous format texte donc une chaîne de caractère ou l'URL là encore une chaîne de caractère mais l'URL à partir de laquelle on va aller extraire le HTML pourquoi ça a son importance parce que là vous allez voir que on va avoir plusieurs fonctions qui vont travailler sur ce HTML et donc il s'agit de ne pas répéter l'information si à chaque fois par exemple on donne la requête et qu'on recrée un objet beautiful soup ou select AX dans le cas de l'utilisation de cette librairie pour remplacer beautiful soup et bien est-ce qu'on va recréer à chaque fois un objet auquel cas on pourrait impacter les performances donc ces décisions on va déjà un petit peu les prendre ici et c'est pour ça que j'ai envie de créer le corps du script et je vais également commencer avec les imports et utilisation du logger donc ça on l'avait fait dans la partie dans laquelle je présentais les outils qu'on va utiliser donc je vais juste coller le code ici on a donc l'import du HTML parser de selectolx qu'on va utiliser à la place de beautiful soup le logger de log Guru et le 6 ici qu'on va mettre d'ailleurs avant puisque c'est un module de la librairie standard et ça ce sont des modules que l'on a installé avec PIP on crée notre logger on ajoute le logger dans books.log avec le niveau warning et la rotation sur 500 KB et on va ajouter donc le loger également vers le terminal avec un niveau plus haut ici d'information donc on va retourner sur notre plan d'attaque ici et on va voir déjà quelle est la fonction qui sera un petit peu si vous voulez le point d'entrée de notre script on va probablement faire une fonction main là encore la fameuse fonction de point d'entrée avec la structure conditionnelle qui appellera ce point d'entrée et dans cette fonction qu'est-ce qu'on va faire quelle est la première chose qu'on va faire ça va être finalement je crois ce qu'on avait mis plutôt à la fin c'est-à-dire une fonction pour récupérer les URL de tous les livres de la bibliothèque puisque ça c'est la première chose qu'on avait dit qu'on allait faire donc je vais le mettre ici dans ma fonction main une fonction pour récupérer les URL de tous les livres de la bibliothèque et à partir de toutes ces URL on va pouvoir récupérer grâce à cette fonction donc fonction qui à partir de l'URL d'un livre va calculer le prix donc cette fonction pour récupérer les URL de tous les livres de la bibliothèque elle va faire appel à d'autres fonctions notamment la fonction pour récupérer l'url de la page suivante et la fonction pour récupérer les URL sur une page spécifique donc je vais les mettre ici je vais les rapprocher l'une de l'autre et je vais les mettre en fait à la suite je vais les couper et les mettre ici alors je vais refaire je vais sortir ça en fait de ma fonction main je vais mettre un pass c'est juste pour les avoir un petit peu plus en haut ici et je vais refaire une chaîne de caractère multiligne comme ça on les aura ici et ça je vais le déplacer ici aussi donc on va commencer par ces trois fonction et ensuite on terminera avec ces fonctions un peu plus spécifiques donc cette fonction qui à partir de l'URL va calculer le prix et les deux fonctions un peu plus utilitaires ici pour récupérer le prix et récupérer la quantité disponible donc dans l'ordre on a celle-ci la fonction en fait une des f fonction principale qui va récupérer les URL de tous les livres et là on arrive au moment préféré au moment préféré des développeurs c'est trouver des noms donc c'est souvent le plus difficile finalement comment on va appeler toutes ces fonctions donc je vais faire des fonctions avec des noms en anglais pour les dog strings puisque je vais essayer de faire un script le plus propre possible je vais mettre des doc string des annotations de type et cetera les doc strings je les ferai en français pour pas trop vous perdre mais normalement dans des script on fait tout en anglais euh après bon ça dépend bien sûr des équipes mais c'est une généralité euh qui est assez reconnu dans le monde du développement peu importe votre langue on essaie de développer en anglais pour que ce soit le plus facilement possible récupérable par n'importe quel développeur donc je vais faire des noms assez explicites qui vont être peut-être un peu longs mais au moins on comprendra bien de quoi il s'agit donc on va commencer par un verbe on va faire get et qu'est-ce qu'on va récupérer bah tout simplement les URL de tous les livres donc get all books books au pluriel parce qu'il va y en avoir plusieurs et URLs aussi au pluriel puisqueon va avoir plusieurs URL donc je vais mettre un pass pour l'instant comme je vous dis le but là n'est pas pas de coder les fonctions mais juste les noms les paramètres et peut-être on ira jusqu'à la doc string donc get all books URL là qu'est-ce qu'on va faire dans cette fonction donc je vais mettre une un commentaire une doc string ici donc récupère ici toutes les URL URL delivre sur toutes les pages et euh à partir donc à partir c'est là qu'il va falloir réfléchir je pense que moi en fait dans ce cas-là je vais juste lui donner une URL de départ donc on va donner l'url du site l'URL de départ du site et à partir de là il va va naviguer la prochaine page récupérer toutes les URL et cetera donc l'URL ça va être un paramètre qui va être une chaîne de caractère et qu'est-ce qu'on va retourner donc là encore j'utilise les annotations de type on va retourner une liste de chaînes de caractères alors là je vais importer depuis le module typing depuis typing on va importer liste et on va typer nos éléments avec cet élément donc liste et ça va être une liste de chaînes de caractèrees puisque les URL seront en toute logique également des chaînes de caractères et ensuite qu'est-ce qu'on va faire alors là je vais continuer ma doc string en précisant ce que font les paramètres je vais utiliser les outils de pycharm si je vais ici dans doc string on va pouvoir choisir le style des doc string donc je vais taper ici dans la barre de recherche des préférences doc string et donc ce n'est pas le site doc string c'est vraiment les documentation string ici et doc string format donc on est avec le restructurer de texte je vais le laisser comme ça et en fait là comme j'ai déjà écrit quelque chose il ne va pas me les proposer ce que vous pouvez faire c'est donc couper le texte que vous avez déjà écrit donc je vais revenir ici et si vous refaites vous voyez avec la touche Entrée un retour à la ligne automatiquement il va prendre la définition de votre fonction et remettre le bon formatage donc là on va voir deux points param le nom du paramètre deux points et nous on va indiquer ici à quoi corresponde ce paramètre et on va faire pareil avec return pour expliquer en fait qu'est-ce qu'on va retourner donc là je remets mon texte ici et à partir du coup de l' d'e URL en fait on va mettre d'e URL donc qu'est-ce qu'on va avoir ici bien tout simplement l'URL de départ et qu'est-ce qu'on va retourner liste de toutes les URL de tout toutes les pages de toutes les pages tout simplement on va s'arrêter là liste de toutes les URL de toutes les pages donc ça c'est la première fonction normalement on est bien ici on a un nom on a un paramètre donc à partir de cette url on va récupérer on va naviguer en fait et récupérer tout ce dont on a besoin on a une annotation de type ici pour dire ce qu'on va retourner ça va nous permettre de vérifier dans chaque utilisation après des fonctions et si on utilisait un type checker de vérifier que tout est bon et qu'on a pas fait d'erreur et qu'on a pas de problèmes potentiels qui peuvent arriver parce qu'on n pas retourné la chose et on a nos paramètres ici et je vais finir par un pass pour l'instant et je vais reformater tout ça là encore vous allez me voir le faire très souvent option commande l sur Mac sinon vous allez dans code pour retrouver le raccourci c'est reformat code ici et ça va faire des séparations pour tout ce qu'il faut entre vos doc string votre le corps de la fonction les autres fonctions et cetera donc ensuite qu'est-ce qu'on a une fonction pour récupérer l'url de la page suivante donc ça ça va être assez facile on va l'appeler get next page URL tout simplement et là comme je vous dis je pense que en fait je vais privilégié le plus possible de partir en fait directement d'un objet HTML parsur qui est l'objet de selectol AX qui va contenir déjà l'arbre qu'on va pouvoir traverser pour trouver les informations parce qu'en fait ici donc dans get all books URLs je vais créer cet objet je vais le passer à cette fonction et je ne veux pas le recréer à chaque fois pour ne pas ralentir le script donc là je vais faire un objet je vais appeler tree et je vais mettre la notation de type pour indiquer que ça va être un objet de type HTML pars et on va dire donc que ça retourbe tout simplement ici une chaîne de caractère parce que ça va être une URL unique donc ce n'est pas une liste d'URL c'est juste une URL on met la doc string donc les trois guillemets j'appuie sur Entrée là j'ai automatiquement les paramètres qui sont bien mis correctement et je vais dire bah tout simplement récupère l'URL de la page suivante à partir du HTML d'une page donnée voilà alors le paramètre tree bien ça va être un objet HTML parceur de la page à chercher on va faire ça ou de la page à scrapper de la page on va mettre tout simplement de la page et qu'est-ce que ça retourne et bien ça retourne l'URL de la page suivante là encore je mets un pass on commence donc à avancer dans la structure donc récupérer à partir du HTML ou de l'URL ça on y a répondu on va pour l'instant se baser sur le html directement plutôt que de l'URL puisque là en fait on va déjà récupérer dans cette fonction le html parsur et donc on va le passer à notre fonction ici pour récupérer la page de l'URL là encore tout ça n'est pas dans le béton bien sûr là c'est ça le but en fait de faire cette étape c'est de commencer à penser les choses mais après bien sûr ça peut bouger un petit peu par la suite il y a pas de souci avec ça donc fonction pour récupérer les URL sur une page spécifique donc ça je vais le mettre après on va continuer et là encore on peut l'appeler de façon très explicite get all books URLs mais cette fois-ci on page et là encore on va passer un objet donc HTML parsur puisque je vais continuer avec cette même logique et qu'est-ce qu'on va retourner donc all books URL là on retourne avec une liste de chaînes de caractères puisqu'on va avoir plusieurs URL retournés sur chaque page et je vais mettre donc m doc string ça va commencer à se répéter ici alors get all books URL on va dire donc récupère toutes les URL des livres présents sur sur une page le tree donc ça va être objet HTML parsur de la page là encore et en retour on va retourner donc liste des URL de tous les livres sur la page et encore une fois on met imp passe donc je vais collapser un petit peu tout ça pour voir où on en est donc on a notre chaîne de caractère ici on a fait ces trois premières fonctions fonction pour récupérer les URL de tous les livres donc get all books URL on pourrait rajouter in library ou un truc comme ça mais bon je veux pas non plus faire des fonctions avec des noms de 3 km donc get all books URL fonction pour récupérer l'url de la page suivante get next page URL et fonction pour récupérer les URL sur une page spécifique getthbook URL hand page donc comme ça depuis ici on va pouvoir à partir de cette URL récupérer donc déjà appeler en fait getthold books URL sur la page où on est ensuite récupérer l'url de la page d'après naviguer vers la page d'après et refaire un appel à getold books et cetera pour construire petit à petit notre liste donc cette fonction en fait va utiliser ces deux autres fonctions pour faire la ce dont elle a besoin mais là vous voyez que déjà on commence à séparer les choses bien pour ne pas tout faire à l'intérieur d'une même fonction ça permet d'avoir des fonctions qui vont être plus faciles à tester qui vont faire une seule chose et une seule chose bien plutôt que de faire au moins trois ou quatre choses en même temps et comme ça ça va être donc plus facile et donc qu'est-ce qui nous reste comme fonction on a ces trois autres fonctions ici donc là encore je vais couper tout ça et je vais le remettre à l'intérieur de ma chaîne de caractère ici je vais même le déplacer un petit peu on va on va descendre un petit peu dans notre script donc je descends ici je remets mes fonctions à créer donc fonction qui à partir de l'URL d'un livre va calculer le prix donc on peut faire une fonction qu'on va appeler getbook price par exemple from URL alors là là encore euh qu'est-ce qu'on fait est-ce qu'on prend l'URL alors oui dans dans ce cas-ci ça va être l'URL alors on n peut-être pas obligé de mettre from URL là encore c'est une décision à prendre vu qu'on va mettre un paramètre URL donc cette fonction elle va être appelée par une autre fonction qui va probablement être la fonction main dans laquelle en fait ici si vous vous souvenez bien on a dit qu'on allait déjà récupérer toutes les URL et ensuite à partir de ces URL on va récupérer les prix donc probablement qu'on va tout simplement faire une boucle for qui va appeler cette fonction autant de fois qu'il y a de livres pour lui passer l'URL qu'on aura récupéré au préalable dans cette fonction ici donc là on va passer une URL dans ce cas-ci on pourrait choisir dans la boucle ici de déjà créer un objet HTML pars dans mon cas je pense que je vais plutôt faire cette opération à l'intérieur de la fonction je veux juste passer l'URL je veux pas faire trop de logique dans cette fonction main donc je vais garder cette logique à l'intérieur de getbook price from URL donc là comme je vous disais on n pas obligé de mettre from URL finalement si on met un paramètre URL ça fait un petit peu doublon donc je pense que je vais juste mettre getbook Price et dire que ici on a en paramètre une URL qui va être une chaîne de caractère et qu'est-ce que ça va retourner dans ce cas-ci ça va retourner un float puisque les prix peuvent être des nombres décimaux donc ça ne va pas être un nombre entier mais un float et je vais remettre encore une fois ma doc string pour expliquer ce que ça fait donc tout simplement récupère le prix d'un livre à partir de son URL donc l'URL ici ça va être URL de la page du livre et Return ça va être le prix du livre tout simplement le prix du livre en fait euh le prix du livre multiplié on va être plus spécifique multiplié par le nombre de livres en stock parce que c'est pas juste le prix du livre là si on a un livre qui coûte 50 € et qu' y en a 10 ça va être 500 € du coup le le prix total du coup je pourrais spécifier un petit peu get book price on pourrait dire get book price based on quantity si on veut ça sera un petit peu plus un peu verbeux mais bon en tout cas c'est un peu plus clair comme ça directement de quoi à quoi va servir cette fonction donc cbook price based on quantity ça c'est bon et ensuite on a dit si je remonte là donc ça on l'a fait fonction pour récupérer le prix à partir du HTML euh là encore à voir peut-être qu'on va le séparer je j'hésite je ça c'est peut-être quelque chose que je verrai plus tard en fonction de la longueur du code euh mais là encore pour des questions de vu que c'est quelque chose qu'on va pouvoir probablement répéter et si on le testait tester de façon plus unitaire j'ai envie d'avoir une fonction en fait juste pour à partir du HTML euh donc de l'objet tree HTML parsur donc cet objet ici on va récupérer à partir de select AX juste à partir de ce prix vérifier que on peut à partir du du HTML de notre page récupérer le prix et pareil pour la quantité donc je vais quand même faire des fonctions séparées pour ça on va faire une fonction qu'on va appeler extract cette fois-ci pour bien signifier qu'on extrait des données le des données HTML le prix donc on va dire extract price from page et on va lui passer dans ce cas-ci directement un objet HTML parser pourquoi là on passe pas l'URL parce que l'URL et le le le parser en fait on l'aura déjà ici dans cette fonction donc là encore comme je vais extraire le prix et la quantité je ne veux pas recréer un objet html par sur à chaque fois donc là je vais récupérer cet objet HTML parsur dans cette fonction et le passer à extract Price et l'autre que je vais faire pour extraire la quantité et qu'est-ce qu'on va retourner ici bah dans ce cas-ci un float puisque le prix on l'a dit ça peut être un nombre décimal donc extract price from page là encore on va mettre notre doc string extrait le prix du livre depuis le code HTML de la page donc tre ça va être un objet HTML parsur de la page du livre et return on va retourner le prix unitaire du livre et ici on va mettre un pass et on va faire la même chose je vais même peut-être copier on va voir peut-être qu'on pourra même faire une seule fonction pour les deux si ça se répète là encore on peut pas le savoir à l'avance mais si le code est presque le même peut-être qu'on pourra tout rassembler ça dans une fonction et juste avoir un paramètre qui change en fonction de de l'information qu'on souhaite récupérer euh là pour l'instant je préfère quand même bien séparer les choses plutôt que de passer par un paramètre c'est plus plus plus clair aussi comme ça faut juste voir à quel point le code va se répéter par la suite donc là on va dire extract donc qu'est-ce qu'on va extraire ici extract stock quantity from page donc le le la quantité de livre en stock et ici on va mettre aussi on va modifier et on va dire extrait la extrait la quantité de livr en stock sur depuis le code HTML de la page le code HTML de la page là encore donc objet HTML de la page du livre et là le nombre le nombre de livres en stock et là dans ce cas-ci donc ça va pas être un float ça va être un int puisque il on aura pas on ne peut pas avoir une moitié de livre en stock donc ça va forcément être 0 1 2 et cetera donc des nombres entiers donc voilà normalement je pense qu'on a tout on va enlever cette chaîne de caractère ici qui ne sert plus à rien je refais un petit reformat et là normalement donc dans notre fonction main ici qu'est-ce qu'on va faire ben on va prendre les all books URL ça va être get all books URL l'URL de base je vais la mettre ici je vais l'appeler même base URL hop URL et ça va être donc l'URL de la page d'accueil on va récupérer toutes les URL à partir de cette url de base et ensuite on va dire pour each book on va mettre juste book pour book in all books URL on va mettre book URL du coup puisque ça va être une URL là on va récupérer le Price qui va être égal à get price getbook price based on quantity et là ouais c'est un peu je vais enlever le bas down quantity parce qu'on a l'impression que là il va falloir lui passer la la quantité alors qu'en fait on va juste récupérer le juste récupérer le book price euh je vais je vais le laisser comme ça je vais laisser get book price ça me semble plus clair là encore comme je vous dis les noms c'est vraiment la chose qui est peut-être la plus difficile à à avoir de correct il y a pas de bonne réponse et il faut essayer de de coller le plus à la réalité donc kbook price là on a dit que c'était justement depuis l'URL donc book URL donc vous voyez là on commence à faire la logique même si on a rien encore qui est fait dans les les fonctions euh on vérifie que là on a bien la logique qui se met en place parce que là imaginez donc que je j'aurais pu mettre autre chose en fait j'aurais pu mettre l'arbre comme je vous dis mais là ça veut dire qu'on aurait dû récupérer ici déjà le tree à partir de HTML parseur donc ça peut être ça peut être une façon de faire mais là moi je préfère avoir le minimum de code ici et avoir après à chaque fois le code qui se passe à l'intérieur des fonctions donc là on a l'URL donc ça fait du sens de passer l'URL à cette fonction et de récupérer le prix et après qu'est-ce qu'on peut faire on va même peut-être pouvoir à la fin va faire tout ça dans une une compréhension de liste mais je pense que c'est bien aussi d'avoir une boucle pour que ce soit plus clair on peut dire total price est égal à zéro ici faire un total price de plus égal price tout simplement et à la fin retourner total price et je pense que ça suffirait voilà pour récupérer le prix total de la librairie donc on a notre URL de base à partir de cet URL on fait un get all books URL on lui passe l'URL de base là on va avoir une liste avec toutes les URL de tous les livres de la bibliothèque on boucle dessus on définit un prix des de base qui est égale à zé on boucle sur toutes les URL on récupère le prix du livre basé sur le prix du livre plus la multiplié par la quantité à partir de l'URL du livre donc on va faire le scrapping dans cette fonction qui va utiliser ces deux autres fonctions pour extraire les données et ensuite on ajoute ce prix à cette variable on pourrait faire une liste aussi ça pourrait être plus simple et un peu moins gourmand ressource de faire une liste plutôt que de d'ajouter tout ça euh de faire total price point appen Price et ensuite de faire un retour de somme de Total price c'est une autre façon de faire vous voyez là encore il y a pas qu'une seule façon de faire les choses et je vais m'arrêter là pour cette partie on a fait déjà beaucoup de choses je pourrais aussi aller faire déjà le le code aussi dans get BX URL pour faire la logique sur papier de ce qu'on a dit qu'on voulait faire mais là je pense qu'en fait quand on va commencer à faire ça on va vraiment commencer à mettre les mains dans le code et faire le code de chaque fonction parce que là comme on l'avait dit get books URL ça va utiliser get next page URL et get all book URL hand page donc on pourrait commencer à faire du pseudo code ici mais en fait là je pense qu'on est rendu à un bon niveau pour pouvoir commencer à coder spécifiquement chacune de ces fonctions alors dans cette partie on va coder la fonction qui va nous permettre de récupérer le prix d'un livre donc ça va être cette fonction getbook price on va commencer à ce niveau-là directement dans le cœur donc on va s'amuser à récupérer le prix du livre et après on verra comment faire toute la logique autour donc la logique avec le get all books URL on pourrait faire l'inverse bien sûr commencer par cette fonction là c'est vraiment à vous de voir moi dans ce cas-ci je vais commencer par la fonction qui me permet de récupérer le prix d'un livre puisque ça c'est sûr qu'on va avoir besoin de le faire les autres là encore on va voir comment on va adapter notre script peut-être qu'on va penser en faisant ça à d'autres moyens de faire c'est pas encore forcément couler dans le béton comme je le disais donc je préfère commencer par cette fonction qui là je le suis sûr va être absolument essentielle puisque on peut pas récupérer le prix autrement qu'en allant sur la page du livre on l' vu la quantité en stock elle n'est pas disponible au niveau des pages ici des pages du site il faut faut vraiment aller sur la page du livre donc je vais prendre le premier exemple là encore on va isoler les choses c'est-à-dire qu'on va prendre un exemple spécifique et par la suite on va faire de la gestion d'erreur également pour voir si les éléments sont trouvés ou non et comme ça quand on fera un scrapping sur tout le site si jamais il y a des erreurs si jamais par exemple sur une page on n pas la quantité en stock ou le prix ou quelqueautre information dont on aurait besoin et bien on va avoir une gestion efficace de ces erreurs pour en fonction de ce qu'on souhaite soit afficher un message soit faire planter le script et cetera comme on l'avait vu dans les exercices précédents et bien faire une action qui va nous permettre de gérer cette erreur correctement de la façon dont on le souhaite et non pas de subir cette erreur donc là je vais appeler cette fonction getbook Price et dans l'URL je vais lui donner l'URL que je vais créer juste avant ici qui va correspondre à ce livre donc URL égal à l'URL que je viens de définir donc dans cbook price qu'est-ce qu'on va faire ici on va avoir une URL et on va retourner un float donc il faut déjà bien entendu naviguer vers cette URL avec le module request pour pouvoir récupérer le html donc le module request je pense que je l'avais déjà importé non en fait je l'avais pas encore importer donc on va l'importer ici après donc import request et ici à partir de l'URL donc on va faire un request.get vers cette url cette requête je vais tout de suite la mettre dans un bloc try accept puisqu'on sait que les requêtes ça peut planter on peut avoir des problèmes de réseau on peut avoir des erreurs 404 et cetera donc il y a plein de choses qui peuvent arriver donc je vais récupérer cette regette dans un objet response et je vais faire un response.raace for status pour qu'on ait une erreur qui soit levée si jamais on n pas un code valide qui nous est retourné comme un code 200 donc là qu'est-ce que je vais faire comme exception l'exception qui est dans le module request qui est dans le sous-module donc exception et qui s'appelle request exception et je vais récupérer cette exception as e donc dans une variable qui va être e qui va me permettre de faire un log donc puisque les erreurs dans ce cas-ci je veux les loguer dans mon fichier de log le fichier de log qu'on a créé ici donc avec avec logger.adbooks.log toutes les erreurs qui sont de type warning error ou critical on va les loguer dans ce fichier moi ce que je veux faire ici ce n'est pas donc arrêter le script là je vais vraiment adopter une logique qui est que je veux vraiment aller au bout de mon cheminement je veux scrapper l'entièreté du site et ce script en fait je veux le lancer tous les jours par exemple pour récupérer la valeur totale et voir tous les jours combien mes combien ma librairie vaut en terme de stock donc par exemple on va dire 300000 € le jour d'après on va avoir fait des ventes donc il restera plus qu'un total de 298000 € par exemple dans la boutique et on aura fait 2000 € de vente et on pourra voir comme ça l'évolution de du prix total de notre boutique donc moi je veux vraiment qu'il y ait aucune erreur parce que imaginez que ça plante au milieu et que là du coup on nous dise le prix de la librairie c'est 150000 parce que ça a pas réussi à faire tout le scrapping là ça serait un problème et par contre quand on a des erreurs on veut les régler donc s y a un moment une page qui ne contient pas la quantité en stock ou qui ne contient pas le prix bah c'est un problème aussi mais on va l'adresser différemment c'est-à-dire qu'on va mettre cette erreur dans un fichier de log et ensuite on va avoir une personne dans la librairie par exemple qui pourra vérifier qui pourra être averti avec des outils comme centry par exemple qui pourrait vérifier avec ses logerss et envoyer une alerte quand on a une erreur pour que l'erreur soit réglée plutôt que de faire penser que en fait le script a correctement fonctionné alors que ce n'est pas le cas donc là on gère cette erreur s'il y a une erreur dans ce cas-ci qu'est-ce que c'est c'est une erreur qui va se passer lors de la requête donc on va faire tout simplement un loger point error et on va dire erreur lors de la requête donc je vais mettre erreur lors de la requête HTTP et je vais insérer à la fin l'erreur donc je vais mettre des accolades ici j'ai fait une F string au début pour insérer ce message parce que là on ne va pas faire un raise on ne va pas arrêter le script comme je viens de le dire on va continuer donc qu'est-ce qu'on va faire ici dans ce cas si on va juste retourner 0 donc on va retourner 0.0 parce que là ici on est avec un retour qui est un float et on ne veut pas retourner à un autre élément puisque le prix du livre ici si vous vous souvenez bien dans cette fonction main on va l'utiliser on va l'ajouter en fait dans cette liste de prix totau et on va faire la somme à la fin donc si on se retrouve avec un objet nonone ou un false ou quelque chose d'autre et bien ça va le encore planter donc ce qu'on veut faire c'est c'est pas que ça plante on veut juste retourner une information qui va être valide mais qui ne va pas fausser le résultat donc c'est juste que voilà on va dire que ce prix-l il vaut zéro parce qu'il y a une erreur sur le site donc ça déjà ça nous permet de gérer les problèmes qu'on pourrait avoir avec raise for status et ensuite on va créer donc notre objet HTML parsur à partir de response.text et je vais stocker ça dans une variable que je vais appeler tree et que je vais passer du coup à mes autres fonctions ici donc là on revient au sujet qu'on avait vu précédemment à savoir que là je ne veux pas passer l'URL pour recréer un objet HTML parseur à chaque fois je vais le faire juste une fois ici et ensuite passer cet objet à mes fonctions d'extraction qui vont à partir de cet objet donc à partir de le de l'objet HTML parser extraire les informations de prix et de stock et ensuite ici ici bah qu'est-ce qu'on va faire tout simplement multiplier l'un par l'autre donc je vais dire price ég extract price from page on va passer le tree et là je vais dire stock ég extract stock quantity from page et on va lui passer le TR également et au final on va faire un price FO stock tout simplement et c'est à l'intérieur ensuite de ces fonctions qu'on va gérer les erreurs potentielles qui pourrai y avoir lors de l'extraction on va pas faire un try except ici on va le faire directement à l'intérieur de ces fonctions donc on va rentrer maintenant dans cette fonction on rentre encore plus dans le cœur du j'ai je vais déjà peut-être faire un un test pour voir qu'on arrive bien ici donc je vais mettre un point de débug et vérifier qu'on arrive bien au moins jusqu'à ici jusqu'à la récupération du tree donc de l'objet tree je lance en mode débug et on espère qu'on se rendre jusque là et voilà donc on a bien un response de 200 donc la requête a été correctement effectuée et on a ici notre objet tree qu'on va pouvoir inspecter pour récupérer le prix donc j'enlève mon point de débug je reviens ici extract price from page et là donc qu'est-ce qu'on a ici on a le prix qui est à un seul endroit je pense sur la page je vais faire un contrôle F et ah non il est aussi ici donc là on a plusieurs plusieurs possibilités donc je vais regarder qu'est-ce qui est le plus simple on va faire un clic droit inspect et on va vérifier avec notre petit élément donc on peut cliquer sur cet élément ici pour naviguer dans la page donc là on a le P avec le price color qui est un nom de classe assez spécifique je vais vérifier avec un contrôle F s'il apparaît ailleurs et non il est unique donc un sur un donc ça c'est déjà pas mal je pense qu'on a pas besoin d'aller plus loin je vais aller voir quand même ici et là effectivement on a des TD donc on a le prix sans la taxe et le prix avec la taxe donc nous dans notre cas on va garder le le prix le prix qu'on a ici qui va inclure les taxes on veut pas rentrer trop dans le détail avec les là en plus la taxe est de zéro donc on va juste garder le le prix d'origine et ici comme on a des TD sans rien sans classe c'est peut-être un peu plus compliqué à aller chercher alors que là on a un P avec une classe price color qui est unique donc ça ça me plaît bien on va on va partir là-dessus pour récupérer le prix donc là pour récupérer cet élément on va utiliser notre notre objet tree et on va utiliser la fonction CSS et dans ce cas-ci la fonction CSS first parce que CSS nous retournerait en fait une multitude d'informations donc même si on a qu'un seul élément sur la page il va nous retourner une liste alors que CSS first va nous retourner seulement un élément donc le premier élément qui trouve si en a plusieur ou là dans ce cas-ci comme l'élément est unique et bien on aura que cet élément de retourner de toute façon donc là qu'est-ce qu'on va voir un paragraphe avec une classe donc on met la balise P et tout de suite après on met le point pour la classe et là c'est price color si je me souviens bien je crois que je l'avais dans mon oui voilà dans mon press papier donc price color et on va récupérer ça dans une variable que je vais appeler price node et là encore on va pas aller plus loin je vais juste faire un print de Price node et je vais lancer le script et là vous voyez alors on a oui un problème parce que j'ai déjà fait le la multiplication donc là dans mon extract quantity je vais juste retourner directement pour l'instant je vais faire un return de 1 et là on va mettre un return de 1 aussi donc comme ça ça nous fait un return de base qui fait qu'on a pas besoin de de d'enlever cette cette ligne je pourrais aussi commenter cette ligne tout simplement et enlever les return là c'est à vous de voir ce que vous préférez je pense que je vais faire ça comme ça donc je relance le script et là j'ai bien un no de P qui est qui est visible donc ça semble bon je peux faire un print de cet élément point texte et là si on lance le script on a bien le texte avec l'information donc 51.77 donc c'est ce dont on avait besoin et là il va rester un petit truc à faire c'est-à-dire il va on va devoir en fait extraire tout sauf l'élément qu'on a ici alors là encore je vais faire un clic droit pour voir comment sous quelle forme est cet élément et là on a juste voilà le le symbole de de livre de pound et ensuite le nombre donc là on va être obligé de faire l'extraction de texte on va pas pouvoir récupérer uniquement ça si par exemple on avait un span à l'intérieur de ce P ou quelque chose du genre avec une autre classe qui engloberait uniquement le prix ça pourrait être faisable comme ça mais là ce n'est pas le cas donc ce que je vais faire c'est utiliser mon outil préféré pour ça que tout le monde déteste c'est-à-dire les reject donc je vais l'importer au-dessus dans les les librairies qui sont dans la librairie standard donc ici import re et on va utiliser ça pour aller chercher les informations dont on a besoin donc avant de partir dans la reject je vais déjà récupérer donc ce texte qu'on vient de faire avec un print sauf que là je vais le mettre dans une variable et je vais commencer dans ce cas-ci pas avec un try accept cette fois-ci on va faire un lbyl look before you lip on va vérifier est-ce que on a un price node donc on va dire if price node donc si cet objet contient quelque chose donc ça veut dire qu'on a trouvé cette cet élément sur la page et on va pouvoir récupérer le texte même si le texte lui ne contient rien et au quel cas on aurait un autre problème là ce que je veux c'est juste savoir est-ce que cet élément est trouvé sur la page oui ou non et donc si c'est le cas et bien on va récupérer ça dans une variable qu'on va appeler price string par exemple et si on n pas cet élément donc ça veut dire qu'il n'a pas été trouvé sur la page dans ce cas-ci on va faire tout simplement un loger.error et indiquer aucun nœud contenant le prix n'a été trouvé donc nœud c'est le mot français pour node qui est le la façon dont on appelle ces éléments qui sont sur la page et là qu'est-ce que je vais faire ici et bien tout simplement retourner encore une fois un 0.0 parce que je ne veux pas comme on l'a vu arrêter le script empêcher le script de continuer c'est ce que j'ai choisi ici je retourne zéro on considère que il y a un problème avec le prix sur la page donc on le log on le met dans notre fichier de log mais on continue le script en retournant des informations valides pour continuer le script donc quand on n' pas le prix on le logue et on considère que le livre a un prix qui est égal à zéro et on fera Z0 fois la quantité peu importe la quantité on aura un prix de z0ro au final donc ensuite qu'est-ce que je vais faire et bien je vais faire cette fameuse Rex qui va me permettre de récupérer seulement les informations de nombre et le point donc bien important ici parce que si je prends juste les nombres on va se retrouver avec 5177 ici moi je veux bien garder le point donc je vais déjà faire ma reex donc je vais faire une reex avec le r les Guimet ici on va récupérer donc une suite de caractères donc qui vont être dans ce cas-ci des nombres entre 0 et 9 donc je vais mettre un ensemble ici 0- 9 ça va correspondre à tous les nombres de 0 à 9 0 et 9 inclus et l'autre caractère qu'on va vouloir cibler c'est le point donc je le mets à la suite un point ici comme ça donc là je cherche tous les nombres de 0 à 9 et éventuellement un point et je vais mettre un plus ici plus ça veut dire 1 jusqu'à l'infini et c'est pour ça que j'ai mis ici les crochets donc je cherche ces éléments donc soit 0 soit 1 soit 2 et cetera jusqu'à 9 soit un point et ça au moins une fois ou plus donc ça veut dire qu'on peut avoir par exemple 100 ça va marcher on aura 1 0 0 c'est valide c'est contenu dans l'ensemble et on l'a au moins une fois dans ce cas-ci avec 100 on l'aura trois fois on aurait trois nombres comme ça là dans ce cas-ci j'ai 51.77 le premier élément ici le symbole de livre sterling il n'est pas dans cet ensemble donc il ne sera pas trouvé le deuxième élément le 5 il est dans l'ensemble le 1 aussi le point aussi le 7 le 7 et cetera et on en a quatre donc on en a au moins un jusqu'à l'infini on pourrait avoir un prix qui va jusqu'à des milliards de milliards et ça sera valide également donc voilà ma reject que je vais utiliser et pour récupérer cette information on va faire un re.f all pour trouver toutes les occurrences qu'on va avoir dans cette chaîne de caractère qu'on va lui passer qui va être dans ce cas-ci le price string qu'on a récupéré auparavant donc on récupère ce price string si on arrive ici c'est qu'il est correctement défini puisqu'on va être passé dans le if sinon on aura fait un return et ce que je vais faire c'est récupérer le premier élément s'il existe donc avec un crochet zéro puisque si on trouve quelque chose ici on va avoir une liste avec toutes les occurrences qui ont été trouvées puisque finall ça va trouver toutes les occurrences et donc moi ce que je veux c'est récupérer la première puisque je veux pas une liste je veux vraiment la valeur sous forme de chaîne de caractère de cet élément que j'ai trouvé qui va être le premier dans cette chaîne de caractère et qui sera donc le prix là vous vous doutez bien que si on ne trouve pas l'élément on va avoir potentiellement une erreur et cette erreur vous l'aurez compris ça va être une erreur de d'index et cette erreur on va la provoquer pour être sûr que c'est la bonne mais par habitude c'est une erreur d'index puisque ici en fait on va vooir une liste et donc quand on essaie de récupérer un élément dans une liste qui n'existe pas si la liste est vide et qu'on essaie de récupérer le premier élément et bien on aura une erreur de type index error donc je vais déjà faire mon bloc try except et on va essayer de faire planter tout ça pour voir si on arrive bien à récupérer notre erreur donc moi comme je vous dis par habitude je sais que c'est une erreur de type index erreur mais on va la provoquer quand même pour vérifier que c'est bien ça donc là je vais faire un logueer là encore une fois on log notre erreur on va dire aucun nombre n'a été trouvé et on va récupérer l'erreur ici donc as e et on va le mettre à l'intérieur de cette chaîne de caractère donc comme on l'a fait pour les autres erreurs et on va retourner ici dans ce cas-ci encore une fois 0.0 et si c'est pas le cas si on a bien réussi à récupérer quelque chose on va le retourner donc on va retourner le prix qu'on a trouvé dans un else le else il va être exécuté si le try a été réussi et qu'est-ce qu'on va retourner ben on va retourner le prix qu'on aura récupéré auparavant dans cette variable et on va le retourner donc ici avec un return dernière chose à faire c'est de convertir cette information en float puisque là on aura une chaîne de caractère donc je fais un return de float de Price je pourrais refaire un try accept ici pour vérifier que la conversion fonctionne bien là normalement si ma reject c'est bonne je ne peux pas avoir autre chose qu'un Flotat on pourrait avoir des cas de figure où on pourrait vérifier est-ce qu'on a un point ou une virgule et des choses comme ça là on va pas rentrer trop dans le détail sinon cette formation ne finira jamais mais voilà il faut pas non plus être complètement fou là je vais faire un float directement mais sachez que si on voulait vraiment vraiment être sûr on pourrait aussi vérifier cette ligne pour s'assurer en fait au préalable que ce soit avec un try accept ou avec un IF s'assurer que on peut convertir cet objet en float donc là je vais le retourner comme ça et comme je vous dis on va volontairement faire planter le script donc là c'est-à-dire que je vais faire un price string ici qui va être égal à quelque chose qui ne va pas fonctionner donc là par exemple je vais mettre ABCD donc là dans ce ABCD on ne va pas trouver quoi que ce soit qui corresponde à cette reject à savoir des nombres des points au moins une fois et donc là on aura une liste vide et normalement ça va planter donc je relance le script et on vérifie et là on a bien notre erreur qui est loguée correctement dans dans notre terminal avec extract price from donc erreur à la ligne 84 c'est bien effectivement à cette ligne là qu'on a le loger aucun nombre n'a été trouvé list index out of range donc vous voyez que ça a bien fonctionné là si j'avais mis un value error par exemple à la place je relance là vous voyez on a on n pas réussi à récupérer cette erreur donc on a l'erreur complète avec le index error et on n pas notre message de loger puisque ici ce n'est pas une erreur de type value error mais bien de type index error donc vous voyez n'hésitez pas à provoquer les erreurs comme ça pour vérifier de quel type es sont et ensuite bien gérer cette erreur de la façon dont vous le souhaitez à l'intérieur de ce bloc except donc normalement c'est bon on va faire un print de float price pour vérifier que tout est bon ici et on a bien 51.77 donc ça fonctionne parfaitement je vais juste vérifier avant de terminer cette fonction que on a bien le else qui va être correctement exécuté donc là à la place d'un P je vais mettre un div et on va lancer et là on voit bien qu'on a de nouveau cette erreur avec aucun nœud contenant le prix n'a été trouvé donc on arrive bien avec cette erreur ici à la ligne 77 d'ailleurs si je vais voir dans mon fichier de log normalement dans le book. log on voit ces deux erreurs que j'ai eu également avec la date l'heure et le type d'erreur le ligne la ligne et cetera donc ça va me permettre comme je vous disais de bien voir de bien faire le suivi des problèmes qu'on pourrait avoir dans notre script donc je vais replacer le P ici et maintenant on va s'attaquer à la fonction qui va extraire les quantités donc ça va être assez similaire comme je vous l'avais dit peut-être qu'on va même pouvoir faire une seule fonction avec ça mais là je vais récupérer donc à partir de mon arbre euh avec la méthode CSS first ce que je recherche dans la page puisqueon va en avoir un seul donc je reviens ici on va faire un clic droit inspect sur cette donnée instock availability et là on a le instock avec 22 available et je crois que je l'avais vu également ici availability donc on va faire un inspect aussi sur cette partie là et là de la même façon on se retrouve avec un TD euh tbody TD donc ça pourrait être une autre façon de faire moi je pense que je vais préférer encore une fois cet élément là avec une classe bien spécifique donc instock availability donc inst stock ça veut dire qu'il est en stock si on trouve pas cet élément ça veut dire que probablement en fait le le livre n'est pas en stock donc moi je vais cibler cet élément comme je vous dis ça va être assez similaire donc je vais aller peut-être un petit peu plus vite on va récupérer ici donc le stock on va l'appeler stock node égal à ça ça va être alors je crois que c'est un P ou un div je sais plus j'ai oublié c'est un P aussi donc P inst stock availability et là on a deux classes donc instock et availability donc là on cherche à avoir à la fois cette classe et également cette classe sur notre P et ensuite ce que je vais faire c'est euh là encore une Rex puisqu'on va vouloir extraire ce nombre à l'intérieur de cette chaîne de caractère donc là encore on pourrait utiliser find all on peut aussi utiliser r.s pour enlever tout ce qui n'est pas euh une tout ce qui n'est pas un nombre à l'intérieur de cette chaîne de caractère là pour garder une cohérence avec la l'autre fonction je vais utiliser find all également donc ici je vais faire un re.f all et dans ce cas-ci on n' pas le point puisque on peut pas avoir comme on l'a dit euh un demire en stock donc ça va être des nombres entiers donc la Rex va être plus simple ça va être tout simplement slash D avec un plus donc avec le slash D qui défin n'importe quel nombre de 0 à 9 là encore on pourrait remplacer aussi et mettre les crochets comme on l'avait vu avec 0-9 ça marcherait également et là j'ai effacé hop le le guillemet donc ça aussi ça marche à vous de voir ce que vous préférez moi je vais préférer le slash d si vous voulez une bonne référence de tout ce que vous pouvez utiliser vous avez reex 101 si je descends ça doit être je vous afficher ici on a le slash D qui doit être quelque part là voilà slashd any digit vous voyez donc à vous de voir soit vous spécifier très précisément ce que vous voulez avoir donc des nombres de 0 à 9 ou le slash d ça va être exactement la même chose donc qu'est-ce que je vais aller chercher ici on va voir le stock node et là on va faire un try accept on va faire tout un peu dans le même bloc et on va gérer les différentes cas de figure avec différents blocs except je pense dans ce cas-ci je vais vous montrer là encore une autre façon de faire donc ce qu'on va faire c'est récupérer le point texte à partir de ce stock node et le find all donc ça va nous retourner encore une fois une liste donc on va récupérer le premier élément de la liste et euh et voilà et on va convertir tout ça en nombre entier parce qu'encore une fois on va avoir une chaîne de caractère donc il faut la convertir on va faire la même chose qu'ici je vais gérer plusieurs cas de figure mais pas le dernier cas de figure qui est la conversion en int parce que je considère que si je suis arrivé jusqu'ici ça veut dire que j'ai vraiment un nombre puisque on aura extrait tous les nombres de la chaîne de caractère avec le SL HD donc je vais pas gérer cette potentielle erreur avec le int par contre on a deux autres erreurs qui peuvent arriver ici qu'on avait géré également dans cette fonction donc la première erreur c'est la possibilité qu'on ne trouve pas de nœud sur la page avec cette cette ce sélecteur CSS la deuxième erreur c'est que même si on trouve un texte qu'on arrive pas à trouver les nombres donc imaginez qu'on est juste inst stock mais qu'on est pas le 22 dans le nombre et bien on pourrait pas récupérer ici les nombre qui n'existe pas dans le findall donc là on a deux erreurs on a une première erreur qui serait que là par exemple stocknes sera égal à non donc là si on a un objet non parce qu'on a rien trouvé ici dans ce cas-ci c'est une erreur de type attribute error ça veut dire que l'attribut texte sur l'objet non il n'existe pas donc là ce que je vais faire c'est remettre mon stock node et faire un try except donc try on essaye tout ça et si ça marche on va mettre un return d'ailleurs on va retourner tout ça et except donc on va gérer la première erreur avec une attribute error as e et on va dire ici tout simplement loger.error encore une fois on va dire aucun nœud aucun nœud comme ça et on va mettre le nom du nœud donc P instock availability hop n'a été trouvé sur la page tout simplement n été trouvé sur la page avec un point à la fin et qu'est-ce qu'on va faire ici encore une fois continuer avec le bon déroulement du script en retournant 0ro pour pouvoir multiplier par 0 du coup le prix qu'on aura trouvé donc même si on a un prix ici qui est valide si on n pas réussi à trouver les stocks on considère qu'il y en a zéro ou on pourrait considérer qu'il y en a un mais je préfère considérer qu'il y a zéro et juste après les laisser les personnes ne pas fausser les prix parce que s'il y a pas de stock affiché c'est probablement qu'il y a une erreur quelque part et qu'on a peut-être pas le livre donc je vais laisser après la personne gérer le problème avec le fichier de log et on va retourner zéro et le et je vais mettre également ici hop avec un f string l'erreur qu'on a à l'intérieur de ma chaîne de caractère et l'autre erreur qu'on peut avoir c'est un index error donc comme on l'avait vu ici avec le prix c'est-à-dire que on peut essayer de récupérer l'indexe zéro sur une liste qui est vide et donc encore une fois ça ne fonctionnera pas donc là loger.error de nouveau et on va dire aucun nombre n'a été trouvé dans le nœud tout simplement et on fait un return de Z0 de nouveau donc normalement on a tous les cas de figure que je vois qui ont été gérés le cas de l'attribute error le cas du index error on va mettre le E ici aussi hop avec notre F string avec un de point comme ceci et avec un deux points ici aussi pour qu'on sépare bien les deux donc là encore je vais tester quand même tout tout ça en provoquant des erreurs donc je vais mettre un S par exemple ici pour fausser les données je lance et on a bien une erreur à la ligne 100 donc ligne 100 aucun nœud pain stock avability n'a été trouvé donc c'est parfait si on trouve ce nœud mais qu'ensuite donc là encore je vais fausser les choses je vais mettre ici à la place de ça je vais mettre une chaîne de caractère on va mettre AB CD je relance et là on se retrouve bien avec voilà aucun nombre n'a été trouvé dans le nœud donc ça fonctionne de la même façon et je pense que c'est tout je pense que c'est tout euh on a le in et on va pouvoir tester normalement là j'ai tout ce qu'il faut j'ai laissé mon return alors non je l'avais commenté on va le remettre le return de Price FO stock et je croise les doigts je vais lancer mais normalement ça devrait être bon je pense qu'on a tout alors je n'ai pas fait de print pour vérifier ce qu'on a à la fin je vais faire un print de cet appel de fonction et là on a 1138.94 donc si je fais 51 point non 51.77 x 22 c'est bien la bonne valeur 1138 94 donc ça fonctionne on a bien le prix du livre en multipliant le prix par la quantité donc vous voyez qu'on a pas mal de choses ici encore une fois quand on fait de la gestion d'erreur quand on met les logur et cetera ça fait beaucoup de codes pour peu de choses à la fin on pourrait mettre juste deux lignes de code voir une ici on pourrait tout faire sur une ligne même mais ce ne serait pas bien gérer les erreurs et si jamais il y avait un problème sur la page comme on l'a vu et bien soit personne ne se rendrait compte parce qu'on ferait un try accept par exemple trop large soit en fait le script planterait à la MO moindre petite erreur qui arrive et on serait on passerait notre temps en fait à à régler les soucis en fait un peu à l'aveugle sans trop savoir pourquoi ça a planté là au moins avec cette gestion d'erreur très précise à tout moment on peut facilement dans le fichier de log voir qu'est-ce qui a planté est-ce que c'est que le price color n'existe pas est-ce que le problème c'est que à l'intérieur de ce nœud qui a été trouvé on a aucun nombre qui a été trouvé donc vous voyez avec ce niveau-là ça va être très facile en cas d'erreur de cibler très précisément quel est le problème et de le régler pour la personne en charge de ça dans cette partie on va remonter un petit peu on va pas faire encore cette fonction principale get all B URL on pourrait faire celle-là get next page URL et get all books URL on page je vais remonter dans l'ordre ici on va prendre celle-ci get all books URL on page donc on va lui passer un tree directement et on va récupérer toutes les URL à partir de cet arbre donc si je viens par exemple sur la première page sur cette page d'index ce qu'on veut c'est récupérer les URL de tous les livres sur la page donc je vais prendre C URL je vais aller dans mon main je vais remettre cette URL à la place de celle spécifique du livre que j'avais et on va faire get all books URL on page et là on va récupérer l'arbre en dehors donc de cette fonction à la différence de getbook Price parce que là en fait on va créer cette cet arbre dans get books URL à chaque fois qu'on va naviguer sur la page on va déjà avoir cet arbre puisqu'on va l'utiliser à la fois pour get next page URL et get all book URL on page donc là encore on va éviter de recréer deux fois le même objet donc ce que je vais faire fa c'est un tree à partir de HTML parsur on va faire une requête avant donc r = request.get à partir de cette URL et là je vais mettre r texte et on va passer cet arbre à notre fonction donc normalement j'ai tout qui est bon ici j'arrive là je vais faire pour l'instant juste un print de Tree et je vais lancer mon script pour vérifier qu'on a bien le html parsur donc ça fonctionne donc maintenant si on retourne analyser notre page ici je vais faire un clic droit un inspect et on va voir où est-ce que se trouve ce lien donc ce lien il se trouve ici on a un href avec notre lien je vais vérifier s'il se retrouve pas euh à d'autres endroits de la page donc je vais copier l'URL je vais voir cette url si elle se trouve à d'autres endroits et effectivement on a un sur de donc elle se retrouve euh également ben en fait ici dans l'image donc on a le image container et on a le H3 ici donc deux endroits à partir desquels on peut récupérer l'url c'est une URL relative comme vous le voyez donc ça il va falloir qu'on le gère pour pouvoir accéder à l'URL de la page parce que si je donne juste catalog/l indiatic euh et qu'on n pas le https booktoscrap.com et cetera bien sûr notre requête ne va pas fonctionner il faut qu'on ait une URL complète donc on va voir comment gérer ce cas de figure et là j'ai deux choix donc soit je vais dans le div image container soit je pars du du a ici alors là on a pas on a une classe ici sur ce div on a le href et ensuite à l'intérieur de ça on a l'image et euh ok donc là moi de voir je pense que les H3 je vais voir aussi combien il y en a sur la page donc je vais faire une recherche des H3 des tags H3 et on en a 20 donc ça correspond précisément au nombre de livres qu'on a sur la page on a 20 livres sur chaque page euh donc je pourrais aussi partir du H3 et je pense que je vais faire ça parce que le le lien ici a plus d'informations on a le titre notamment du livre donc ça peut être pratique pour d'autres choses si jamais on veut on a un problème et qu'on souhaite récupérer le titre du livre pour l'envoyer justement dans notre loger ou quelque chose comme ça ça peut être pratique alors que ici on ne l'a pas avec ce lien euh on l'a dans le dans le alt ici mais on l'a dans le title directement sur le sur le lien donc je vais passer par ça donc on va récupérer en fait tous les tags toutes les balises a donc toutes les balises de lien qui sont à l'intérieur des balises H3 donc on va déjà cibler les balises H3 et vous allez voir que c'est très facile à faire avec select AX grâce à la syntaxe des selcteurs CSS donc ce que je vais faire ici c'est tree.css dans ce cas-ci et pas CSS first puisqu'on va récupérer plusieurs informations notamment 20 dans ce cas-ci donc 20 pour chaque page puisquon a 20 livres par page donc CSS qu'est-ce que je vais chercher déjà les H3 et à l'intérieur de C3 je vais chercher les éléments a donc si je retourne sur ma petite mon petit Ted mémoire sur W3 school si je descends vous allez voir qu'il y a différentes façons de faire on a le cet élément ici donc élément élément et élément avec le symbole plus grand que et un autre élément donc ça vous voyez select all P elements inside div et select all P element where the parent is a div element donc c'est un petit petit peu différent c'est-à-dire que là si je fais H3 a comme ça on va sélectionner tous les liens qu'il y a à l'intérieur des H3 et si je fais avec un symbole plus grand que comme ça on va récupérer tous les liens dont le parent direct est un H3 donc c'est un petit peu différent parce qu'imaginez qu'on est d'autres d'autres choses à l'intérieur de ce H3 d'autres par exemple une liste un div et cetera ce qui n'est pas très conseillé d'ailleurs d'avoir trop de choses à l'intérieur d'un H3 euh en niveau en terme de sémantique HTML donc si je mets met juste le a comme ça on va récupérer tous les liens qui a à l'intérieur du H3 si on met ça ça va être juste les liens direct moi je vais mettre ça je pense que là dans ce cas-ci ça change pas grand-chose puisque si je retourne faire un inspect sur le lien ici je crois qu'on avait vraiment juste le lien à l'intérieur du H3 effectivement donc dans ce cas-ci ça ne change pas grand-chose pour vous montrer je vais je vais faire les deux vous allez voir que normalement on devrait avoir la même chose donc je vais faire un print de la longueur de tout ça je lance mon script et là on devrait avoir 20 ça fonctionne et si j'enlève le symbole plus grand que on a 20 également donc vous voyez dans ce ci il y a pas vraiment de changement avec l'un ou l'autre donc je vais y aller au plus simple et faire juste H3a ou si je veux blinder mon script pour être sûr que ce soit juste les liens directs si jamais la structure du HTML change et qu'on a d'autres choses par la suite à l'intérieur du a avec d'autres liens notamment peut-être ça sera un petit peu bizarre mais bon je peux le spécifier comme ça donc là je vais récupérer toutes les toutes les nodes donc je vais mettre book book books links nodes avec des S partout et ici donc si je fais un print de tout ça vous allez voir qu'on a des nœuds donc c'est voilà node a et nous ce qu'on va devoir récupérer ici c'est le l'attribut href de ces nœuds donc si je prends par exemple le premier avec crochet zéro on a un attribut qui s'appelle attributes qui porte bien son nom justement qui va correspondre à tous les attributs qu'il y a sur cet élément donc là on voit qu'on a un dictionnaire tout simple avec href qui est égal au lien et on avait le title également qui est égal au titre donc là je peux faire un crochet href ou un point get là encore la même chose avec les dictionnaires le point get ne nous retourne pas d'erreur si jamais il y a un problème donc moi je vais mettre ici les crochets euh puisque'on va refaire un try accept avec une gestion des erreurs en cas de problème donc je préfère là encore provoquer l'erreur s'il y en a une en mettant les crochets pour qu'on ait dans ce cas-ci alors avec les crochets ça va être un quiy erreur si je me trompe pas puisqu'on aura pas de clé à shref si jamais sur un lien il y a pas cet attribut à shref on pourra pas y accéder et comme c'est un dictionnaire ici ça sera un key error donc je vais faire ça et sauf qu'il faut que je le fasse pour tous les liens là j'ai pris le premier avec crochet zéro mais moi je veux récupérer ça sur tous les liens donc là on va faire une petite compréhension de liste que vous aimez tant euh pour récupérer tout ça on pourrait faire une boucle normale mais une compréhension de liste ça sera plus rapide donc là on va faire le plus simple comme d'habitude on va dire pour link in book link node et qu'est-ce qu'on récupère pour l'instant on va mettre juste le Link donc si je fais ça ça va absolument rien changer je vais faire une variable que je vais appeler URL et là si je prte URL ici on aura encore une fois que les nodes donc pour l'instant je n'ai rien changé comme je vous dis j'aime bien faire ça pour que ce soit clair qu'est-ce qu'on a début on a juste la boucle normale et qu'est-ce qu'on va faire maintenant on va vouloir concaténer comme je vous avais dit l'URL relatif avec l'URL absolu donc ça on l'avait vu dans un exercice précédent on va utiliser pour ça une bibliothèque de la librairie standard qui s'appelle URL joint qui est disponible dans URL lib.pars on va importer URL join et ça ça va me permettre de joindre l'URL de base donc l'URL de base du site ici avec l'URL relative et ça va s'occuper de toutes les petites particularités qu'il peut y avoir avec des URL donc je vais utiliser ça et là donc à la place de Link je vais utiliser mon url de base alors je pense que celle-là je vais la mettre dans une constante on verra par la suite est-ce qu'on la passe à cette fonction ou pas est-ce que ça change pour l'instant je pense que voilà je vais y aller avec le flux de ma pensée c'est-à-dire qu'on va partir de cette page je pense qu'après il faudra peut-être la modifier en fonction des pages mais pour l'instant je vais mettre donc cette URL dans une constante parce que on va peut-être du coup l'utiliser à plusieurs endroits donc je vais l'appeler base URL et on va mettre oui alors pas le tout le URL on va juste garder voilà voilà la chaîne de caractère et je vais m'en servir du coup pour joindre tout ça ici donc je vais faire URL join de base URL avec Link pour link in booklink node et là en fait ça va être un peu plus spécifique que ça parce que Link on l'a vu quand j'ai lancé le script ici c'est un objet nœud donc nous on veut récupérer l'attribut href donc je vais faire point attributes ici et récupérer sur cet attribut avec les crochets l'attribut href donc normalement je pense qu'on a tout ici euh je vais laisser ça comme ça un print de URL et là on a URL is not defined alors qu'est-ce que j'ai fait j'ai dû oublier quelque chose ah oui j'ai oublié le voilà là on va mettre B URL ici je relance et là on a bien donc les URL complètes et non plus relatives puisque il a concatiner l'URL de base avec l'URL relatif du livre donc ça fonctionne et si je souhaite éviter cette erreur ici avec les crochets je peux donc comme on l'a vu soit mettre un point get problème du get c'est que en fait ça va me retourner non donc si je je met point get et qu'il y a pas de href ici on aura un objet non et moi je veux pas avoir une je veux pas un objet non je veux vraiment être sûr d'avoir des URL ici euh je pourrais mettre une valeur par défaut mais là encore j'ai pas vraiment de valeur par défaut à mettre donc ce que je vais faire c'est plutôt laisser les crochets et vérifier si on a le href dans attribut donc pour ça je peux rajouter une un IF à la fin de ma compréhension de liste ça va commencer à faire une compréhension de liste un petit peu longue mais c'est pas très grave et on peut dire donc que on va faire ça uniquement si on a href in link.attributes donc dans ce dictionnaire link.attributes si on a une clé href donc si on a une paire clé valeur avec cette clé href puisque par défaut on pourrait mettre point Kys ici mais on n'est pas obligé par défaut il va chercher dans les clés donc si on a ce href dans les clés de notre dictionnaire d'attribut associé au lien et bien on peut le récupérer sinon là ça veut dire qu'on va pas on va même pas on va pas avoir un non donc là si on a une URL qui ne contient pas d'attribut href on va juste continuer à la prochaine itération on n' pas de else ici donc c'est juste juste un IF donc on ne va rien récupérer et ça évite de se retrouver avec des URL qui sont des non ou des valeurs par défaut donc là je relance là normalement tout fonctionne et ça n'a rien changé mais voilà c'est juste pour éviter les erreurs ici et il y a peut-être d'autres erreurs qu'on n' pas vu alors dans ce cas-là on peut pas non plus tout prévoir donc ce qu'on peut faire ici si jamais on n'est pas sûr et qu'on veut quand même loguer les erreurs on peut faire un except de exception qui est l'erreur de base en python as e encore une fois puisqu'on va la récupérer et là on peut loguer cette erreur avec notre logueer et dire par exemple une erreur générique donc erreur lors de l'extraction des URL hop des livre et on va intégrer ici notre message d'erreur avec notre F string et là qu'est-ce qu'on va faire bah si jamais on a une erreur et bien on va retourner tout simplement une une liste vide et et là ici je vais retourner les URL hop je vais retourner tout simplement directement cette compréhension de liste donc soit voilà on arrive à récupérer les choses ici normalement comme je vous dis devrait pas y avoir trop de problème si jamais ici on a rien dans tree.css imaginez là je mets un H4 on va tester euh si je mets un H4 je crois pas que j'ai de H4 avec des lien dedans on va voir peut-être mais si on a rien ici si le CSS le sélecteur CSS ne nous retourne rien si je me trompe pas on aura une liste vide et donc on va pouvoir itérer dessus avec notre compréhension de liste c'est juste qu'on va itérer sur une liste qui ne contient rien donc on aura pas d'erreur mais on aura juste une liste vide donc je relance et là effectivement on n pas d'erreur euh je vais mettre n'importe quoi quand même pour être sûr queon a pas voilà des H4 ou quoi euh donc là on n pas d'erreur ça fonctionne bien c'est juste qu'on a pas de lien mais si on a la bonne chose avec le H3 on a ce qu'il faut ici et si jamais on a une erreur quelconque qu'on n pas prévu et bien on va la loguer et on va juste retourner une liste vide là encore pour pouvoir continuer notre extraction puisque là on retourne une liste de chaîne de caractère donc soit ça fonctionne on retourne cette liste de lien soit on retourne une liste vide et on va juste dans notre fonction principale ici get book URL on va juste arriver sur une page il y aura un problème on va le loguer et on va va itérer sur une liste qui sera vide donc on va récupérer aucun prix et on va continuer avec notre extraction et notre scrapping on avance on avance on commence à arriver près de la fin on a déjà toutes ces fonctions qui sont faites la prochaine fonction qu'on va faire on va continuer en remontant dans l'ordre c'est la fonction qui va nous permettre de récupérer l'url de la prochaine page là encore à partir d'un objet tree donc un objet HTML parseur qu'on aura déjà récupéré et qu'on va utiliser pour toutes ces fonctions donc dans cette fonction on va avoir une approche un petit peu différente de ce qu'on a fait précédemment à savoir les approches eafb et lbyyl que vous devez commencer à connaître puisque dans ce cas-ci on ne va pas faire un try accept mais plutôt vérifier qu'on a bien quelque chose qu'on a bien un bouton sur lequel cliquer pour continuer la raison c'est qu'ici on peut arriver à un point où il n'y a plus de page si on arrive à la dernière page il y a plus de page et c'est normal donc c'est un peu différent de ce qu'on avait précédemment par exemple avec des erreurs si on arrive sur une page où il y a pas le prix ou pas la quantité en stock là ce n'est pas normal donc là effectivement on peut avoir des erreurs et dans ce cas-ci on va lever une erreur on va la loguer on va potentiellement comme on l'a fait continuer avec notre script parce qu'on ne veut pas faire planter le script on veut juste indiquer qu'il y a une erreur mais c'est pas un comportement normal là dans le cas de la prochaine page c'est normal à un moment qu'on arrive à la fin il il faut bien un moment qu'il y ait plus de page sur notre librairie on peut pas aller jusqu'à l'infini donc dans ce cas-ci on va vérifier plutôt que de faire un try accept on va vérifier est-ce qu'on a un bouton Next et et si c'est le cas on va retourner quelque chose et sinon on va retourner tout simplement rien pour indiquer que et bien on est arrivé à la fin et qu'il y a plus de page et ça on pourra le gérer à l'intérieur d'une autre fonction donc quand on va appeler cette fonction get next page URL si on a quelque chose et bien on va continuer et quand on arrivera avec cette fonction qui nous retourne non ça veut dire qu'on aura plus de page à parcourir et on va pouvoir sortir par exemple de notre boucle qui bouclera sur toutes les pages du site donc si je reviens sur mon site là on voit qu'on a un bouton Next en bas je vais cliquer dessus et refaire un inspect pour ouvrir l'inspecteur et on voit que c'est un lien avec là encore un lien relatif qu' va falloir gérer pour le rendre en lien absolu avec tout simplement next à l'intérieur et on a un li avec une classe de Next et un li avec une classe de current donc je vais vérifier si le li apparaît d'autres fois on a deux match ici donc le Next ici et en fait le deuxième next c'est le texte tout simplement à l'intérieur du bouton donc on a bien une seule classe next à l'intérieur de ce lii donc ça va être assez facile à cibler donc je vais remettre hop le petit chrome sur le côté et on va récupérer cet élément donc next page node dans ce cas-ci ça va être égal à tree. CSS first puisque là on a qu'un seul bouton Next qu'on souhaite récupérer il y en a qu'un sur la page et il y en a qu'un qu'on souhaite récupérer et dans ce cas-ci ça va être donc le li avec le point next et ce qu'on veut c'est pas cet élément mais c'est l'élément qui se trouve à l'intérieur si vous vous souvenez bien on avait un lien à l'intérieur de cet élément nous ce qu'on veut c'est le href qui est sur ce lien donc ce qu'on va faire c'est ici récupérer le lien qui est directement à l'intérieur donc je vais mettre le symbole supérieur à pour récupérer le lien dont le parent direct et le li.nex et avec le CSS first on va récupérer normalement juste celui-là donc je vais faire un print de next page node avec les crochets href pour vérifier si on récupère bien les données alors là il faut que je change un petit peu mon script on va faire le GET next page URL on part de notre URL de base on lui passe le tree je relance et là alors on a un petit problème ah oui puisque j'ai fait directement ici j'ai pas fait sur les attributs il faut faire bien sûr sur les attributs et non pas sur le nœud lui-même et là on récupère bien le catalogue page Ti 2 donc qu'est-ce qu'on va faire ici comme je vous ai dit on va vérifier déjà si on a quelque chose sur cet attribut si on a un next page node donc je vais enlever ce print donc qu'est-ce qu'on veut vérifier ici est-ce qu'on a un node un nœud qui est existant donc est-ce qu'on a trouvé ce bouton Next et est-ce que on a également un href sur ce lien là encore on va faire plusieurs vérifications d'un coup puisque ce n'est pas tout d'avoir le nœud il faut aussi qu'il y ait l'information sur le nœud donc on va dire if next page node end euh href in next page node next page node comme ceci point attributes donc si on a un attribut href à l'intérieur de ce dictionnaire et bien on va continuer et on va récupérer la valeur de cet attribut et donc là dans ce cas-ci on va faire un return tout simplement euh alors on va pas le faire encore puisqu'il va falloir qu'on fasse notre URL join avant euh on va faire un next page nodeattributes crochet href et on va faire un URL joint de base URL base URL avec cet attribut href et là on va pouvoir le retourner on va retourner tout ça et si ce n'est pas le cas et bien là on va faire un return de N et on va faire un petit loger mais cette fois-ci ce n'est pas une erreur comme je vous l'ai dit on va pas faire erreur puisque ce n'est pas un problème qu'il n'y ait pas de bouton on va juste faire un point dbug pour indiquer point dbug ou point info à voir pour indiquer c'est pas vraiment un débug là c'est plus une information pour dire qu'il n'y a plus de page à scrappé donc on va dire ici on est arrivé à la dernière page voilà c'est pas très bien dit je pense qu'on pourrait changer on pourrait dire euh aucun bouton Next trouvé sur la page voilà et on retourne non ici alors je vais changer mon mon annotation de type ici et on va mettre un opérateur ou puisque ça peut être soit une chaîne de caractère soit un objet non qu'on retourne dans ce cas-ci c'est une chaîne de caractère et dans ce cas-ci c'est un objet non donc voilà pour cette fonction je vais quand même la tester avant de terminer cette vidéo je lance et là on n' pas fait de print au niveau de notre main donc forcément on ne voit rien je vais faire un print de tout ça et là normalement on a voilà l'URL complète avec catalog/page 2 donc l'URL absolu et non plus relatif puisqu'on a fait le URL join et on peut donc passer à la page suivante à partir de cette page donc voilà on commence à avoir presque toute la logique on a fait tout ça et maintenant on va pouvoir presque boucler le tout c'est-à-dire arriver sur cette dernière fonction qui va à partir de cette page récupérer tous les URL des bouquins sur la page avec cette fonction passer à la page suivante et refaire la même chose pour constituer notre grande liste qui va contenir toutes les ur URL qu'on peut scrapper pour récupérer ensuite les prix et ensuite additionner donc comme on l'a fait dans la fonction main ici on a déjà la logique donc récupérer tout ce qu'il nous faut à partir de ces URL pour avoir le prix total de la librairie alors dans cette partie on va s'attaquer à cette dernière fonction dans laquelle on va parcourir toutes les pages pour récupérer toutes les URL des livres sur toutes les pages à partir de l'URL de base qui sera donc cette base URL donc ce que je vais faire c'est commencer par faire une liste vide qui pour l'instant ne va rien contenir mais on va la remplir avec toutes les URL qu'on aura trouvé sur chaque page au fur et à mesure ce que je vais faire moi ici c'est une boucle while alors on pourrait faire de différentes façons là je pense qu'une boucle while c'est pas mal et comme on ne sait pas à l'avance combien de pages on va avoir on va faire tout simplement une boucle while true et on va s'arrêter quand on ne trouvera plus de prochaines page donc c'est-à-dire qu'on va récupérer l'url de la prochaine page et comme on l'a vu quand on a fait cette fonction get next page URL ça peut retourner soit un string soit un non donc si on fait une vérification on va faire un truc du genre if get next page URL et ou plutôt if not donc if not get next page URL et bien là on fera un break pour sortir de notre boucle true et et ne plus ne plus continuer tout simplement notre boucle donc qu'est-ce qu'on va faire ici on va faire une requête donc je vais faire request.get vers notre URL on va récupérer ça dans un objet response on va refaire un response. race for status et on va gérer les er de requête potentielle avec un try except on va faire une exception vous commencez à connaître la chanson sur request.exception.request exception as e et on va dire que s'il y a un problème et bien on a une erreur donc erreur lors de la requête HTTP sur la page et là on va mettre l'URL de la page en question et on va mettre notre erreur à la fin ici comme ça et on va faire un F et qu'est-ce qu'on va faire ici alors est-ce qu'on arrête non on va faire un continue dans ce cas-ci parce qu'on est avec notre boucle while donc là l'idée c'est que si sur une une page spécifique à un moment on n arrive pas à à récupérer à récupérer le résultat de la requête donc si on a une page 404 ou une erreur de ce genre et bien on va tout simplement continuer à la prochaine page là encore mettre dans notre log queil y a eu un problème sur la page à cette url précis donc on pourra avec cette information savoir précisément quelle est la page qui pose problème euh et voilà et on va juste continuer avec notre scrapping pour ne pas l'interrompre donc une fois qu'on a fait notre try accept on va faire un HTML parsur pour récupérer le compte puisque on en a besoin pour nos autres fonctions pour notamment cette fonction et cette fonction donc on va le faire une fois comme je vous disais ici et ensuite passer cet objet à ces fonctions pour ne pas le recréer donc je vais faire response.text ici et on va récupérer donc les URL de tous les livres donc books URL qui va être égal à get all books URLs on page là je vais lui passer notre arbre et on va ajouter ces URL à notre liste d'URL donc on va faire un extend pour ajouter toutes ces URL on ne fait pas un happen sinon on va avoir une liste liste de listes moi ce que je veux c'est une liste flat comme on dit en bon français donc une liste à un niveau qui va contenir toutes les URL donc là dans ce cas-ci on aura une liste avec 1000 éléments à l'intérieur de cette liste et ensuite il faut que je prenne la prochaine page donc on va faire next page URL ég à get next page URL on va lui passer notre tree et on va dire if not next page URL du coup et bien on fait un break tout simplement et là je fais un return de toutes nos URL et voilà je suis allé un petit peu vite là j'ai tout fait à la suite comme ça me venait mais vous voyez que une fois qu'on a tous les éléments dont on a besoin en fait et bien et qu'on a des noms assez explicites comme on l'a fait euh ça coule de source on a pas besoin trop de se poser la question puisque toute la logique en fait est déjà faite ailleurs donc là on va vérifier quand même on a notre URL tant que c'est true on fait un try donc on essayer de récupérer l'url de la page euh ensuite HTML parser response.text donc on récupère le contenu dans notre HTML parseur de la page en question on récupère toutes les URL on les ajoute à notre liste on récupère la prochaine page s'il y a pas de prochaine page on casse et sinon on revient ici et on continue avec la prochaine page donc je vais tester tout ça je vais mettre un petit loger ici loger.info pour qu'on voit quelque chose donc loger.info et on va dire scrapping et je vais mettre un f string scrapping page at et on va insérer l'URL ici donc je lance le script on va faire donc get all book URL on va revenir ici et on va faire get all book URL à partir de base base URL base URL comme ceci voilà j'enlève tout ça et normalement c'est bon donc je lance on croise les doigts on va voir ce que ça donne info scrapping page scrapping page et là on voit déjà qu'on a un petit problème puisque ça scrape toujours la la même page en fait alors qu'est-ce que j'ai fait ici donc je j'ai dû avoir un petit problème de logique on va analyser tout ça ensemble et et oui effectivement puisqueen fait oui c'est logique je récupère next page URL ici mais en fait je je ah oui j'ai en fait je je boucle toujours sur l'URL de base donc là on a un petit problème de logique en fait ce qu'il faut c'est à chaque fois que je récupère donc que je mette le next page URL le problème c'est que là on a des URL euh là on a fait un URL à partir de base URL aussi alors là vous voyez on a un problème de logique qu'on avait pas anticipé puisque là en fait on fait le join toujours à partir de base URL euh donc donc effectivement ça ça ne peut pas marcher en fait il faut qu'on lui donne une URL qui ne soit pas toujours l'URL de base donc je vais rajouter ça dans ma fonction et donc je vais mettre un paramètre URL ici qui va être une chaîne de caractère on va le rajouter là param URL qui va être URL de la page courante et là à la place de base URL du coup on va mettre URL et on va concaténer cet URL avec l'URL de la page suivante donc je reviens ici et là on va adapter un petit peu notre script donc on a notre next page URL on a notre URL de base mais du coup cet URL va changer donc c'est logique donc donc là en fait ce que je vais faire c'est écraser la variable puisque on va on va on va partir d'une URL en fait donc partir de l'URL qu'on va passer à getthbook URL qui va être l'URL de base mais ensuite on va mettre à jour cette url puisqu'on va récupérer l'url de la prochaine page donc on va lui passer ici l'URL actuel on écrase notre URL là-dedans et comme ça on peut quand on revient dans le while passer à la page d'après donc je sais pas si c'est très clair je vais refaire le cheminement avec vous on commence notre boucle on récupère donc les le contenu de la première URL qui va être l'URL de base on fait ce qu'on a à faire ici avec notre try accept avec la récupération des URL on ajoute tout ça à notre liste ensuite on récupère l'url de la prochaine page et on écrase on refait une variable URL si ça n'est si ça ne contient rien donc là encore ça ne change pas on sort et si ça contient quelque chose et bien ça sera l'url de la prochaine page et quand on revient en haut de notre while et bien on sera avec l'url de la prochaine page on va faire une requête sur cette nouvelle URL donc normalement là ça fonctionne je vais relancer le script si je n'ai rien oublié et on va voir et là effectivement on a bien donc notre première page 2 3 4 5 6 et cetera donc ce que je vais faire ici c'est euh c'est vérifier déjà qu'on a bien tout ce qu'il faut dans les URL donc je vais mettre un point de débug ici pour vérifier que cette fonction fonctionne bien également donc je relance cette fois-ci le script en dbug pour vérifier notre liste donc là on a notre liste URL qui contient 20 éléments book to scrap catalog light in the aTIC c'est bon ok là on a 20 éléments donc on commence à zé on en a 20 on va continuer je fais un resume du programme on continue là on a 20 autres éléments avec in wake how music work B Song et cetera et on continue comme ça et si je fais un resum voilà on va faire grossir notre liste là on va être rendu à 60 et cetera et cetera donc ça fonctionne bien et on peut comme ça récupérer les URL de toute la bibliothèque et on va pouvoir ensuite passer au scrapping puisque là on récupère tout ce qu'il nous faut donc on fait getb URL mais là nous ce qui va nous intéresser c'est bien entendu de récupérer le prix de tout ça donc on va voir ça tout de suite dans la prochaine partie donc on arrive à la fin de notre script on va vérifier maintenant qu'on arrive bien à récupérer le prix des livres et qu'on arrive bien à faire le total donc pour que ce soit pas trop long je vais faire le test sur deux trois pages et on va voir si tout fonctionne et et après on pourra lancer sur les 50 pages pour voir si tout fonctionne sur l'entièreté de la bibliothèque donc là ce que je vais faire je vais juste faire un petit compteur on va dire page number euh égal à 0 et on va incrémenter ce page number voilà euh ici page number + = 1 et on va dire if page number euh plus grand que 2 on va faire un break donc euh je vais commencer déjà par récupérer allbox URL je vais mettre un point de débug ici je vais lancer mon script alors je vais appeler le main puisque là hop je fais ça ici donc je vais à la place lancer le main et on va vérifier qu'on a déjà donc la toutes les URL donc je lance on récupère bien les trois première page là on a vu ici hop le scrapping avec notre info donc le logger qui nous indique scrapping page scrapping page 2 3 ça fonctionne là on a 60 éléments dans notre liste donc c'est bon on va continuer on arrive dans notre boucle on récupère le prix du premier livre ça fonctionne on continue on récupère le prix du deuxème livre ça fonctionne 3è livre et cetera donc on va on va pas faire chaque livre comme ça avec le stepover à chaque fois on va cliquer sur resume pour voir ce que c'est ça donne on va retourner dans notre console et là on a rien donc on va faire un petit loger point info pour vérifier que que ça fonctionne bien parce que là on a aucune information donc dans le getbook price ici je vais quand même mettre un loger info quelque part pour qu'on sache ce qui se passe donc ici dans le try on va faire logger.info et on va dire scrapping book et je vais faire un string scrapping book at on va dire dans plutôt getting euh ouais getbook price at et on va mettre l'URL ici donc donc je relance mon script je vérifie que tout fonctionne on a le info on récupère déjà les trois premières pages et ensuite on récupère le book price à partir des URL donc ça fonctionne ça fonctionne on a bien ce qu'il faut et ah là on a des erreurs alors vous voyez erreur lors de la requête donc vous voyez exactement ce que c'était pas prévu mais c'est exactement ce que je voulais potentiellement vous montrer c'est que quand on a des erreurs on les voit on va les voir également si je vais voir dans mon fichier de log voilà ici on a les erreurs voilà erreurs HTTP donc vous voyez qu'ici on n pas les les infos on n pas le l'info ça nous sert pas à grand-chose en fait nous ce qu'on veut voir c'est erreur donc là on voit qu'on a une erreur à la ligne 101 donc si je vais à la ligne 101 c'est une erreur sur la requête donc qu'est-ce qu'on a comme erreur je retourne voir ici not F for URL donc 404 on a une erreur 404 à l'URL tout ah oui parce que ok je pense que je vois le problème je reviens oui ok alors là en fait on a on a un slash catalogue et on l'a plus après et si je vais voir l'UR effectivement là on a un 404 donc en fait c'est un problème avec l'URL et je pense si je reviens voir là je pense que c'est le même problème qu'on a avec le GET next page URL c'est que voilà là ici pareil en fait on donne l'URL de base et l'URL est différente selon donc si je reviens voir sur Chrome l'URL va être différente en fonction des pages puisque là sur la page d'accueil on va concaténer si je vais voir le inspect ici on a catalog/s me free et si je vais voir sur la page 2 hop et que je je regarde là in her wake là voilà ok alors là on a une différence vous voyez ici on a plus le catalogue puisque là on a le catalogue en fait dans l'URL ici donc l'URL relatif ne contient plus le catalogue donc nous en fait ce qu'on fait c'est qu'on fait juste ajouter à l'URL de base qui est book to scrap on ajoute le inhwake et il manque le catalogue donc là en fait ce qu'il faut faire c'est exactement la même chose que ce qu'on avait fait ici avec le GET next page c'est qu'il faut lui passer l'URL donc je vais la rajouter ici URL string on va rajouter le paramètre aussi hop paramètre URL URL de la page qui contient les livres et là à la place de base URL on va mettre URL et on va la passer également si je reviens donc désolé je vais un petit peu vite je vais ralentir euh donc on a rajouté un paramètre URL à get all books URL on page donc c'est quand on arrive sur une page et qu'on veut récupérer les URL de tous les livres sur la page comme l'URL de la page est différent et que on a une URL relative qui ne contient pas le catalogue on peut pas repartir de l'URL de base donc il faut passer cet URL à notre fonction donc là j'ai juste rajouter le paramètre dans la doc string et je l'ai remplacé ici quand on fait le URL join pour ne pas utiliser l'URL de base mais l'URL qu'on va passer donc ça il faut la passer bien entendu ici aussi quand on va récupérer get books URL on passe le tree et on va aussi lui passer donc l'URL de la page actuel comme ça on va pouvoir bien concaténer l'URL de la page donc/catalog/ page 2 si je me souviens bien si je vais voir ici donc on va sur la page 3 par exemple page 3 ici on a catalog/page 3 donc on va concaténer tout ça avec l'URL relatif donc je pense que c'est bon je vais relancer le script pour vérifier hop si on a une erreur de toute façon avec la gestion d'erreur qu'on a faite on devrait l'avoir donc getbook price on a bien le catalogue qui est correctement mis je continue et et et suspense et voilà et ça fonctionne je reconnais le INH wake qui est le l'URL qui ne fonctionnait pas et là effectivement ça fonctionne on a plus de problème donc getting price ça fonctionne parfaitement et là ce qu'on pourrait faire aussi parce que là on fait juste getbook price on pourrait changer le loger on pourrait le changer ou en mettre un autre dans le getbook price on pourrait le mettre à la fin on pourrait le déplacer ici faire une variable intermédiaire pour ça donc là j'utilise le raccourci clavier option commande V qui me permet de créer une variable intermédiaire très facilement vous pouvez retrouver le raccourci en faisant clic droit et en allant dans refactor introduce variable ici et ça va créer une variable donc price stock vous voyez en plus il a trouvé un bon nom directement et là du coup on va dire getbook price à URL found hop et là on va mettre price stock voilà euh ouais on peut même oui ok je vais laisser ça comme ça donc je relance et là comme ça dans notre information on a directement voilà fin 1138 tac tac tac ok super donc ça fonctionne bien on va pouvoir lancer un test complet et vérifier que on a bien récupéré le prix total donc je vais faire un print de tout ça et normalement là encore comme on l'a vu vu qu'on a géré les erreurs d'une façon qui ne qui permet de continuer le script euh si j'ai bien fait ça même s'il y a des problèmes comme vous l'avez vu là on avait des erreurs 404 mais ça n'a pas arrêté le script donc si on a des erreurs queles qu'elles soi il va les loguer mais ça va aller au bout et s'il y a des erreurs je pourrais aller voir les erreurs dans le fichier de log alors bien sûr j'ai oublié une chose importante là on voit que j'ai un nombre qui n'est pas cohérent et c'est parce que tout simplement j'ai laissé mon page number ici avec le break au bout de deux trois pages donc forcément ça n'a pas donné grand-chose donc je vais relancer le script n'oubliez pas d'enlever cette condition si vous l'aviez rajouté pour bien scrapper toutes les pages donc là si je continue on voit qu'on va bien continuer jusqu'à la page 50 comme ceci voilà le script a donc terminé alors là on a eu un petit conflit entre mon print et le dernier loger mais voilà on a bien la valeur qui est affichée qui est cohérente avec les autres tests que j'avais fait on est donc à 300188,27 € comme prix total de la bibliothèque et on voit ici qu'on a bien donc réussi à scrapper on n pas d'erreur là tous les logs que j'ai c'est des infos et je suis allé voir dans le fichier de log et on a aucune erreur non plus donc on a bien un script qui fonctionne dans ce cas-ci avec 100 % des requêtes qui ont été correctement effectué on a donc la première partie qui a bien fonctionné avec le scrapping de toutes les pages donc on récupère à partir de la page d'index ensuite toutes les autres pages on a notre loger qui nous indique par la suite avec ce log ici qu'aucun bouton Next n'a été trouvé donc c'est logique puisqu'on arrive à la page 50 et ensuite on continue avec le scrapping des 1000 livres avec à chaque fois la récupération du prix total en fonction du prix et de la quantité en stock donc voilà notre script fonctionne et gère correctement les erreurs qu'on a identifié comme possible à l'intérieur de notre script vous avez probablement remarquer quand on a lancé le script que ça prend pas mal de temps à exécuter si je regarde ici on a terminé à 22h35 et si je remonte tout en haut on va voir qu'on a commencé à 22h26 donc on a un peu près 9 minutes pour extraire toutes ces URL et c'est asse c'est long comme je vous avais dit avec selectolx on va beaucoup plus vite qu'avec beautiful soup mais ce qui prend le plus de temps ici c'est le fait qu'on utilise pas une des merveille de la librairie request que sont les sessions puisque là en fait qu'est-ce qu'on fait actuellement et bien on ouvre un nouveau navigateur si vous voulez à chaque fois on fait une nouvelle connexion à chaque fois qu'on utilise le module request donc dans le Main ici quand je vais récupérer toutes les URL avec cette fonction quand je fais un une requête ici à chaque fois c'est exactement la même chose que si vous vous ouvriez chrome que vous vous rendiez sur la page et que vous fermez Chrome vous l'ouvrez de nouveau et cetera et cetera donc ce n'est pas très pratique et pour ça on peut donc utiliser les sessions alors une session on peut la créer avec ce qu'on appelle un context manager donc le fameux with qu'on utilise par exemple pour ouvrir un fichier ça va avoir pour effet de fermer la session automatiquement une fois qu'on sort de cette structure donc ce que je vais faire c'est à partir de request.session on va créer une session donc en tant que session donc session comme ça avec de que je vais stocker dans cette variable donc c'est un objet session ici on met les parenthèses pour créer une instance qu'on récupère dans cette variable session et on va indenter tout ça donc toute notre boucle ici à l'intérieur de ce contexte manager et ici et bien il ne reste plus qu'à utiliser cet objet session à la place de request et là en fait ce que ça va faire et bien c'est exactement comme si on ouvrait une seule fois un navigateur et qu'ensuite on naviguait d'une page à l'autre sans fermer le navigateur et vous allez voir que ça a énormément d'impact sur les performances vous allez voir que ça va beaucoup plus vite je vais relancer le script et vous allez voir que là ça va très très vite on va presque 10 fois plus vite donc ça couplé au fait d'utiliser selectolax au lieu de beautiful soup ça va vraiment grandement augmenter les performances de notre script là vous voyez qu'on repasse pour le getbook price ici avec une session différente à chaque fois et on voit vraiment le ralentissement qui se fait donc ce que je vais faire c'est également le faire pour notre getbook price la différence avec le getbook price c'est que c'est unitaire ici en fait on a notre request qui se fait dans la F fction euh et donc on va avoir le la boucle qui se fait dans notre main ici on a le getbook Price qui se fait à l'intérieur de cette boucle donc ce qu'on va faire c'est laisser le choix soit d'utiliser une requête à chaque fois si on veut tester de façon unitaire par exemple cette fonction soit lui passer un objet session donc je vais le rajouter ici en paramètres en indiquant que c'est un objet de type request. session et on va le mettre égal à non par défaut puisque on souhaite permettre à quelqu'un si cette variable n'est pas définie de juste utiliser une requête normale donc là ce que je vais faire faire c'est vérifier est-ce qu'on a une session donc si on a un objet session qui a été passé on va utiliser cette session à la place de request et sinon donc on fait un else on va utiliser ce qu'on avait c'est-à-dire tout simplement un request pointget donc request comme ceci pointget URL et ce qu'on va faire c'est au niveau de la boucle donc si je reviens dans mon main ici et bien on va encapsuler de nouveau notre boucle à l'intérieur d'un contexte manager donc on va faire with request.session donc comme on l'a fait avec notre boucle while on met tout ça à l'intérieur du context manager et on va lui passer notre session comme ceci en argument et là vous allez voir que ça va aller vraiment vraiment beaucoup plus vite donc je vais le relancer et vous allez voir autant au niveau du scrapping ici de toutes les pages on fait tout ça presque en quelques secondes là où avant ça prenait presque une minute et pareil ici vous voyez à quel point ça va beaucoup beaucoup beaucoup plus vite donc je vais le laisser tourner vous allez voir combien de temps ça prend donc comme je vous disais on était à 9 minutes sans les session et là je pense que si on arrive à une ou deux minutes ce sera vraiment le maximum et voilà donc 22h51 et 42 secondes et si on revient au début on était à 22h49 donc ça a pris un peu près voilà un peu moins de 3 minutes si mes calculs sont bons donc vous voyez que on a un gros gros gain de performance ici bien sûr là on s'éloigne un petit peu d'un scrapping qu'on pourrait dire éthique puisque ça va très vite on pourrait encore améliorer tout ça on pourrait faire des requêes insynchrones on pourrait lancer plusieurs threads on pourrait utiliser d'autres outils qui feraient ça beaucoup plus facilement pour nous également mais là le but est quand même de rester raisonnable ce qu'on pourrait faire pour rajouter un petit peu d'umain c'est par exemple faire un time time. sleep ici avec un nombre aléatoire on pourrait faire donc un nombre aléatoire avec uniforme entre 0,5 et 1 et là bien sûr je n'ai pas importé ces librairies je vais les importer et là ce que ça ferait c'est juste attendre un petit peu entre chaque requête donc là vous allez me dire quel est l'intérêt si finalement on a augmenté les performances d'un côté pour les ralentir par la suite faut savoir que c'est toujours mieux quand même d'optimiser le script comme ceci avec les sessions ça a un impact quand même moindre sur les performances d'utiliser les sessions plutôt que de recréer un objet request à chaque fois et de toute façon c'est mieux d'avoir quelque chose qui est le plus rapide possible et après vous vous contrôlez en fait la rapidité que vous souhaitez avoir plutôt que d'avoir un script qui subit des performances qui sont négligées à cause d'une d'un code qui n'est pas optimal donc moi je préfère comme ça optimiser mon code en utilisant des outils comme selectolx en utilisant des sessions pour avoir le code le plus optimisé possible qui consomme le moins de mémoire et qui est optimal en terme de rapidité et après si je souhaite vraiment doser mon mon scrapping et bien pass par un time point slep comme ceci pour par exemple doser très précisément le temps que je souhaite attendre entre chaque requête il y a d'autres choses qu'on peut faire aussi pour ce script pour l'améliorer bien sûr on pourrait utiliser un yield et un générateur donc à la place de tout stocker dans une liste là pour l'instant on a 1000 URL donc ce n'est pas encore trop mais imaginez sur un site un peu plus grand ça serait pas très efficace d'avoir toutes ces URL dans une seule grosse liste donc il y a plein d'autres petites choses qu'on peut faire on peut toujours améliorer un script c'est sûr mais là au moins vous voyez que on a quelque chose qui est bien séparé avec une bonne bonne gestion des erreurs et qui permet d'avoir un aperçu de Comment notre script fonctionne faut savoir aussi qu'avec les logers donc dès qu'on fait un print dans un terminal dès qu'on affiche quelque chose ça ralentit aussi un petit peu le script donc c'est aussi à prendre en compte mais normalement une fois qu'on a ce script là on aura pas trop d'intérêt en production d'avoir ce loger qui log dans le terminal ce qu'on va garder c'est uniquement le log des problèmes avec le warning les erreurs et les critical qui seront logués dans le fichier qu'on peut aller voir quand on le souhaite pour vérifier s'il y a eu des erreurs lors du scrapping et voilà pour cet exercice j'espère que ça vous a plu là encore je le précise on aurait pu faire beaucoup plus court et on peut faire aussi bien différemment pour la gestion des erreurs il n'y a pas qu'une seule façon de faire j'ai essayé de vous expliquer au maximum la logique qu'il y avait derrière tout ça ça fait des vidéo un petit peu longue mais j'espère que ça vous permet vraiment de voir ce qu'on peut faire avec un script qui va un peu plus loin que quelques lignes de code qui plante dès qu'on a une information qui n'est pas valide sur la page web qu'on va récupérer j'en profite pour faire une petite parenthèse de 10 secondes si tu souhaites te former à Python une seule adresse docstring.fr tu peux te créer un compte c'est gratuit et tu auras beaucoup de contenu des exercices des quiz des glossires des formations des projets des parcours cré-toi un compte tu vas pouvoir découvrir tout ça et n'hésite pas également à nous rejoindre sur le serveur discord de de doc string on a des challenges toutes les semaines des vocaux des salons d'aide donc rejoins-nous tous les liens sont dans la description dans le monde du scrapping de donné sur le web il existe un conflit latant entre les scrappeurs et les sites web beaucoup de ces sites résistent activement au scrapping et parfois ils ont de bonnes raisons de le faire un scrapping excessif peut en effet sérieusement affecter les performances d'un site web et nécessiter des investissements importants en infrastructure pour maintenir la qualité de service c'est pourquoi les sites Web ont dû trouver des moyens de se protéger contre des pratiques abusives de scrapping c'est un peu comme la conduite automobile si tout le monde respectait les règles de la route il n'y aurait pas besoin de radar d'alcotest ou encore de ralentisseurs malheureusement la nature humaine nous pousse bien souvent à ne pas vouloir respecter les règles c'est donc en réaction à ces abus que des barrières se mettent en place mais il y a une autre dimension à cette lutte de nombreux sites web utilisent des données publiques fournies par leurs utilisateurs et ils préfèrent ne pas avoir ses données réutilisées ailleurs les données c'est le pétrole du 21e siècle une ressource précieuse que les entreprises cherchent à protéger et à exploiter à leur avantage c'est pourquoi certains sites comme Amazon Airbnb ou plus proche de nous le boncoin par exemple déploie des défenses actives contre le scrapping parce qu'ils savent qu'il disposent de nombreuses données qui peuvent intéresser un large public ou des concurrents mais le scrapping n'est pas toujours négatif pour ces sites pour Amazon il est bénéfique que de nombreux produits dérivés se développent grâce à leurs données pour d'autres sites autoriser le scrapping dans les limites du raisonnable ça peut leur permettre d'éviter d'avoir à entretenir une API coûteuse en temps de développement il laisse ainsi les utilisateurs naviguer de façon raisonnable sur leur site pour récupérer les informations dont ils ont besoin besoin et ils économisent ainsi du temps de développement et de l'argent le scrapping navigue donc dans un équilibre délicat entre ces deux mondes certains sites adoptent des approche très défensif pour empêcher le scrapping et rendre la tâche très ardue c'est cette tension persistante entre l'accès aux données et la protection de celle-ci qui continue ainsi de définir le paysage du scrapping sur le web dans les parties qui vont suivre on va s'intéresser à un sujet très important ce que dit la loi et ce qu'il est possible ou non de faire dans le cadre de l'extraction de données sur le web alors dit comme ça ça ne paraît pas forcément passionnant mais vous allez voir que la jurisprudence sur le sujet est assez intéressante notamment dans le cas d'une affaire qui concerne le bon coin alors bien sûr tout ce que je vais vous dire dans ces parties c'est le résultat de mes recherches et de mes échanges avec les acteurs du marché mais ça ne vaut pas un avis juridique si vous avez le moindre doute sur vos activités de scrapping bien sûr demandz un avis juridique compétent qui pourra également vous couvrir ce qui n'est pas le cas de ma vidéo Youtube qui n'aura aucune valeur en cas de problème dans vos activités de scrapping les CGU qui définissent les conditions générales d'utilisation elles sont propres à chaque site mais si vous allez voir les CGU de la plupart des sites web l'écrasante majorité vous indiquera qu'il est interdit d'utiliser des robots pour effectuer du scrapping sur leur site mais dans la plupart des pays ce ne sont pas les sites web eux-mêmes qui font la pluie et le BE temp mais la loi et dans la matière c'est le droit sur la propriété intellectuelle qui fait référence en France et la loi elle dit que lorsqu'une base de données est mise à la disposition du public par le titulaire des droits celui-ci ne peut interdire je cite l'extraction ou la réutilisation d'une partie non substantielle apprécié de façon qualitative ou quantitative du contenu de la base par la personne qui a licitement accès autrement dit la loi est très claire la collecte de données en ligne est entièrement légale mais à condition de respecter plusieurs conditions précises la première les données doivent être publiques la deuxième l'accès doit être licite et la troisième la partie doit être non substantielle données publiques ça veut dire que ces données doivent être accessibles même si vous n'avez pas par exemple un compte sur le site web qui est ciblé accès licite c'est assez logique ça veut dire que si vous accédez à ce site d'une façon détournée piratée bien sûr ça n'est pas valide partie non substantielle ça veut dire que vous devez récupérer seulement quelques parties qui vous intéressent et non pas l'intégralité des données du site web pour la partie non substantielle des données qui sont récupérées il est indiqué qu'elle doit être appréciée de façon qualitative ou quantitative si vous ne comprenez pas que ça veut dire je vais vous expliquer tout de suite effectivement la loi elle indique bien que le problème il ne porte pas uniquement sur la quantité de données que vous récupérez mais aussi le type de données je vais vous donner un exemple imaginez un site web qui fournit des analyses financières détaillées et exclusives sur les marchés boursiers ces données sont publiques mais ce site est reconnu pour ses prévisions très précises et ses analyses pointues qui sont le résultat d'une recherche approfondie et d'une expertise particulière dans un cas comme celui-ci même si vous ne copiez qu'une petite partie de leur contenu comme cette cette analyse fine du marché boursier ça peut-être considéré comme un problème qualitatif parce qu'effectivement même si la quantité des données copiées est faible une seule analyse parmi des milliers de pages de contenu sur le site l'importance de cette information est très élevée c'est une analyse exclusive et potentiellement très influente et sa valeur repose donc sur son contenu unique et son expertise donc sa qualité plus que sur la quantité de texte ou de données qu'elle contient donc même une petite extraction de données peut-être problématique si elle porte sur des éléments qui con tiue le cœur ou la valeur unique de la base de données que vous extrayez dans cet exemple la copie de cette analyse pourrait avoir un impact significatif sur la valeur et l'unicité du service qui est offert par le site web ce qui pourrait en faire une extraction qualitative problématique selon le Code de la Propriété intellectuel français dans l'Union européenne on a depuis quelques années le fameux rgpd le règlement général sur la protection des données qui a été lancé en 201 18 pour donner au public le contrôle de ses propres données le rgpd il limite ce que les entreprises peuvent faire avec des données personnelles identifiables teles que les noms les adresses les numéros de téléphone ou les adresses email la réglementation ne déclare pas que la collecte de données est illégale mais elle impose des limites à ce que les entreprises peuvent faire lorsqu'il s'agit de les extraire par exemple les entreprises doivent obtenir un consentement explicite des consommateurs pour pouvoir collecter des données à partir d'un site web en d'autres termes ce n'est pas parce que vous pouvez récupérer des inform formtion personnelles qui sont accessibles publiquement sur un site web que vous pouvez en faire ce que vous voulez la récupération de données comme des adresses mail ou des numéro de téléphone pour contacter les personnes concernées sans leur accord et à des fins de démarchage elle est donc prohibée si vous n'avez pas l'autorisation explicite des personnes concernées c'est notamment pour cette raison que vous l'avez peut-être remarqué de plus en plus sur les sites de petites annonces ces données personnelles ne sont plus affiché publiquement ainsi si vous souhaitez contacter quelqu'un le numéro de téléphone ou l'adresse mail seront masqués par défaut et c'est vous qui devez effectuer une demande au site en question pour vous procurer cette information ou même passer par le service de messagerie interne au site pour éviter que ces informations ne soient jamais divulguées dans une affaire judiciaire récente le site entreparticulier.com a été accusé de scrapper les annonces immobilières du site le boncoin sur 70 annonces de vente 69 affichai le logo LBC également sur 100 annonces de location et de vacan 96 avait repris les données du site le boncoin à l'exception des numéros de téléphone la cour elle indique trois éléments qui vont à l'encontre de la loi la collecte de données elle est substantielle les quantités de données collectées sont donc importantes on a également une surreprésentation du contenu collecté puisque dans la catégorie d'annonces ciblé on avait 96 % des annonces qui venaient du scrapping de le boncoin et dernier point et non des moindres la collecte s'est fait à des fins de concurrence directe puisque entreparticulier.com est un concurrent direct de le boncoin le jugement il indique donc une demande d' d'indemnisation de 50000 € parce que la société leboncoin elle a dû organiser des parades face à ses extractions substantielles et consacrer un investissement humain et financier à la gestion des plaintes des utilisateurs qui étaient mécontents de la réutilisation de leur annonce pour ceux que ça intéresse je vous mets des liens qui vont un peu plus loin dans les sources de la vidéo pour pouvoir lire en détail les résultats de ce procès dans cette partie je vais vous présenter deux exemples de scrapping le premier est en fait de façon raisonnable et le deuxième étant un scrapping qui peut potentiellement vous poser des problèmes avec la loi pour le premier exemple on imagine que vous êtes un particulier en recherche d'un bien immobilier à acheter dans la banlieue de Paris tous les jours vous parcourez les trois premières pages d'un site d'annonce immobilière dans cette région au bout de quelques semaines à effectuer cette tâche à la main vous décidez de l'automatiser grâce à vos compétences avec Python et le scrapping dans cet exemple seul le prix et le lien de l'annonce vous intéresse vous accédez donc à des données disponibles publiquement sur le site d'annonce immobilière qui ne ne nécessite pas de connexion à un compte ni un paiement quelconque pour accéder à ces données vous ne récoltez pas non plus sans leur consentement le nom ou l'adresse mail des personnes ayant posté ses annonces pour leur faire des offres automatiquement dès que l'annonce est publiée dans ce cas-ci le scrapping est raisonnable vous automatisez une tâche que vous faisiez manuellement pour récupérer une donnée qui vous intéresse sans porter atteinte au site concerné ou au particulier qui posteent les annonces 2uxème cas de figure vous êtes un particulier ou une entreprise qui opère la revente d'éditions spécial de basket dans ce domaine vous devez mettre la main sur les bonnes affaires le plus rapidement possible vous décidez donc de mettre en place un script qui va envoyer une centaine de requêtes toutes les minutes sur un site de petites annonces pour trouver les baskets au meilleur prix vous mettez en place ce script et vous le laissez tourner H24 7 jours sur 7 le script fonctionne parfaitement et vous averti dès qu'une annonce est disponible à un bon prix vous décidez de pousser l'automatisation jusqu'au bout vous créez un compte payant sur le site de petites annonces pour avoir accès à des annonces exclusives et les coordonnées des vendeurs vous décidez ensuite d'ajouter une fonctionnalité pour contacter automatiquement les vendeurs qui vous intéressent en leur faisant une offre votre script fonctionne tellement bien que vous décidez de créer un service associé que vous faites payer à d'autres utilisateurs pour qu'il puisse faire de même dans ce casci vous l'aurez compris plusieurs problèmes se pose et dans ce cas de figure vous risquez d'avoir des problèmes avec la justice premièrement parce que votre script effectue un nombre très important de requêtes et il risque donc de mettre à mal les performances du site votre script également il accède à des données qui sont derrière ce qu'on appelle un paywall puisque vous avez payé pour accéder à ces données elles ne sont donc pas disponibles publiquement également vous accédez à des données personnelles et vous contactez les personnes sans avoir leur consentement et dernièrement vous utilisez ces données pour commercialiser un service qui peut être vu comme une concurrence directe au service sur lequel vous récupérez ces données ce n'est qu'un échantillon des problèmes qui sont posés ici mais vous voyez que là déjà on contrevient à beaucoup de choses qui peuvent être considérées comme éthique et donc en faisant ce genre de script vous risquez de porter atteinte de nombre nombreuses façons au site que vous ciblez que ce soit en terme de performance mais aussi en terme de business donc je ne vous conseille pas de faire ce genre de scrapping si vous le faites c'est à vos risques et péril et je vous conseille dans ce cas-ci d'être armé d'un bon avocat pour être sûr que vous faites les choses dans la légalité ce qu' me semble difficile à réaliser dans ce cas-ci sans modifier grandement votre script et l'objectif final de celui-ci sur la majorité des sites Web que vous visitez il y a un petit fichier texte qui est disponible à la racine des sites qui indique les pages à ne pas scrapper ce fichier c'est le fichier robots.txt vous pouvez le trouver en ajoutant tout simplement robots.txt après l'URL d'un site donc directement à la racine du site vous allez retrouver ce fichier qui indique les éléments qui ne sont pas utiles pour un scrapping donc c'est un fichier qui est destiné principalement aux bots qui vont venir récupérer des informations sur le site notamment les crawers de Google qui vont aller récupérer les informations pour les indexer sur le mode moteur de recherche vous voyez par exemple ici pour Amazon qu'on a beaucoup de dossiers ici qui sont indiqués et qui ne sont d'aucune utilité pour un indexage sur Google donc ça va être des parties du site ou des URL qui vont être utilisés pour la mécanique interne du site mais qui n'ont aucune donnée d'intérêt pour un moteur de recherche ou même pour des humains alors bien sûr ce fichier est publicque n'importe qui peut aller le lire et vous pouvez essayer d'accéder à ces URL pour voir ce qu'ell contiennent si ça vous intéresse vous voyez ici qu'on a beaucoup de dossiers qui sont désactivés donc avec cette commande dis allow et on a à l'inverse d'autres dossiers ici qui sont indiqués comme poss possiblebles d'accès avec l'inverse donc allow ici et on va avoir cela pour différents botes donc les différents botes vont être identifié avec ce user agent au début on avait un user agent avec une asterisque ici donc ça va concerner de base tous les crawers qui vont arriver sur le site et si on descend ici vous voyez qu'on a certains bots qui sont avec un peu plus de restriction donc notamment le GPT bot qui doit être le bot de open ai j'imagine je n'ai pas vérifié mais j'imagine que c'est ça où là on indique que l'accès doit être total à l'entièreté du site site donc avec diesel ici qui est fait sur la racine si vous voulez en savoir plus sur ce fichier vous pouvez aller sur robots-txt.com c'est un site très bien fait qui explique toute la syntaxe de ce fichier ce que vous pouvez mettre dedans dans le cas du scrapping donc ça va nous être utile pour savoir les pages qui ne sont pas vraiment dignes d'intérêt ça peut être intéressant si vous faites des bottes de scrapping qui vont avoir comme intérêt un peu comme le fait Google de faire un indexage et non pas juste une recherche de données et vous avez un autre paramètre qui peut être intéressant pour le scrapping qui est assez rare personnellement je dois avouer que je ne l'ai jamais vu dans un fichier robots.txt mais ce paramètre est un paramètre qui est géré comme vous le voyez ici par différents moteurs de recherche comme yaho Bing et cetera donc c'est un Craw delay qui va indiquer en fait le nombre de secondes à attendre entre chaque requête vous voyez que par exemple les robots de Google n'utilisent pas ce coll delay et à la place vous pouvez le spécifier dans les outils pour les webmaster de Google donc voilà ça peut être une bonne indication aussi si quelqu'un a mis un Craw delay ici vous avez une indication du nombre de temps en seconde à utiliser entre chaque requête pour ne pas surcharger leur site si vous utilisez un bot de scrapping donc le robots.txt ce n'est pas une bible absolue il y a plein d'autres choses à prendre en compte comme on l'a vu dans les parties précédentes mais c'est toujours intéressant par exemple j'aime bien celui de Airbnb qui nous indique que si on est un bot il suffit de suivre comme expliquer toutes les indications ici mais que si on est un humain qui aime résoudre des challenges intéressants avec d'autres humains alors on peut aller voir leur page qui indique les posts qui sont ouverts chez Airbnb donc c'est toujours assez intéressant quand même d'aller voir ce fichier pour savoir ce qu'il est possible de faire mais aussi pour découvrir des petites pépites comme celle-ci j'en profite pour ajouter un petit complément sur le GPT bot effectivement c'est un bot qui est utilisé par open ai et vous voyez ça confirme ce que je disais sur le scrapping ethique avec le user agent vous voyez qu'ici il est clairement indiqué que le user agent va contenir cette information donc on est bien avec le GPT bot et on a même le lien ici de cette page qui indique tout ce qui est fait par ce bot donc vous voyez c'est un très bon exemple de ce que je disais sur la modification du user agent avec cette chaîne de caractères qui a été modifié pour indiquer que le script qui est utilisé vient de open ai et ainsi on peut très facilement juste en inspectant le user agent de notre côté quand on est éditeur de site savoir que c'est donc une requête qui vient de open ai et ainsi entrer en contact avec eux si jamais cela nous pose des problèmes de performance ou autrees sur notre site vous voyez également cette indication donc qui indique bien sur le robots.txt que ce bot de scrapping va respecter le user agent et que pour empêcher le bot d'Open ai d'utiliser ses données pour potentiellement comme c'est indiqué ici améliorer de prochains modèles qu'ils vont utiliser et bien il suffit de mettre ses information à l'intérieur de votre fichier robots.txt ok me questions regardad because think miss in web scrapping there's always a part about the technical aspect but there's always questions that are not answered about the ethical ways to get data to collect them to store them and I know that bright data is also really uh doing a lot in this field uh so it's a really a great pleasure to be able to talk with you about all this these questions so um maybe you can just start for the audience to introduce do at data and then we can go on and follow up with the questions I have yeah sure so first of all thank you for for having me always a pleasure to talk about these things as I agree with what you said there's a lot of um gaps in terms of information what is ethical web data collection everything related to that uh my name ISIT i'm the Vice President of compliance and ethics here at data been with the company for a couple of years now now uh previously partner at KPMG working for advisory ris Consulting compliance and ethics uh in those areas and happy to be here and share any information about web scraping and ethical web data collection thanks so I have a first question about uh the fact that why writing my course I'm talking about ethics and how to SCP data and why in first there's regulations and why there's website that prevent people from scraping so because there's I was using a metaphor about uh the cars on the road like if everybody followed the rules perfectly there would not need for uh for things to prevent people from drinking alcohol or to speed limit uh in the roads and so we have the same problem in the web that if everybody followed the rules and did the scrapping uh ethically we wouldn't need on the website part to prevent people from scrapping so I have a first question about what's the difference between regulated and and unregulated activity when it comes to web data collection and scrapping ok so I think the example that you you said with the cars it's interesting because on one hand we have regulation but it's keep on involving you know 30 years back seat belts were not something as common and myself driving in my my parents car at the front seat no seat belt anything like that and it was just as uh dangerous as it is today so sometimes it's up not only for the regulationse it can have some rough time keeping ahead of uh technology but also for us as people or businesses to set the framework of what is ethical and not ethical and this is exactly the case between regulated and unregulated territories in general where when we talk about data collection and scraping the easy part or some might say not that easy but it's where you have regulation in place like regarding privacy for example regarding copyrights those kind of things are are already heavily regulated even though it keeps on evolving and the new uh technology keeps on challenging it you know in terms of ai and those kind of things so it will always be this kind of discussion which regulation but we see a lot in tech different places that has no regulation and it's up for the businesses to decide how to do it the most ethical way and this is where we talk about ethical web data collection where it's up for us in this case by data to decide what is ethical usage of web scraping how do you uh source your pe to create your network what do you say when you come to a website want to collect the information how you identify yourself those different aspects have no regulation uh over them there's no specific requirements and for us is is BRI data we want to make sure that we on the good side when dealing with scraping and everything related to that there's a lot of bad that someone can do as well so we want to make sure we on the good side and there are a lot of different layers for that yeah it's and it's a ni thing to see that you know it's a i've always seen uh scraping before as having a bad label on it you know it's it's always something we think of being abusive but in fact it's it's what's the Web is it's data it's and data is everywhere and it's like Open Source you know when it's public when the data is there and data is the new the new gold of the 21st century so you know it's it's really important question and that brings me to the second question that I have which is what is for you for data ethical scrapping so first following up on what you just said we always have data uh even when we go back from word of mouth from one person to to the other later on in writing um public libraries and so on and now everything is online and this is the database thatind ever had and most of it is publicly available it's been uploaded by people to be used by other people and there's so much information out there just a matter of really making the most out of it so in that's TER it's not really different just another step in involv involvement of uh data as we as human um use it and know about it and when we talk about ethical data collection it's a matter of first of all for us and you mentioned what data is collected because there's a big difference between publicly available data and nonpublly available data and it's sometimes might seem very obvious but it's not because you can have different restriction on the information the most clear one know if it's in order to see any data you need to log in to a website or you need to pay you go pay anything like that that is obviously uh not public information um so that is the first thing when we look at uh scraping of data is it publicly available because on one hand we believe that publicly available data should remain public public uh and this is um an ongoing discussion between the the websites the publishers the scrapers and everyone involved but this is I think the basics for everything regarding eical web dat collection and the other part is how do you collect the data itself that means from our perspective do no harm that means when you do collect the data that shouldn't interfere with anything that the website is doing on a day-to-day basis there still supposed to provide their services or that data for me and you if we go from our own computer and want to log in want to see that information it should be available to all of us so we want to make sure that don't harm the website in any way and in order to do both you need to put a lot of tools resources uh into place to to guarantee um because we have so much data running through our systems with hundreds of new customers on a daily basis and data just to put it in scale right data has more uh then all the top search engines Yahoo being Google and the others combined in a day okay in terms of request that goes to a system so obviously it's it's a big system that if you want to monitor it you need to invest a lot uh but at the end this is how you try to sepate the ethical and nonethical uh when you go on that journey of web data collection and it's um because yeah you say you have a lot of connections coming from from your customers through datata and you have a really large network of proxies and so I i know you have a lot of uh what is called know your customer so you have a lot of procedures that uh you want people to go through so that uh your customer can use the residential network can you talk a bit about that about what you have put in place to make sure that uh you can use the you can use this residential proxy from bright data point of view but also from your customers point of view like what the people that using the network needs to do and what the people that BRI to do yeah sure um this is a challenging part because when you set up a platform any SAS platform for that example you want to have as less fiction as possible you want your customer to on board start using it without the need for anyone to talk with him or to provide any special access anything like that um but data we we do have that in place but as you need more and more uh special access rights and residential uh system the residential network is one of them we need to get to know you better and when this is why we took the the KYC the know your customer process which is basic basically coming from the financial sector this is something that regulators has enforced on the financial sector to know who their customers are what they're using the money for where they're coming from and those kind of things um so we took that and we adjusted to our needs which basically we ask to different questions the first one is who you are we want to validate who's on the other side whether it be a large enterprise with thousands of employees or freelancer just doing scraping uh jobs or anything like that for for his customers in both cases we want to know who's on the other side uh and verify that and obviously uh we do that in order to make sure that this is your business we are a B2B platform we don't allow any personal use of our systems so this is ongoing review that we we are doing and the other part is to know what exactly is your use case and again this is a challenge because I know a lot of uh different platforms of saying that uh you need to provide your use case but it's not just a matter of you providing me the use case but for me to review it to validate it and toove it um because you can look at the proxy infrastructure as infastructure only no one will have any issues with at or SPR those kind of platforms if someone will do something bad in their network uh but that's not the case with proxy and we want to make sure that we know who's the customer and what they want to do so we verify both ends and we have a lot of different uh attributes that we look at in terms of validation but we also publish anyone can go and see what is our acceptable use policy what are our unapproved use cases things that we don't allow to do in our network and going back to the regulated versus nonreulated it's not because we it's it's illegal to do so for example anything related to crypto exchange in most countries is regulated some way or the other but we deed that we don't want to um use a network to anything related to that just because anonyizing yourself plus any exchange which is already hard to uh track it's not a good situation and we have a bunch of those and that the results at the end of us being you know we we don't approve or don't accept hundreds if not thousands of customers on a yearly basis uh which we are okay because we want to keep protecting not only all of our customers and our network but also our peers the one that uh that traffic goes through them and we have the guarantees for them about what type of traffic and how we protect them and the web in general uh which seems might seem quite strange but we want to make sure we are on the good side uh of things and that is an ongoing process with the dedicated team that we have here in place uh which is a global team and they go over each and every request of our customers to review to validate to go on a call with them whatever is needed to verify but not only before the use but also while they use it we have different monitoring processes that alert us if we see anything out of usual and we reach out to our customers compli is a mandatory step when you want to get more access rights and this is something that our customers Cheng us and we keep evolving to prot everyone in NW it's nice it's interesting because I think we talked a bit uh about that uh before the call r about the way that people in fr in general are really concerned about ethics and I think that's a bit too much sometimes because I know a lot of my students before they write the first line of code about scraping they always starting to raise questions about oh I can can I do this or can I do that and as I said also at the beginning of the call the way that some websit are really really strict on scraping maybe too much even like if you just start refreshing the page even humanly like a bit too much you going to be blocked and so people are are afraid and they're like oh my god I did something wrong because I refreshed too quickly but they just sent like five requests in a minute which is not a lot when you have sometimes say people could refresh much more and then you you would have um alerts on your side about uh nonethical use but so yeah in France I see this this um this fear that people have that because of some website that are really really against scraping even a bit too much I think because they have public data as you said like data that you can get humanly and and but I think it's it's good that you know people are aware that by using BRI data they see that there's this level of regulation that it's not it's not something that's completely open as well for them because you know you you can have trust in the fact that the company is doing what needs to be done to stay in the long term as well so so that leads us leads me to to another part that I want to approach so it's it's more clear now like what you do to to know a customer to create this network and I wanted to know based on that I like what what do you do more in general to protect uh to protect to get the worldwind web um a safer place for scrapping do you have other things other processing place to ensure that that once again your customer and the website that that gets great uh are uh staying safe yeah well this is something that uh we keeps on uh evolving every time because we need to figure out what will be the the next challenge and not to wait for something to happen before we react uh i think a good example a basic example but a good one is everything related to governmental sites uh governmental sites are blocked in our system by default not because it's not publicly available not because there's any harmful information over there but the other way around we want to make sure that if you need to scrape any information from a governmental website it's okay and we can verify it and provide you with the access but you want to make sure that no one exploit our system in order to harm any governmental website which are very um um they get targeted a lot get especially in these days you know different political situations different uh action that are being deployed around the world and we want to protect those kind of websites just because we understood there are a high risk in general and even though they have their own AntiBot and protections but we think that it's our job also to protect those kind of websit this is one part of an example and I think it's interesting because it's not just blocking.gov domain it's about something larger than that and we uh have a project project of uh classification where we classify generally the the the web okay billions upon billions of domains that we try to to classify with different tools uh and say okay these are government related domains these are crypto related domains and so on and to make sure we block as much as we can or protect them and provide access on a case by case um we viw that we do every time so this is like um one uh vector of activity that we do in order to protect the web in general there's a lot of communication channels that anyone can reach by data to report any suspicious activity any abuse related activity it can be from our vendors it can be from our website it could be by simple email uh to to by data and what the the differentiator for us is by data is the fact that we look at each and every one of those reports because we want to make sure if it's a false report we will let you know we looked into it we we don't see anything problematic in our system we have the logs to do it but if it is something that even might be problematic we want to investigate and reach out to the specific customer to stop any uh harful activity even if it's not yet harful but something that is might be might be problematic and we are able to do so because we have logs because we have uh tools within our systems uh to make sure that it's working as we intended to and you are doing what you told us you're going to do so we have different alerts for that uh and I think part of it is also educating the market about public versus non publicu you mention that some website might have too many restrictions about scraping and that is definitely the case I think when you talk about the technology um Arena let's say if it try to put more um blocks from the technology point of view antibots and those kind of things this is perfectly legitimate no no problem we have no problem with that that has been the case and we need to see how we can provide access but uh not hurting the the website in any way one of the things that we do for example is to make sure that any um targeting coming from our network doesn't change or har the website in terms of latency we check the latency of the website to make sure it still operate as it's supposed to be and obviously it can differ from one website to the other but when we see any uh changes in the latency that might only might be uh because of our traffic we will lower down the the traffic and we will adjust it to make sure it won't have it again that mean we put sort of our weight limit for a specific website uh to make sure it will keep on running as it's supposed to to be running from the getg so these are only some we have many more we even provide tools to the main owners if they want to know what uh traffic is coming from by data to separate it to say ok no problem you can go ahead and S but I want to to clear it I want to take it outside of because of analytic reasons because of whatever they want we will provide that as well the problem is it's really about educating the other side making sure because you know there's always an example that we talk about if two different grocery stores one uh opposite the other you want to check the prices everyone can go to the other store and look uh and it seems unreasonable if someone told you hey no you can go inside because you're from the other store that doesn't seem uh right that's the same case and we all use those kind of platform when we order our hotel or flight tickets anything like that everyone is doing it this is the public data that we have uh and if it's publicly available it should be publicly available for all and there are amazing use cases of what can be done with data for good in terms of um you know to protect uh child abuse to prevent human trafficking those are whole different aspects of usage of data that we have in data in a separate entity called the bright initiative this this is what they do we data for good where we help people use data for for their um projects academies and so on so again being on the good side of things and protecting the web working with the domain working with Cyber Security companies and explain to our customers why this is really an advantage by working data if you want to do something bad could go use proxy not by data if you to good business legitimate access be more than happy to toort you it's really interesting you got me with the educational part because it's it's really what I'm pushing forward as well and and it's nice to know that you have because I I see this fe l about website owners to about the latency and the fear of beingraight to much especially when it's when smaller website and they have people to so it's nice to know that you can have the limits and latency and I didn't know you doing this and it's good that you can see like clearly see if there's a latency issue with the website and this I think it's it might be also what prevents people from being blocked from the from the beginning if if if it's prevented this way and it's it's also I think a good sign for you were talking about government I know in France we have a lot of we had a lot of DAT that was not and was more that people governware this dat could useful and so people started asking you know right now we need to go scrape the data manually or with scripts and it's it's not efficient and we would like this data to to do good to to prevent when there's natural catastrhe ors like this we can dat to pr people to people like that and so we have UK as wellig company for food labeling which is checking the ingredients and using data and stuff like that so there's a lot of use case where sometimes the people themselves and the government the website don't know that the data they have is really valuable and it's not that they don't want people to use it it's just that they don't know so when you educate them about the fact that they can create API or be aware that they data can be scratch but in a good way that won't work the webs that is not like a or something like that I think everybody wins and then you can you can see emerging new new products and new thing that benefits from everybody so yeah I think it's also I'm coming back to the fact that some websit are a bit too aggressive and and people are afraid and I think it's education in both s to say ok so this website is agressive but it doesn't mean that it doesn't want at all to be scrapped because you know it's just that the limits are really really uh really high but you know when you use the good tool that's what I like data is even the hardest website that you get blocked really easily you see that you can when you do it ethically you can when you SP the request and you do it well and you see that in in all aspect of the scrapping j whether it be my code or the proxies from data I end up being able to do what I want to get the prices from a page without being block so I get the information I'm never blocked the website is not um is not uh doesn't get any latency issue so everybody is winning and so I think it's a good thing for everyb definitely and just to follow up on what you said with the governments not knowing that there might be some good use cases and providing API uh this is amazing obviously the the involvement uh not only government uh but other entities as well we need to remember the other side of tech Giants that has so many information but they try to close it from the outside and this is another problem that we haveuse just just imagine the world if we take down the biggest um databases that we have you know like from from Google from meta uh Twitter X and those it's is very problematic because when for example if you try to train an ai or large language model then by default you create bias because you only train it on some of the information and one system can be more liberal the other one can be more conservative and that's an issue and if everyone will only train on their own uh dataet obviously there's a bias within in it and this is something that that looking forward we need to fight in to keep that publicly available information public uh for everybodyse again as you mentioned and we talk before the different users are endless we see it from our customers endless uses of proxy of web data collection which is amazing what people are doing with that uh both from the business perspective but also uh as humans in general how we can improve our life in general by getting insights from those uh datas by providing better tools better offering based on that and this is the where we live today and it will only keep on expanding the amount of data that's been recorded on a daily basis is really not something that we can grasp even uh but we need to keep it publicly available while protecting the web in general yeah it's it's also funny i think that we always have also because there's a lot of tutorials about this there's a lot of tutorials about financial data i think about getting price for houses or getting price for Amazon to get something at the best price resell it and something like that I think it it brings also a fear from ban that you know as you said with the store that this store is going to get my price and try to beat me at it and but there's so much more to about like weather data about food data about so many things that can be that people have and that can be used by other people that have other ideas about what to do with this data so it's a it's very very interesting and and there's also for sure a lot of gray areas and a lot of questions raised I was thinking about open ai and like yeah for for sure the the new language model that are trained on lots of data and sometimes data that are publicly available but that people were not okay for it to be trained to make like I'm thinking about the art uh mainly so you know you put your art up there to get a job and then your art is being used by language mod also you know there's a lot of greay areas like this so I think it's good that companies are aware of that and that there's a discussion about that in once again on both side about what what regulation needs to be to be available for people to also be able to protect their data when it's intellectual property and they want protected but also when as we say educate people about your data is valuable it won harm you if people use it and it W it will even benefit with open source sometimes it's better to put your code out there because people will use it and will improve it and everybody will benefit from yourode being available rather cl so so I think it's if everybody can make sure this is done properly like I said everybody wi yeah I couldn't agree more it's we are we want to push regulation because we want everybody in this business to do at least what we do whatever regulation will be not because and we want to do it not because we said it's the good thing to do or the right to do but because someone went over and and really adjusted what does it mean to to do web data collection to do scraping and I think everyone should ask themselves those questions about the ethical web scraping how to do the best way and definitely we hear by that that this is the type of customers that we have that this is one of the top priorities for them um because there some great area because there are bad actors they want to know who the partner with um you mention you know uh financial institutions and those kind of things and it's not only that now if you don't have the data you are laging behind that's where we stand today it's not just having a a data science thing just not just you don't even have to be to have any R&D resources you can just ask this is the website that I need this is data that I need and get it as structured data um and this is I think it's amazing uh and should keep on pushing it but the challenge to do it in ethical way will remain and think that will set apart the different providers and I think this is something that everyone who you mention that starting to do any seping needs to ask themselves and we have no problem of people looking at us seeing what we do we we are very transparent about what we do but we also open for criticism if someone thinks there something that is wful glad have that discussion this is the way that we've been operated operating from from day one to tackle things to go on a call to understand what's the issue to see how we can improve only by doing that and uh relying on the community and everybody trying to protect the web that we as a company can continue uh to grow while keeping the the web safe for everybody it's good that there a discussion about this because as said maybe it makes the onbarding a bit slower and more friction at the beginning but it's good as well for the customer part to know that you know it's not just a set of rules that are there and that's you know could be interpreted in different ways as I say it's a discussion it's you have a human be behind this you have to know your customers so you have to ask questions but it's not to be in Tru or it's just to understand what's the what the point and what's the the issue the problem that wants to be solved and yeah and I go back to this I think a lot of my students when I see what they want to do it's always good stuff it's not always always but like 90% of the time it's you do have some people who want to get the price at Amazon 100 times per second for sure but you know it's uh as we say someone good does this will probably end up with something that's broken that's not good that will make the website crash and everybody is losing on this side so you know there'ss to do things the good way and to make sure everybody keeps doing what they want without harming other business or people so so it's good that there's there's discussion and um so that was that was it for my question I think it it answers uh all I wanted to ask i don't know if you want to add something or maybe advice about the people who are going to to watch this because there are students I know there's a lot of hype about scraping but there's a lot of questions to so I don't know if you want to say word about the world of scraping and how to start on this well you will probably have better uh advices on how to start with with scraping uh i do think that when anyone deals with scraping especially when they are looking uh a few steps into the future okay they need to ask themselves exactly why they want to SCP why is the legitimate business or use case for them to do so and really how they going to do it um and we touched only some of the the aspects but you know just residential network that we talked about a little bit is something that just to have an ethical uh peer residential network it's something that you need to ask about it ask the questions you can go invited a website and learn a lot about our peers and networks our tools everything that we just talked it's within our trust Center more than welcome to to look into that and then it's perfectly fine as I say to our customers go check the other providers do your de diligence do your checks we know what we can offer um and we know who's the type of customers we want to serve uh the ones that see that is important to do it in an ethical way uh so just as always keep asking questions uh keep getting the right answers uh you know people who's doing it are people that are very sharp and and know what they want and how to do it uh use the same system to ask about ethics uh and scraping and what does it mean and how any vendor activity protects you as a customer at the end of the day and that think is is the challenge that we are facing challenge that I'm facing in my team on a daily basis uh but it's one that amazes me and keeps me going uh day in day out to keep on improving and doing what we do and love to do uh and serving customers the best way possible and thank you for having me and asking those questions and was a pleasure thanks as well and I will be sure to redirect my audience to all the links because I i I checked as well all the things that you have that are not only technical you have technical part which is nice as well to start using at that but I was uh I was it was nice for me to find also all that you said about the ethics and and what's what's the regulation or or how to keep as we say the web safe so it's it's it's a good read to have as well so I I will for sure things about this beaucoup de sites web aujourd'hui fonctionnent avec des framework javascript les plus connus étant react ou encore VGS qui permettent le rechargement dynamique du contenu sur une page mais même sans l'utilisation de ces framework qui nécessite une utilisation intensive de JavaScript pour afficher le contenu d'un site web on ne peut pas avec une simple requête récupérer toutes les ressources d'un site web avec un script comme on le fait avec un navigateur par exemple le module request avec Python il est principalement utilisé afin d'effectuer des requêtes pour récupérer le contenu des pages web mais il ne permet pas l'évaluation du Javascript ou encore l'application des styles CSS lorsque vous utilisez le module request vous demandez simplement au serveur web de vous fournir le contenu de la page web qui est spécifié par l'URL que vous lui avez donné le serveur vous renvoie ainsi tout simplement le code HTML de la page à votre demande vous allez donc récupérer ni plus ni moins qu'une grande chaîne de caractère qui va contenir le code source de la page à l'adresse indiquée mais si on regarde de plus près dans ce code source on distingue des balises HTML qui contiennent des liens vers d'autres URL qui sont nécessaires au bon fonctionnement et à l'affichage du site généralement dans ces ressources on trouve des feuilles de style les fichiers CSS des fichiers javascript qui permettent d'avoir de l'interactivité donc les fichiers pointjs et également les images mais lorsque vous visitez une page web avec un navigateur le processus est différent vous effectuez comme avec le module request de votre côté une requête unique vers une URL le navigateur reçoit le code HTML de la page mais il interprète également son contenu pour identifier les références aux ressources externes il va ainsi effectuer automatiquement des requêtes supplémentaires pour récupérer ces ressources qui sont nécessaires au fonctionnement du site le navigateur il utilise ensuite toutes ces ressources pour rendre la page de manière appropriée en appliquant les styles CSS en affichant les images en exécutant le Javascript et cetera et c'est de cette façon que vous avez dans votre navigateur un site 100 % fonctionnel même si de votre côté vous n'avez fait qu'une seule requête c'est le navigateur qui se charge de repérer les requêtes supplémentaires à faire et de les faire de son côté pour afficher le site web dans son intégralité pour vous montrer ce que ça donne en pratique vous pouvez ouvrir n'importe quel site web si je fais un clic droit et que je clique sur inspect pour ouvrir les outils de développeur dans l'onglet network ici si je réactualise la page on va voir toutes les requêtes qui sont effectuées donc vous voyez que avec notre simple requête unique que l'on fait vers cette url on a tout ça en arrière-plan qui va être récupéré à partir des différentes balises de lien à l'intérieur du HTML donc on a des images on a des fichiers CSS on a le code source du fichier HTML donc ce fameux fichier qu'on récupère avec request mais qui contient comme vous le voyez ici toutes ces balises Link qui font le lien vers tous les autres fichiers qu'on va récupérer par exemple le style ici les images qui sont également affichés et les fichiers Javascript et vous pouvez également si vous le souhaitez bloquer ces requêtes je peux faire un clic droit sur n'importe laquelle de ces requêtes et cliquer ICI sur block request URL j'ai un petit panneau qui va s'ouvrir ici et je peux bloquer certaines URL on peut même bloquer avec des patterns donc par exemple je vais bloquer tous les fichiers de type JPG et vous allez voir que si je rafraîchis la page cette fois-ci on a plus aucune image qui est qui est affiché puisque toutes les requêtes vers les fichiers JPEG ont été bloqué et si je rajoute également un bloc vers les fichiers CSS et les fichiers Javascript vous allez voir qu'on va se retrouver peu ou prou avec le même résultat que celui qu'on aurait en utilisant directement le module request pour récupérer uniquement le fichier HTML donc vous voyez que sans le CSS sans le Javascript et les images le site web a toujours des informations mais il n'est plus du tout aussi fonctionnel que ce qu'on avait auparavant et donc c'est pour cette raison que dans certains cas vous allez devoir vous-même faire ces requêtes par exemple dans le cas des images si je veux récupérer les images il faut que j'identifie les liens vers les images dans le html pour ensuite aller télécharger ces images donc pour aller ici par exemple chercher sur cet URL le contenu de l'image et le télécharger sur mon disque et dans le cas du javascript c'est pour cette raison qu'on va utiliser des navigateurs qu'on appelle headless qui sont des navigateurs qui peuvent rouler en arrière-plan mais qui vont quand même avoir cette interprétation de tout ce qu'on a vu ici donc le CSS le Javascript et cetera on va voir ça dans les prochaines parties ne vous inquiétez pas et c'est avec ces navigateurs qu'on va pouvoir également interagir avec les sites web pour par exemple cliquer sur un bouton naviguer sur une page et récupérer des données exactement comme on le ferait avec un humain donc c'est de cette façon qu'on va contourner ces blocages techniques qu'on pourrait avoir avec une requette simple comme on le fait avec le module request vous devez le savoir désormais pour empêcher un scrapping sans limite de nombreux sites populaires ont été obligés de mettre en place un certain nombre de protection voire de restrictions il est ainsi pas rare de se voir bloquer l'accès à un site Web si vous rafraîchissez trop souvent une page et même en effectuant un scrapping éthique et raisonnable il est facile pour un site de détecter si vous utilisez un script ou non il y a de nombreuses solutions ces dernières années qui se sont développées pour contrer l'utilisation de bot comme datadome que vous trouverez présent à la fois sur des sites français mais aussi des sites internationaux comme le boncoin ou TripAdvisor ou encore cloud FLIR qui permet également d'ajouter des mesures de protection contre les botes ces solutions elles sont très efficaces mais elles coûtent beaucoup d'argent et elles ne sont donc présentes que sur des sites assez importants mais ça ne veut pas dire qu'il faut faire n'importe quoi sur des sites qui ne disposent pas de ces moyens les grandes plateformes comme Amazon ou Airbnb elles ont une structure bien plus robuste que la majorité des sites web c'est donc pas parce qu'un site web n'offre aucune protection contre le scrapping que vous pouvez faire n'importe quoi tout simplement parce que vous risquez de détériorer les performances du site et il n'est pas très compliqué comme on va le voir dans les prochaines parties pour un éditeur de site de mettre en place des protections simples mais efficaces et parfois trop efficaces et trop restrictive c'est donc aussi un risque pour vous si vous faites n'importe quoi vous risquez d'encourager même les sites de moindre importance à mettre en place des barrières pour empêcher toute forme de [Musique] scrapping dans cette partie on va voir le concept du blocage par limitation des requêtes et comment essayer de le contourner même si vous allez voir que c'est assez facile en théorie et beaucoup plus difficile en pratique cette pratique c'est donc la pratique qu'on appelle en anglais du rate limiting c'est-à-dire qu'on va permettre à quelqu'un d'accéder à un site qu'un certain nombre de fois et vous allez voir comment c'est très facile à implémenter du côté des développeurs en bac end sans faire quelque chose de très compliqué on peut tout simplement indiquer qu'on souhaite par exemple que quelqu'un ne puisse pas accéder plus de 5 fois par minute à notre site donc là j'ai le site en local déjà sans cette limitation et on va voir par la suite en la rajoutant ce que ça change donc là si j'accède au site si je rafraîchi la page vous voyez que je peux le faire plusieurs fois ça va pas poser de problème de la même façon si j'essaie de le faire avec le module request je peux donc lancer mon script et on va bien récupérer le H1 de la page et je peux faire ça de façon assez importante en faisant une Bou par exemple de 50 itérations et en répétant cette opération donc je relance le script et là vous voyez qu'on lance 50 fois l'opération et on n'est pas dérangé par contre si maintenant du côté du backend je fais cette petite opération ici qui tient en quelques lignes comme vous pouvez le voir je vais indiquer ici que je souhaite limiter l'accès à cette page à cinq fois par période de 60 secondes donc dès qu'on va accéder en 60 secondes donc dans une minute au moins 5 fois à la page la 6e fois on va être bloqué et ici je vais retourner cette erreur donc là si j'essaie de nouveau avec cette fois-ci cette protection qui est affichée je vais le faire déjà à la main vous allez voir que même à la main on va être limité donc je relance la page j'actualise une fois deux fois trois fois quatre fois c fois et à la 6e fois vous allez voir que là voilà on est bloqué rate limit exceeded il m'indique ici donc comme je l'ai mis je suis assez gentil je dis qu'on a utilisé les cinq requêtes et que la limite est 5 je n'ai pas indiqué ici la durée pendant laquelle je vais limiter la personne mais là si j'essaie de nouveau vous voyez que je suis de nouveau limité donc là je peux attendre une minute je vais poser la vidéo et on va voir que ça va donner la même chose avec notre script ici dans notre boucle une fois qu'on aura de nouveau accès au site à partir de la 6e itération on va être bloqué et on aura une erreur car on ne pourra pas récupérer le H1 sur la page car on aura tout simplement pas accès au HTML là si je fais un clic droit pour inspecter ce code vous voyez qu'on a juste dans le body ce texte qui est affiché rien dans le Head juste un HTML très très très simple et rien de plus que l'on peut scrapper donc voilà j'ai attendu suffisamment de temps si je rafraîchis la page ici vous voyez que j'ai de nouveau accès au site et là si j'essaie de relancer mon script vous allez voir qu'on va être très rapidement bloqué et en fait non parce qu'en fait j'ai fait une erreur toute bête dans mon script c'est que j'ai mis la boucle ici je me disais aussi que c'était assez rapide donc en fait on on effectuait la la requête une seule fois et ensuite on effectuait cette sélection sur le H1 50 fois donc c'est pour ça que c'était assez rapide mais si je relance cette fois-ci avec la boucle au bon endroit vous allez voir que là assez rapidement on va être bloqué donc vous voyez à à peine deux itérations j'en avais fait une de mon côté et j'en avais fait une autre ou deux avec le l'essai du script et là on est directement bloqué donc on fait deux itérations ici et là directement on a le non type et si j'essaie de relancer le script on va l'avoir tout de suite sans même pouvoir y accéder une seule fois donc quelle est la première façon de régler ce problème elle est très très simple c'est tout simplement de faire un import de Time et de faire un time.sleep pour attendre un certain nombre de temps donc ce n'est pas forcément très clair toujours combien de temps il faut attendre ce n'est jamais clair non plus est-ce qu'on va un jour être débloqué là ça va dépendre vraiment de chaque site là dans ce casci je vous ai montré la mesure que j'ai mise en place qui est de d'autoriser uniquement cinq requêtes par 60 secondes mais c'est rare que le site va vous indiquer cette donnée donc là le mieux que vous pouvez faire c'est en premier lieu d'essayer de ralentir votre scrapping pour éviter le plus possible de surcharger ça va de toute façon être quelque chose d'éthique en premier lieu de ne pas surcharger un site avec des requêtes donc c'est quelque chose que je vous conseille toujours de mettre en place que ce soit si vous le faites manuellement ou avec des méthodes professionnelles comme avec bright data qui de toute façon va le faire jusqu'à un certain point pour vous pour éviter de surcharger les sites mais si vous le faites de votre côté donc déjà dès le départ de commencer à limiter le nombre de requêtes pour ne pas surcharger le site ça va être quelque chose d'éthique et ça va éviter aussi de vous faire bloquer la deuxième façon de faire c'est une façon un peu plus professionnelle c'est d'utiliser des proxy donc je vous montre avec ce code ici là vous avez une liste de proxy qu'on va utiliser vous avez une fonction qui va récupérer un proxy aléatoire à partir de cette liste donc là on en a qu'un seul mais on pourrait en mettre bien plus on a ici un dictionnaire qui est retourné avec le proxy qui va être retourné dans le dictionnaire pour les requêtes en HTTP ou en HTTPS et ensuite on peut utiliser donc cette fonction qui va récupérer un proxy aléatoire essayer de faire la requête avec ce proxy et si ça ne fonctionne pas et bien réessayer de nouveau donc là on fait un peu une une sorte de fonction récursive puisqu'on essae la requête et si elle ne réussit pas on rappelle la fonction pour essayer avec un autre proxy et on essaie comme ça de récupérer le H1 le problème de ça si je lance le script là vous voyez qu'on a directement une erreur donc quel est le problème de ça c'est qu'en fait ces proxy vont être très difficiles à trouver donc je vais vous montrer il y a plein de sites qui existent vous pouvez chercher sur google free proxy list et vous allez avoir des centaines de résultats le problème de tout ça c'est que comme tout ce qui est gratuit forcément tout le monde se jette dessus et en fait ça fait bien longtemps que ces façons de faire ne produisent que très peu de résultats enf en fait vous allez passer votre temps à chercher des proxy peu importe ce que vous mettez en place les méthodes gratuites vont les tris/4 du temps être bloqué parce que ça va être des proxy de centes de données des proxis qui ont déjà été identifiés par les sites comme des adresses qui sont utilisées pour le scrapping donc vous avez très très peu de chance avec ça d'avoir un résultat positif et vous allez finalement perdre du temps à faire des centaines de requêtes pour en avoir une qui va réussir à passer donc la seule solution pour ça c'est d'utiliser des proxy professionnels des proxy notamment résidentiel et on verra comment les utiliser avec bright data dans une autre partie mais voilà si vous voulez essayer sachez que c'est possible techniquement comme je vous le disait c'est pas compliqué on fait juste rajouter un petit dictionnaire ici qu'on passe à notre requête dans cet argument proxy donc c'est pas sur la technique que c'est difficile c'est vraiment sur l'infrastructure d'avoir accès à ces proxy là forcément ça va nous coûter un petit peu d'argent et j'ai envie de dire heureusement aussi parce que si c'était aussi facile d'utiliser des proxy et bien ce serait aussi beaucoup plus simple pour tout le monde de faire du scrapping et le côté éthique finalement de la chose serait plus difficile à respecter tout ça n'est pas pour dire que dès que vous payez de l'argent forcément vous faites un scrapping éthique ça n'est pas du tout ce que je veux dire mais plus que forcément dès qu'un service est payant ça met une certaine barrière à l'entrée si on avait pas besoin de débourser un seul centime pour pouvoir essayer et scrapper toutes les informations du monde et bien beaucoup de gens le feraient donc vous pouvez essayer sur des sites de test vous pouvez essayer en local vous pouvez faire votre propre serveur pour vous entrer trîner et dès que vous allez avoir envie de faire des solutions professionnelles qui tournent en continu sans être bloqué il faudra vous tourner vers des solutions professionnelles qui heureusement ne coûte pas non plus des sommes astronomiques et on verra tout ça dans les prochaines parties avec l'utilisation des proxy de Bright data un autre blocage auquel on peut faire face c'est le blocage avec les user agent donc ça c'est quelque chose qui va être aussi très facile à parî du côté du site si vous ne prenez pas la moindre Pr précaution de votre côté pour changer ce user agent donc je vais vous montrer ici si on clique sur récupérer les livres secrets là vous voyez qu'on a le texte qui est affiché et on pourrait faire un clic droit pour inspecter les appels qui sont faits donc si je vais dans network ici et que je relance la page et que j'appuie sur récupérer les livres secrets on voit ici le point d'API qui est appelé et si je viens donc je vais réduire un petit peu pour qu'on y voit quelque chose on a ici l'URL qu'on peut appeler pour récupérer ces livres secrets donc je pourrais l'appeler directement donc je vais mettre cette URL dans mon request et je vais essayer de récupérer les éléments donc là ça va être les H2 donc je vais faire un select de tous les H2 sur la page et on va voir si ça fonctionne et vous allez voir que si je lance directement ce script de cette façon on a une liste vide pourquoi donc non pas parce que ce point d'API n'existe pas mais tout simplement parce qu'il est bloqué si je vais voir dans la console de doc string ici qui fait tourner le site en local on voit que j'ai un bad request et que j'ai le GET qui a retourné une erreur 400 donc ça c'est parce qu'en fait j'ai réussi ici à identifier cette requête comme venant d'un bot donc je vais mettre un point de débug ici sur le user agent donc sur cette vue qui va vérifier les requêtes qui arrivent et je vais refaire cette requête vers le scrapping/api/books et vous allez voir qu'automatiquement on arrive dans le debugger ici et que si j'agrandis un petit peu cette fenêtre et que j'avance on va récupérer le user agent et le user agent de request par défaut il est très explicite il met python- request et la version qui est utilisée donc c'est très très simple pour moi quand on ne fait pas de modification du user agent de repérer que cette requête vient d'un bot donc vient d'un script et non pas d'un humain et je peux ainsi très facilement la bloquer avec une structure conditionnelle en disant que si je trouve python request dans user agent j'envoie un Jason response qui dit error request from bot et je retourne une erreur 400 sinon si on n' pas le python request dans user agent et bien je retourne les données et ce user agent il va être différent en fonction de comment vous accédez à la ressource si je remets mon site ici ici que j'actualise que je refais un clic droit pour ouvrir les outils Network et que je clique sur le bouton on va pouvoir inspecter ce qui se passe ici donc là de nouveau je suis avec ma vue de dbug je vais avancer et vous voyez que cette fois-ci le user agent il est bien plus complexe qu'est-ce que c'est le user agent c'est tout simplement une longue chaîne de caractère qui va donner des informations sur la personne qui fait la requête donc on voit ici Mozilla macintouh Apple WebKit chrome et cetera donc c'est juste une chaîne de caractère qui contient les informations pour indiquer par exemple ici que je suis sur MacOS que j'utilise la version 120 de chrome et cetera donc c'est des informations qui vont être utilisées par le site autant pour savoir justement qui fait la requête et pouvoir la bloquer comme on l'a fait ici mais aussi utiliser de façon analytique comme pour savoir par exemple si votre site web est plutôt consulté par des appareils mobiles donc des iPhone des androids s'il est consulté par des ordinateurs de bureau des Mac des Windows et cetera et donc quand on utilise le user agent par défaut vous voyez que c'est très facile de mon côté de vous bloquer donc ce que je peux faire c'est par contre modifier ce user agent je vais faire un clic droit copy value pour copier le user agent que j'utilise quand je navigue de façon humaine donc directement avec mon script et si je revient dans mon script principal ici je peux très facilement modifier cette chaîne de caractère donc je vais créer une variable user agent qui va contenir la variable que j'ai copieré dans le mode debug donc en faisant ma requête manuellement et je vais changer les entêtes donc les entêtes elles se trouvent dans headers ça va être un dictionnaire et dans ce dictionnaire je vais mettre une clé que j'appelle user agent et je vais lui passer la variable user agent que j'ai créé juste ici donc on pourrait mettre directement la chaîne de caractère aussi là c'est juste pour faire une variable intermédiaire pour que on n pas tous sur la même ligne et ensuite qu'est-ce que je vais faire et bien tout simplement ici à ma requête passer ses entêtes à l'argument headers là encore je pourrais me passer de cette variable et tout mettre ici directement mais c'est juste pour que ça ne prenne pas trop de place et si je relance cette fois-ci la requête donc j'arrête le script ici je le relance là on voit qu'on arrive dans le point de débug je continue et cette fois-ci le user agent vous voyez c'est pas plus compliqué ça cette fois-ci il est bon et donc je continue avec ma requête et là alors on a quand même une erreur parce que je retourne ma réponse sous forme de Jason donc si je reviens ici vous voyez qu'on retourne un Jason response donc c'est pour ça que je n'arrive pas à faire le scrapping mais la requête passe bien si je fais un print de r.status code pour montrer le code de retour qui nous est donné je relance le script là on arrive bien dans mon point de débug je valide je continue et là on a bien un statut de 200 et non plus 400 comme on avait auparavant si j'enlève les header ici et que je refais le status code vous allez voir que là cette fois-ci la requête est bloquée et que j'ai bien un status code de 400 donc vous voyez cette technique elle est très simple mais très efficace c'est en fait la première chose qu'il faut faire si vous utilisez request c'est de tout de suite modifier le user agent pour ne pas avoir python request dans le user agent sinon vous êtes là encore quasiment assuré d'être bloqué et si vous voulez faire un scrapping ethique vous pouvez bien entendu modifier ce user agent pour quand même indiquer au site web que vous êtes quelqu'un qui souhaite scrapper votre site mettre les informations pour vous contacter comme ça vous faites un scrapping dit éthique en indiquant clairement vos intentions mais c'est sûr que comme vous l'avez vu il y a plein d'outils qui de base vont bloquer s'il voit python request ou d'autres chaînes de caractère de ce genre donc c'est quand même important même si vous mettez ces informations de contact d'avoir un user agent qui n'est pas celui par défaut utilisé par des bibliothèques comme request pour naviguer sur des sites dont le contenu est généré dynamiquement par JavaScript on va devoir utiliser ce qu'on appelle des navigateurs headless donc headless qui veut dire sans tête ce que ça signifie c'est qu'on va utiliser un navigateur exactement comme celui que vous utilisez pour naviguer sur Internet tous les jours donc ça va être un navigateur comme Chrome Firefox ou encore d'autres disponibles avec ces outils qui vont donc afficher les sites web exactement de la même façon que vous le faites de votre côté en naviguant sur le web et comme leur nom l'indique le fait qu'il soit headless signifie qu'on ne va pas être obligé d'avoir une interface graphique pour les faire fonctionner donc on va pouvoir lancer un script qui va ouvrir ses navigateurs en arrière-plan donc on a'ura pas d'interface graphique mais ils vont quand même interpréter le Javascript et réaliser toutes sortes d'actions que l'on pourrait également faire de notre côté comme rentrer des information dans une boîte de texte ou encore cliquer sur des boutons les navigateurs headless disponibles avec Python il y en a plusieurs et dans notre cas on va utiliser le navigateur playwright alors quels sont les avantages et les inconvénients de playwright vous allez voir qu'il a beaucoup de avantages et des inconvénients qui ne sont pas très dérangeants pour nous le premier avantage c'est notamment qu'il est bien plus rapide que d'autres que j'ai pu essayer par le passé le deuxième avantage et pas des moindres c'est qu'il est beaucoup plus facile d'utilisation vous allez voir que c'est un jeu d'enfant et si vous essayez par la suite d'autres navigateur vous allez voir que vous reviendrez probablement très vite vers playri pourquoi il est plus facile notamment parce qu'il a une technique qu'on appelle auto waiting c'est-à-dire qu'il va automatiquement attendre que les éléments soient affichés sur la page pour pouvoir effectuer des action action c'est quelque chose qu'on doit gérer à la main avec pas mal d'autres navigateurs headless et donc là ça va grandement faciliter l'utilisation qu'on va en faire un autre avantage qu'il a c'est qu'il dispose d'un débuger intégré très pratique pour voir les lignes de code que l'on peut écrire on va avoir des outils de débugage que l'on va voir dans les prochaines partie on va ainsi avoir accès à des outils de débugage qui vont nous permettre de cibler des éléments sur la page et de voir le code que l'on pourrait utiliser pour effectuer des actions sur ces éléments un autre point assez intéressant c'est que les navigateurs sont intégrés vous allez voir que c'est c'est très facile de les installer et là encore avec d'autres solutions qui existent c'est quelque chose qu'il faut faire séparément et qui peut être assez castê au début parce qu'on ne sait pas quel navigateur choisir il faut choisir le type de navigateur est-ce qu'on va aller sur Chrome Firefox quelle version on va utiliser les sites sur lesquels on peut télécharger ces navigateurs aussi des fois ne donne pas vraiment confiance pour tout vous dire donc on n'est jamais trop sûr si on est au bon endroit si on fait la bonne chose et ça paraît très vite très technique alors qu'avec playwri vous allez voir qu'en une ligne de code c'est résolu et dernier point il est développé par Microsoft alors non pas que je vouse une passion pour Microsoft mais l'avantage de ça c'est que c'est une boîte très solide il y a des outils qui sont soit open source et qui peuvent être un peu plus risqués à utiliser parce que l'OP source comme on le sait ça dépend de gens qui ne sont pas forcément toujours payés derrière et qui peuvent décider à un moment d'arrêter le développement même si la puissance de l'Open Source fait que généralement le projet peut-être repris et ne tient pas sur les épaules que d'un seul développeur mais on a quand même vu des cas de figure dans lesqueles ça pouvait arriver et donc le fait que ce soit développé par Microsoft vous pouvez le voir comme un avantage ou un inconvénient on pourrait dire également que les boîtes comme Microsoft ou Google n'hésitent pas trop quand elles doivent couper dans une solution donc voyez-le comme un avantage ou un inconvénient moi j'ai préféré ici le placer dans les avantages dans les inconvénients on a le fait qu'il supporte moins de langage ce que je veux dire par là c'est que en fait ces librairies sont utilisables avec différents langages de programmation et dans le cas d'autres bibliothèques comme sééium qu'on peut également utiliser avec du PHP ou du c#arp playright n'est utilisable qu'avec du Java du javascrip script du python et du DNET si mes souvenirs sont bons ou du Java également donc si vous faites du PHP ou du c#arp bien sûr vous ne pourrez pas utiliser cette solution mais dans notre cas ce n'est pas vraiment un problème puisque on va tout faire avec Python et le dernier inconvénient c'est qu'il a seulement 4 ans d'existence là encore par rapport à d'autres solutions comme sééium qui existe depuis plus de 20 ans c'est un petit jeune mais là encore je trouve que ce n'est pas forcément un inconvénient puisque on a du coup une technologie qui est à la pointe séléum quand on l'utilise ça fait un peu vieux jeu c'est sûr que c'est très robuste on a une communauté qui est très importante aussi de par les questions qui ont été posé par le passé sur Stack Overflow et d'autres sites du genre donc playri c'est beaucoup plus jeune mais c'est aussi beaucoup plus avancé sur certains points comme ceux qu'on a vu avec le auto waiting le debugger intégré et plein d'autres choses comme ça qui font qu'il est très agréable à utiliser par rapport à d'autres solutions qui sont là depuis plus longtemps mais qui nécessite des compétences un peu plus techniques comme je vous le disais il existe d'autres solutions disponibles la la plus connue est séénium donc je vous invite à aller voir cette solution également vous pouvez aller voir la documentation et lire tout ça vous voyez que là on a des exemples de code en plusieurs langages avec du Java du python du c#arp du Ruby JavaScript Codling donc on a beaucoup de choix de langage mais il est pas mal plus compliqué à utiliser que ce qu'on va voir avec playwright un autre projet que j'aime beaucoup que j'ai utilisé grandement sur docsting c'est une librairie qui est basée sur sééium mais qui va beaucoup plus loin qui s'appelle selenium base et qui résout beaucoup de problèmes qu'on a avec selenium donc comme je vous disais par exemple tout ce qui est autoaiting tout ce qui est debugging on a beaucoup d'outils en plus avec selenium base que j'aime particulièrement qui rendent l'utilisation de cette bibliothèque beaucoup plus agréable donc si je devais choisir dans l'ordre je vous dirais de commencer potentiellement par sélénium pour voir ce qu'il est possible de faire et voir à quel point ce n'est pas vraiment agréable à utiliser ensuite passer assez rapidement vers selenium base si vous voulez rester dans cet écosystème séénium pour voir que on peut quand même faire du séénium avec des outils un peu plus puissants et dans cette formation on va s'intéresser à playwright qui va être un jeu d'enfant vous allez le voir à utiliser et qui est beaucoup plus agréable et qui fait du bien quand on est habitué à sééium et à ce genre de navigateur headless vous allez le voir si jamais vous testez les trois je vous laisse vous faire votre propre opinion dans cette partie on va voir comment installer et utiliser playwright pour afficher du contenu JavaScript depuis les sites donc la première chose à faire c'est d'installer playwght donc dans mon logiciel p je vais aller dans le terminal et tout simplement l'installer avec PIP install playri donc tout en minuscule on valide avec entrée ça va aller chercher les informations pour les télécharger et ensuite l'installer voilà donc ça ne devrait pas être très long et ensuite on va utiliser la commande qui va installer tous les navigateurs dont on va avoir besoin pour faire du scrapping donc c'est cette fameuse partie qui va être beaucoup plus simple à faire avec playright on a juste besoin de faire playri install je valide avec entrée vous allez voir qu'il va aller chercher différents navigateurs on va voir chrome on va vooir Firefox on va voir le web kit donc là encore on a un peu moins de choix qu'avec d'autres bibliothèques comme séenium mais franchement moi personnellement je n'ai jamais eu besoin d'utiliser d'autres navigateurs que ces deux ici donc Chrome ou Firefox généralement j'utilise la version de Chrome donc le chromium qui est de toute façon chromium en fait ce qui fait fonctionner la plupart des navigateurs sur le marché à part Firefox qui si je ne me trompe pas et je pense que c'est pour cette raison qu'il télécharge également Firefox utilise une autre technologie propriétaire mais sinon la plupart des navigateurs en fait derrière c'est du chromium donc une fois qu'on a installé tout ça on va pouvoir utiliser ces navigateurs on n pas besoin de faire quoi que ce soit de plus et on va voir tout de suite ce que ça va changer au niveau de notre site donc pour cette partie vous pouvez aller sur dogstring.fr/scrapping vous allez arriver sur cette page très simple qui va juste nous servir d'exemple dans laquelle on a un livre qui est affiché et je peux cliquer sur un bouton ici pour récupérer les livres secrets et j'ai deux autres livres qui apparaissent donc ce genre de manipulation que je viens de faire elle est faite avec du Javascript on a en fait un un script qui va aller faire une requête vers le back end pour chercher les informations et les afficher sur le front-end et c'est typiquement le genre d'opération que l'on ne peut pas faire avec request puisque request va permettre de faire une requête vers une URL pour récupérer ensuite le code HTML dans ce cas-ci on verra que vous pouvez faire cette requête et l'analyser en fait analyser quelle requête est effectuée vers le backend et essayer de la refaire avec request donc c'est une façon de faire de voir quelle requête est effectuée avec JavaScript pour pouvoir la faire sans JavaScript en fait donc directement avec le mais si on veut cliquer sur un bouton comme je viens de le faire ici on va être obligé de faire cette action de clic et c'est ça qu'on va pouvoir faire avec playri pour l'instant je vais juste vous montrer un usage basique de playwght de comment le lancer comment faire une instance de playwright pour afficher ce site et vous allez voir également si je rafraîchis la page que si je désactive le Javascript donc ce que je peux faire en faisant clic droit inspect sur ce navigateur Chrome si je fais command shift P ou contrô shift P sur Windows je peux faire disable Java ript et là vous allez voir que si je clique sur récupérer les livres secrets ça ne fonctionne plus donc vous voyez que quand on n pas de JavaScript on ne peut pas exécuter ce code et même si on avait avec request la possibilité d'afficher un navigateur comme celui-ci c'est vraiment le fait de pouvoir utiliser le javascript qui fait qu'on va pouvoir récupérer ces informations donc comme je vous dis soit en cliquant sur le bouton donc en faisant exactement la même action que celle que l'on ferait comme un humain soit en allant directement analyser donc dans network ici quelle opération va être effectuée donc je vais vous le montrer je vais activer le Javascript donc on va faire enable Javascript et là si je clique sur récupérer les livres vous voyez qu'on voit ici le point d'API qui est utilisé pour aller récupérer ces informations donc on est sur books donc scrapping/api/books on a l'URL ici on a une requête GET qui est effectué et on a la Response qui nous envoie les informations des livres que l'on affiche dans la partie frontend donc dans le navigateur ici donc on pourrait très bien faire cette requête mais cette requête pourrait être bloquée on va être aussi beaucoup plus facilement identifié comme un bot parce que là l'action humaine à faire pour récupérer ses livres c'est de cliquer sur le bouton et non pas de faire directement avec une librairie comme request cette requette bien sûr on peut maquiller les choses pour donner l'impression que cette requête est effectuée depuis le Front End et non pas directement à partir de request mais il y a plein de cas de figures comme ça des cas notamment beaucoup plus complexes dans lesquels on va avoir un intérêt à simuler le plus possible les interactions d'un humain sur un site web donc pour l'instant je vais juste vous montrer comment accéder à ce site avec playwright alors il faut savoir que avec playri right on a deux API qui sont disponibles l'API Sync et l'API async donc Sync comme ceci et async comme ceci alors la différence entre les deux elle est simple c'est que la librairie assync va permettre de faire des requêtes asynchrones nous dans ce cas-ci on va rester sur la p Sync parce que ça fait du code qui est plus léger et on n pas besoin dans ce qu'on va faire dans tout ce qu'on va faire en fait dans cette formation d'utiliser la librairie assync parce que on va faire des requêtes qui vont être synchrones donc qui vont être les unes à la suite des autres on n pas besoin d'en lancer plusieurs en même temps donc jeis je veux dire from playright.sync API on va importer Sync playright donc je vais me faire un petit peu de place ici pour que vous puissiez tout voir sur la même ligne donc from playright.sync API import Sync playright donc on va faire un context manager avec with et on va créer une instance de Sync playri donc n'oubliez pas les parenthèses ici et on va la mettre dans une variable qu'on va appeler tout simplement playright et à partir de ça on va pouvoir faire playwright. chromium donc là c'est parce qu'on choisit d'utiliser chromium sinon vous pouvez également utiliser Firefox donc là je vais mettre chromium et on va faire un navigateur qu'on va lancer avec la commande launch et ça on va le récupérer dans une variable que je vais appeler browser donc ça ça va nous permettre de lancer un navigateur et ensuite on va pouvoir créer une page parce que là c'est comme si on ouvrait juste le navigateur sans ouvrir de pagees et à partir d'une page par la suite on va pouvoir naviguer vers une URL donc si je fais juste ça et que je lance mon script donc clic droit run JavaScript scrapping vous allez voir que là rien ne se passe donc le navigateur est ouvert et au bout d'un moment quand rien ne se passe il va se fermer mais on n' pas de fenêtre qui s'ouvre donc pour ça il faut créer une nouvelle page donc on va faire page = browser.ne page tout simplement et une fois qu'on a la page on va naviguer quelque part parce que là si je relance le script vous allez voir que rien ne se passe de nouveau il va falloir naviguer vers une URL pour voir ce qu'il se passe également on va devoir changer le paramètre donc le fameux paramètre headless qui va indiquer si le navigateur doit avoir une tête ou non donc head signifie tête en anglais donc par défaut il est headless donc le headless ici est à true alors faites bien attention ça peut être confus au début headless quand on met headless à TR ça veut dire qu'on souhaite qu'il n'apparaisse pas donc ça veut pas dire on souhaite avoir un navigateur quand on met TR ici c'est l'inverse headless ça veut dire on va être sans tête donc on ne va pas voir le navigateur si vous voulez voir le navigateur il faut mettre le headless à false donc je sais que c'est un peu confus au début une fois que vous avez compris ça va un peu mieux donc headless à FALSE si je relance le script cette fois-ci vous allez voir très rapidement quelque chose qui s'ouvre mais vous voyez ça se referme directement donc ça c'est parce que il va falloir naviguer vers une page et ensuite attendre un petit peu pour pour pouvoir voir ce qu'il se passe donc on a différentes façons d'attendre je vais vous en montrer plusieurs donc là je vais faire page.gto et on va mettre l'URL de notre site ici enchaîne de caractère et là on va naviguer vers ce site donc là je relance ça va être un petit peu plus lent mais vous voyez on a une demi-seonde en plus et le navigateur se ferme tout de suite après donc ce qu'on peut faire ici c'est différentes choses on peut faire un page wait for time out donc ça c'est un peu comme un time point sleep c'est-à-dire qu'on va dire attends un certain moment donc on peut dire par exemple 5000 ça va être en millisecondes donc 5000 ça veut dire attend 5 secondes avant de continuer et donc de fermer le navigateur donc si je relance cette fois-ci on la voit et on remarque que c'est bien un navigateur Chrome si je change ici à la place pour mettre Firefox et que je relance vous allez voir qu'on va avoir un navigateur qui va ressembler cette fois-ci à Firefox donc le navigateur est un peu différent mais vous voyez qu'on a vraiment un navigateur comme on l'aurait si on le faisait de notre côté nous-même avec les navigateurs qu'on utilise donc je vais revenir sur chromium et on a d'autres façons d'attendre on peut faire un page point pause et là si je relance vous allez voir que ça va attendre un petit peu et ça va nous ouvrir le débuger ici qui va mettre en posuse en fait le fonctionnement du script et ensuite on peut résumer en cliquant comme dans n'importe quel débugers sur cette petite icône de resume et là on va continuer avec la suite de notre script on peut également utiliser le dbuger de pycharm directement pour mettre un point d'arrêt donc là je vais le mettre ici le script va donc se lancer jusqu'à cette ligne il va exécuter cette ligne et ensuite il va se mettre en pause parce qu'on a mis un point de débug ici donc c'est pas parce qu'on a mis page point pause ici je pourrais juste faire un print ça serait pareil c'est juste parce que là j'ai mis le point de débug de pcharm donc là pour avoir ça je vais relancer ici en mode debug donc debug JavaScript scrapping au niveau de pycharm vous pouvez faire bien sûr la même chose avec n'importe quel navigateur là on voit que la fenêtre a disparu alors c'est pas qu'elle a disparu c'est juste que pycharm a repris le dessus mais si je vais voir dans la liste de mes fenêtres on voit bien que le chromium est encore là et c'est juste qu'il faut le ramener de l'avant par-dessus pcharm et là donc l'intérêt c'est que on a on a le débugger de pycharm donc on peut voir notre browser la page et toutes les autres variables que l'on a à l'intérieur de notre script et on peut entrer des expressions ici si on souhaite les évaluer et faire du débug comme on le fera naturellement avec pycharm donc je vais arrêter le script donc vous voyez il y a différentes façons de faire pour arrêter le script et permettre d'évaluer les choses on peut faire le page pointpuse qui va lancer le debuger et on va voir qu'il y a aussi d'autres façons de lancer ce debuger sans passer par une ligne comme ça page.puse et en utilisant plutôt des variables d'environnement mais voilà vous avez la syntaxe de base qui vous voyez est très très simple de l'installation jusqu'à ici ça prend quelques secondes on a trois lignes de codes à mètrre et on a directement la possibilité d'ouvrir une page et par la suite d'interagir avec celle-ci maintenant qu'on a vu comment ouvrir une page avec playwright on va voir comment interagir avec la page que l'on a ouverte pour ça vous allez voir qu'on a beaucoup de fonctionnalités qui sont directement disponibles avec playwright et qui le rendent très facile d'util utilisation et notamment le debuger qui va nous permettre sans aller même voir la documentation de voir déjà ce qu'il est possible de faire playwright ça va fonctionner avec ce qu'on appelle des locators donc vous pouvez créer ces locators ici qui vont être des façons de récupérer des éléments sur la page il y a plein de choses qui sont possibles on peut utiliser les xpat on peut utiliser les sélecteurs CSS mais vous allez voir que la plupart du temps on aura même pas besoin de se casser la tête on va pouvoir juste utiliser le debugger pour aller analyser la page et voir ce qu'il est possible de faire avec donc là ce que je vais faire c'est c'est juste ouvrir le debugger de playwright donc on a vu qu'on pouvait faire un page point pause et qu'automatiquement ça va ouvrir le debugger ce qu'on peut faire également c'est rajouter une variable d'environnement alors on peut le faire directement dans le terminal ici avant de le lancer mon script je peux définir une variable d'environnement pwdbug qui va être égal à 1 et là je vais lancer avec Python 3 le script donc là c'est JavaScript scrapping.py donc je définis la variable d'environnement PW donc playwright debug = 1 et ensuite je lance le script et si je fais ça vous allez voir que automatiquement on a cette petite fenêtre qui s'ouvre qui est le débuger et que je vais pouvoir naviguer dans mon site comme ça et faire différentes actions donc là si je continue si je fais un step over ça va continuer à la prochaine action là forcément comme je ne fais rien après cette page ça va continuer ouvrir la page et fermer le script je peux aussi changer ma configuration ici si je le souhaite pour ajouter cette variable directement dans les variables d'environnement donc mettre un point virgule ici pwdbug é= à 1 et là de cette façon on va lancer notre script en mode debug donc je vais mettre JavaScript scrapping debug comme ça on sait quand on lance cette configuration ici que automatiquement ça va lancer le dbugger de playwright donc ça c'est une autre façon de faire là si je continue de nouveau ça va arrêter le script est fermé donc là qu'est-ce qu'on peut faire si on souhaite que le navigateur ne se ferme pas c'est faire le fameux page.puse je relance le script ici avec le mode dbug et je vais continuer donc faire un stepover en cliquant sur cette petite icône pour aller jusqu'au page point pause là le script va se mettre en pause donc donc là on voit un autre script qui est affiché vous pouvez revenir sur votre script principal en cliquant ici sur le sélectionneur de fichier pour revenir sur votre script et là on voit que la page est bien posée ce que je vais pouvoir faire maintenant donc de très intéressant avec ce debugger c'est utiliser soit cette petite icône pour afficher les selcteurs donc c'est un picker qui va me permettre d'afficher les différents locatur sur ma page soit utiliser le bouton record et ça va être un peu près la même chose sauf que ça va ajouter les lignes qui vont être générées par ce debuger dans un script donc je vais déjà vous montrer le locator ici piic locator on clique et là vous voyez qu'on peut afficher les différentes lignes de code qui peuvent être utilisé pour récupérer ces éléments donc si je veux récupérer le bouton vous voyez que j'ai un get by roll bouton avec le name par la suite donc si je clique ici en fait ce que ça va faire c'est m'afficher la ligne de code ici je peux la copier ensuite et la mettre dans mon script et si je fais record qu'est-ce que ça va faire ça va faire la même chose sauf que ça va écrire ces lignes dans un nouveau fichier donc si je veux par exemple sélectionner le le heading ici je peux cliquer dessus ensuite je peux cliquer sur la note ensuite je peux cliquer sur le bouton et ensuite arrêter le record et là vous voyez que ça m'a créé en fait un script avec exactement ce qu'on avait mis ici avec un peu plus de syntaxe autour mais on a bien notre playri syn API ensuite il a juste fait une fonction run dedans dans laquelle il passe notre instance de playwright et ensuite on a le context manager ici et on a notre browser avec un nouveau contexte qui est créé et ensuite les lignes de code qui nous permett d'effectuer les mêmes actions que celles qu'on vient de faire et d'enregistrer sur notre page donc là on peut copier juste ce qui nous intéresse moi je vais copier juste le page.getby roll bouton et copier tout ça ici et à la fin vous voyez qu'il fait juste un browser.close et un context.close dans ce script donc je vais arrêter tout ça et là on peut revenir dans notre script enlever le page.pose ici et juste mettre la ligne qu'on a copié donc page.getby roll bouton name = récupérer les livres secrets là bien sûr on peut le faire en différentes étapes on pourrait enlever le point clic et déjà faire une variable bouton et ensuite vérifier est-ce qu'on a un bouton et et si oui faire un bouton point clic par exemple et ensuite on pourrait faire un page wait for time out ici on va mettre 10 secondes pour attendre je vais relancer mon script cette fois sans le mode debug donc je vais enlever le PW debug de ma configuration ce que je fais généralement c'est dupliquer cette configuration enlever le dbug ici enlever ma variable et comme ça j'ai deux deux configurations la variable ici avec le PW Debug et la et la configuration sans et comme ça je peux choisir entre l'un et l'autre donc là je vais le lancer euh sans le débug je relance le script et on va voir qu'on ouvre la page on clique direct sur le bouton et on a bien les deux livres qui sont affichés et ensuite on attend 10 secondes et on va fermer le navigateur donc je peux effectivement pour bien m'assurer que tout est fermé à la fin faire un browser. close sinon notre navigateur n'est pas correctement fermé et il faut qu'on arrête le script pour bien tout fermer donc vous voyez là c'est assez rapide on a tout qui se déroule en quelques millisecondes là je peux refaire un page wait for timeout ici de 1 seconde par exemple pour voir un peu moins rapidement ce qui se passe et là vous voyez qu'on ouvre la page on attend une seconde on clique sur le bouton et ensuite on attend 10 secondes et on va fermer la page et le navigateur en fait avec notre browser. close hop et là on est sorti du script puisqu'on a fermé le navigateur donc vous voyez c'est très très facile comme ça de récupérer des éléments on va voir dans d'autres parties tout ce qu'on peut faire là on a le get by roll qui permet de récupérer des éléments sur la page en fonction de leur rôle donc par exemple des boutons des liens des boîtes de texte et cetera et on va pouvoir cibler spécifiquement ces éléments avec des filtres donc là on a entré le name donc le name qui indique que le bouton doit avoir ce nom ici sur le bouton si on va voir la page donc si je fais un clic droit sur le inspect et que j'affiche ce bouton vous voyez qu'on a aussi un ID donc on va voir dans les prochaines parties qu'il y a beaucoup de façons différentes de récupérer les choses mais là avec le débuger vous voyez que c'est déjà une première façon sans avoir besoin d'ouvrir la doc de voir qu'est-ce qu'on peut faire pour commencer à interagir avec la page qu'on va scrapper dans cette partie on va aller un peu plus loin et je vais vous montrer d'autres façons d'interagir avec les pages qu'on va scrapper je vous conseille vraiment d'aller voir la documentation de playwright elle est très bien faite donc vous avez la référence de la pays en cliquant ici avec toutes les classes que vous pouvez utiliser qui sont bien définies avec des commentaires à chaque fois qui expliquent tout ce qui se passe et vous avez également la documentation qui explique comment installer playwright comment également faire des tests parce que playwright est au départ un outil pour tester des sites web plus que pour faire du scrapping même si on peut l'utiliser pour les deux et faites bien attention quand vous allez dans la documentation vous pouvez l'afficher en différents langages donc on a python ici en premier mais je crois que ça arrive assez souvent que par défaut il affiche node GS surtout si vous chercheer à partir de Google en fait souvent vous allez avoir les réponses à votre question mais pas forcément dans le langage que vous souhaitez donc n'hésitez pas si vous êtes avec notre JS ici de revenir sur python les pages ne sont pas tout le temps disponibles dans les deux langages puisqu'il y a quand même un petit peu de différence entre l'un et l'autre donc il arrive quand vous êtes sur une page précise que vous changiez de librairie en allant de Python à notre JS et que vous tombiez des fois sur une une page 404 puisque il y a pas une concordance 100 % exacte entre les deux mais voilà n'hésitez pas à regarder tout ça et à changer le langage ici pour être sûr d'être avec Python donc dans cette partie qu'est-ce qu'on va regarder on va regarder les locators donc je vais vous montrer ici dans la documentation je vais grossir un petit peu vous allez voir qu'on a plein de façons de récupérer des éléments sur la page on a des façons un peu plus avancées et très précises qu'on utilise généralement dans d'autres bibliothèque comme le CSS et le xpat donc vous voyez ici on peut indiquer avec CSS égal ou avec XPath égal qu'on souhaite utiliser ses façons de faire et on a cette méthode donc locator qui nous permet de créer un locator donc le locator c'est quelque chose qui va localiser comme son nom l'indique quelque chose sur la page et ensuite une fois qu'on l'a récupéré on peut effectuer des actions dessus comme par exemple cliquer sur un bouton où on peut également faire d'autres actions comme remplir un locator avec des informations ça c'est notamment valide pour tout ce qui est boîte de texte donc toutes les balises HTML dans lesquelles on peut rentrer des informations vous voyez qu'à chaque fois fois vous avez le code également Sync et a Sync la seule différence entre les deux la plupart du temps étant que vous devez attendre avec le mot-cé await quand vous faites une opération asynchrone mais comme je vous dis voilà nous on va rester sur du syn ça fait quelques quelques lettres en moins à écrire et pour toutes ces parties ça ne change absolument rien vous voyez que le reste du code est absolument identique donc les locator qu'est-ce qui est intéressant c'est qu'on a beaucoup de fonctions par défaut qui nous sont donné qui sont des fonctions donc ces fonctions ici get by roll qu'on a vu qui permettent de récupérer un élément en fonction de son rôle sur la page on a get by text get by label Get by test ID aussi donc test ID c'est une un attribut qui est sur les balises HTML qui est généralement utilisé pour faire des tests justement donc c'est un attribut qu'on met pour pouvoir cibler très précisément les éléments et vous allez voir que c'est très pratique parce que souvent les plateformes l'utilisent et on va pouvoir aussi l'utiliser du coup non pas de notre côté pour faire des tests mais pour faire du scrapping si on va voir la documentation vous allez avoir des exemples très précis avec le code à chaque fois et les différents éléments avec des petits des petits navigateurs ici très pratiques sur lesquels on peut interagir donc comme je vous dis la documentation est un très bon point d'entrée pour commencer à voir ce que vous pouvez faire avec ces différentes méthodes donc nous on va revenir dans notre projet et je vais vous montrer celle que j'utilise le plus souvent et comment les utiliser dans le cas de cette page pour récupérer les informations qui nous intéressent donc comme on l'a vu pour récupérer ce bouton on peut utiliser le get by roll get by roll ça va permettre d'aller récupérer un élément en fonction de son rôle sur la page vous pouvez retrouver ces éléments en allant de la documentation de playwright cette fois-ci non pas dans la documentation qu'on était en train de regarder donc la documentation des locator mais en allant dans laapi directement donc si vous allez dans laapi dans locator vous allez trouver la méthode GET by roll et vous allez avoir un peu plus d'information sur ce que vous pouvez utiliser donc dans les arguments ici on a le premier élément le premier argument qu'on peut envoyer en fait qui est l'argument du rôle et là vous voyez tout ce qu'on peut utiliser donc on va retrouver le bouton on a pas mal d'autres choses on a par exemple les tool types les tool bar on a les text BO on a les formes les combo box les alertes les bloc codes donc on a vraiment beaucoup de choses ici qu'on peut récupérer à travers ce get by roll comme on l'a vu également on peut utiliser donc des sellecteurs CSS donc ça c'est quelque chose avec lequel on est généralement plus familier quand on utilise des bibliothèques comme beautiful soup alors pour le CSS on va devoir spécifier dans la chaîne de caractère ici CSS égal et ensuite on va mettre notre selecteur CSS donc dans ce cas-ci on a différentes choses qu'on peut utiliser si je fais un clic droit et que je fais un inspect sur ce bouton on voit que le bouton il a un ID get secret books donc pour ça je pourrais faire un diz get secret books et on va voir si je mets mon point de débug ici et que je lance le script en dbug si on a bien récupéré le bouton qui nous intéresse donc je lance le debug là comme je vous dis on a le navigateur qui semble se fermer mais en fait c'est juste qu'il est caché par pycharm qui se remet devant donc je peux le mettre de côté ici mettre ma fenêtre avec le chromium qui a été ouvert à droite et là on voit qu'on a bien récupéré un bouton donc on voit qu'on a un élément dedans dans cette variable et je peux tester cet élément donc je vais décaler encore un petit peu pour qu'on voit bien ici on peut tester ensuite dans cette boîte pour évaluer notre expression on peut tester en faisant un bouton point clic pour tester notre clic et voir si ça fonctionne donc j'appuie sur Entrer et là on voit que le clic fonctionne et qu'on a bien donc récupéré le bouton sur lequel on voulait cliquer donc ça c'est une première façon de faire une autre façon de faire c'est d'utiliser les expat donc les xpat c'est un truc un peu plus précis même très précis on va pouvoir le découvrir également en inspectant avec un clic droit le bouton et là je vais faire un clic droit sur cet élément dans le html qui va être affiché clic droit et là on va pouvoir copier le xpat donc on a un xpat relative ou un xpat complet à partir de la racine de notre HTML donc le xpat complet ça va être assez long vous allez voir si je le mets ici dans ce cas-ci en fait c'est assez court mais dans des sites beaucoup plus complexes vous allez voir que vous allez vous retrouver avec des chaes caractère très longue parce que là vous voyez avec le le xat complet on part du HTML on va va ensuite sur le body et ensuite on va récupérer le bouton donc là pour indiquer que c'est un expat je dois mettre expat égal et rajouter un slash au début je vais relancer en mode débug pour voir si ça fonctionne de nouveau donc là on a bien notre bouton je vais remettre de l'avant mon navigateur ici je vais le mettre sur le côté et là on va refaire un bouton point clic et vous allez voir que ça fonctionne de la même façon donc une autre façon de récupérer les éléments de façon très précise ici avec le xpat mais c'est généralement pas quelque chose que je conseille parce qu'il suffit qu'il y ait une seule chose qui change bon là bien sûr c'est juste HTML et body donc ça risque pas vraiment de changer mais quand on a des éléments qui sont vraiment imbriqués très loin dans le DOM ça va être très long ici et ça risque si vous partez vraiment du début si vous partez du HTML body donc avec un chemin complet de xpat c'est très très probable que le Document Object Model donc le code HTML change et que le xpat ne fonctionne plus assez rapidement donc je vous conseille de cibler plus facilement avec le ID par exemple comme on l'a fait avec le CSS le id dit ça risque beaucoup moins de changer donc je vous conseille de passer par ça une erreur que je vois aussi beaucoup c'est les gens qui pensent en fait que play right est un outil qui va nous permettre directement de faire du scrapping alors ne confondez pas playright avec beautiful soup on peut récupérer bien entendu des informations avec playwright donc si par exemple je veux récupérer le titre des livres ici si je fais un clic inspect sur super livre on voit que c'est un H2 donc je pourrais très bien ici faire un locator faire CSS é= H2 et là si je relance le script donc on va arriver jusqu'ici bouton et là si je fais un bouton point text content je peux récupérer le contenu qui est à l'intérieur donc là dans ce cas-ci ça va être livre 1 puisque livre 1 ici est un H2 et si je vais voir sur les autres ça doit être oui c'est aussi des H2 donc je les ai tous mis en H2 on a le H1 ici qui est le all books donc on peut très bien faire ça utiliser playwright pour récupérer des informations mais ça ne va pas être la façon la plus optimale de faire c'est beaucoup mieux en fait si vous souhaitez récupérer des informations d'utiliser un outil outil qui va analyser l'entièreté du votre Document Object Model donc un outil comme beautiful soup et on va pouvoir à partir de la page à partir de page. content récupérer l'entièreté du HTML pour l'analyser donc je vais vous montrer ici j'arrête le script je vais faire from BS4 import beautiful soup donc installez-le avant avec PIP si vous souhaitez l'utiliser pour faire comme moi donc là qu'est-ce que je vais faire je vais dire HTML égal à page content donc on va récupérer l'entièreté du contenu et je vais la passer à beautiful soup donc avec beautiful soup HTML et on va donner le html.pser ici et là si je fais un print de soup. pretttify on va retrouver l'entièreté de notre de notre HTML dans la console donc si j'enlève le point Debug et que je relance le script là on ouvre le document et on se retrouve bien avec l'intégralité de mon HTML donc à partir de ça par la suite je peux aller chercher des éléments donc je peux faire un print de soupselect et on va récupérer tous les éléments qui sont DH2 et à la place d'un print je peux faire une boucle donc je peux dire pour titre in tout ça hop on va faire un print de titre point texte et là si je lance vous allez voir qu'on récupère bien le livre 1 donc seulement le livre 1 parce qu'on a pas cliqué sur le bouton donc là vous allez voir à quel point on peut maintenant mettre tout ça en pratique pour faire une action et ensuite récupérer les éléments donc là avant le html.page content ce que je vais faire c'est que je vais faire cette action qu'on avait faite donc l'action de récupérer le bouton donc là je vais réutiliser en fait le ID que j'avais donc je me souviens plus c'était get secret books donc je vais refaire mon locator avec le CSS qui est égal à Diaz get secret book et on va faire un clic sur le bouton et ensuite après ça je vais faire un petit wait for timeout pour qu'on que ça n'aille pas trop vite pour que vous puissiez bien voir ce qui se passe après ça donc une fois qu'on a cliqué sur le bouton là je vais récupérer le contenu de la page donc une fois qu'on a cliqué sur le bouton pour avoir les deux autres livres qui sont dans le html et à partir de ça on va analyser le html avec beautiful soup et ensuite récupérer les titres donc je relance on a le navigateur qui s'ouvre le bouton qui est cliqué et là vous voyez qu'on arrive bien à récupérer toutes les les informations après le clic et pour vous terminer là-dessus et vous montrer si je mets le headless en true on va avoir ainsi un script qui permet d'effectuer une action sur la page et de récupérer les éléments après avoir effectué cette action et tout ça sans avoir besoin d'ouvrir de navigateur vous voyez là on a l'impression que j'ai fait exactement comme je le ferais avec request juste une requête alors qu'en fait il y a beaucoup de choses qui se passent en arrière-plan on ouvre le navigateur on clique sur le bouton on attend un petit peu on récupère le contenu du HTML et ensuite on extrait les informations avec beautiful soup donc vous commencez j'espère à voir la puissance de cette bibliothèque et la facilité d'utilisation également de celle-ci c'est vraiment un sujet infini on pourrait faire une formation complète de plusieurs heures juste sur playwright pour l'instant ce que je vous conseille c'est vraiment d'aller éplucher la documentation pour voir toutes les façons de faire d'utiliser également le debuger pour explorer comment vous pouvez naviguer sur des sites donc n'hésitez pas à ouvrir des sites un peu plus complexe et d'analyser avec le locator ou avec le bouton record pour voir toutes les actions que vous pouvez faire en fonction des éléments sur votre page pour naviguer exactement où vous le souhaitez et ensuite utiliser donc des bibliothèques comme beautiful soup pour une fois que vous êtes arrivé à l'endroit où vous voulez avec les informations que vous voulez faire du scrapping de façon plus efficace avec un outil qui est fait pour ça comme beautiful soup dans les prochaines parties on va voir comment contourner tous les obstacles qu'on a vu précédemment de façon professionnelle et sûre avec le sponsor de cette vidéo bright data bright data il propose plusieurs solutions qui répondent à différentes problématiques avec différents niveaux de prix et c'est tout ça qu'on va voir dans les prochaines parties pour savoir quelle solution envisager pour quel besoin vous allez voir qu'ils ont pensé à tout et qu'on a vraiment des outils très bien pensés qui vont nous assurer de ne jamais être bloqués dans notre scrapping et de le faire de façon éthique on va passer à travers la création de votre compte avec les 20 dollars de crédit qui vous sont offerts avec cette vidéo et on va voir comment créer et activer les trois outils qu'on va voir ensemble dans les prochaines parties à savoir le réseau de proxy résidentiel le web Locker et le scrapping browser et si vous avez le moindre souci avec bright data il dispose d'un support très réactif qui est disponible directement sur votre compte alors n'hésitez pas à rentrer en contact avec eux si vous avez le moindre souci lors de l'utilisation de ces outils dans cette partie on va voir ensemble les trois solutions qui nous sont proposées par bright data pour faire du scrapping vous allez voir que c'est peut-être un petit peu confus au début parce qu'il y a beaucoup de solutions qui sont proposées mais j'espère qu'après cette vidéo vous aurez une meilleure idée de ce que vous pouvez choisir en fonction des cas d'usage et on verra dans les projets qui vont suivre dans cette vidéo également avec Airbnb et Amazon quels outils vous pouvez utiliser pour votre scrapping la première solution qui existe c'est une solution assez simple qui s'appelle les proxy résidentiels donc ça si vous voulez pour faire simple c'est un petit peu comme si on utilisait un VPN ça va permettre de changer votre adresse IP et de potentiellement choisir également le pays et même la ville à partir de laquelle vous souhaitez accéder à un service donc ça peut être pratique si par exemple vous êtes bloqué avec votre IP si vous avez trop rafraîchi un site pour récupérer des informations vous pouvez grâce à ces proxy résidentiels changer d'adresse IP pour pouvoir accéder de nouveau à un site donc c'est un service qui marche très très bien qui est efficace assez rapide mais qui ne contient aucune fonctionnalité un peu plus avancé comme ce qu'on va voir avec d'autres outils spécifiques pour le scrapping que sont le web Unlocker et le scrapping browser donc scrapping navigateur en français donc le web Unlocker c'est un niveau au-dessus ça va aussi faire une rotation de vos IP donc ça va changer votre adresse IP si jamais vous êtes bloqué ça va faire tout ça automatiquement pour vous mais il va également avoir un outil de résolution de capcha donc vous pouvez voir ici tout ce qu'il y a de disponible on a le rendu JavaScript aussi très important si vous avez des sites Web qui contiennent du contenu généré par JavaScript et on va avoir une rotation comme je vous disais automatique des adresses IP donc ça c'est une solution très bon marché qui vous permet d'être quasiment assuré à chaque fois d'avoir accès à un site qui vous bloquerait avec des outils qui vont faire tout ça pour vous donc vous avez pas besoin de votre côté de choisir quand est-ce qu'il faut changer les IP quand est-ce qu'il faut faire une résolution de capcha et cetera c'est vraiment le web Unlocker tout seul qui va faire ça en arrière-plan qui va essayer différentes techniques pour débloquer le site et vous assurer que vous avez accès à ce que vous recherchez le dernier élément qu'on a c'est le donc scrapping browser qui est tout nouveau et qui permet d'aller encore plus loin donc qui a également les mêmes outils que le web Unlocker à savoir la résolution des capcha la rotation d'adresse IP et cetera mais avec la possibilité de l'utiliser avec des outils comme pettir play et sééium donc là on va un niveau dessus ça vous permet de faire exactement la même chose que ce que vous feriez avec un navigateur donc ça c'est bien si vous avez des interactions à faire avec le site si vous voulez naviguer sur le site cliquez sur des boutons remplir des informations vous allez pouvoir faire tout ça avec le scrapping browser et un outil comme playwright qu'on va voir dans les prochaines parties que l'on peut utiliser avec Python pour ouvrir un vrai navigateur qu'on pourra ouvrir en avant-plan ou en arrière-plan donc pas de panique vous n'allez pas être obligé de laisser votre ordinateur allumer avec un écran ça peutre très bien se faire également en arrière-plan sans avoir besoin d'ouvrir d'interface mais le navigateur avec playright lui va quand même fonctionner sans qu'on le voit et ça va donc nous permettre comme c'est indiqué ici de contourner les blocages les plus complexes au niveau des tarifs il y a beaucoup de tarifs différents avec à chaque fois des possibilité de souscrire à des abonnements qui vont vous donner accès à un prix préférentiel mais vous pouvez également les utiliser sans aucun engagement vous voyez également qu'on a différentes options ici on a les proxis résidentiels les proxis de centre de données on va revenir en détail sur la différence entre les deux puisque que vous voyez qu'il y a une énorme différence de prix entre les deux malheureusement les proxy de centre données obtiennent généralement des moins bons résultats si vous voulez être débloquer sur certains sites je vais vous expliquer tout ça en détail pas de souci donc là on voit qu'on a un prix qui est calculé en fonction de la bande passante que vous allez utiliser si on va voir par contre les prix pour le web Unlocker là vous voyez qu'on est avec un coût par 1000 donc ça va être un coût en fonction des requêtes réussies là encore vous avez une formule sans engagement ou une formule avec un paiement mensuel qui vous permet d'avoir accès à un prix inférieur et donc le coûp par 1000 c'est vraiment à chaque fois que vous avez une requête qui est correctement effectuée et bien vous allez être facturé et là vous allez être facturé 3 dollars pour 1000 requêtes réussies donc vous voyez que les prix sont quand même assez faibles 1000 requêtes ça laisse le temps de voir venir si vous récupérez des données avec une requête qui est effectuée par exemple trois fois par jour vous allez pouvoir faire des requêes pendant à peu près 1 an et ça vous coûtera 3 dollars donc vous voyez que ça vous laisse quand même le temps de voir les choses venir et finalement le scrapping browser on a un prix qui est là encore possible sans engagement ou avec un engagement mensuel avec un prix qui est là encore réduit et on revient ici sur un fonctionnement en bande passante donc dans les parties qui vont suivre je vais vous présenter ces trois outils un peu plus en détail on va voir comment les utiliser dans notre script Python vous allez voir également que sur chacun de ces outils vous avez un onglet statistics qui vous permet de voir très précisément quel est votre utilisation de ces outils donc vous pouvez monitorer tout ça et vous assurer de ne pas dépenser trop d'argent vous pouvez mettre des limites également vous allez pouvoir monitorer tout ça en allant dans vos options de paiement ici donc en bas à gauche vous avez la petite option billing et pour vous donner une idée vous voyez que moi avec tout ce que j'ai fait comme test donc ça fait 2 mois que je prépare cette longue formation j'ai fait beaucoup beaucoup de tests d'essais d'erreurs avec le scrapping browser avec le web Unlocker et avec les proxy résidentiel et vous voyez que je ne suis même pas à 5 dollars de dépenser donc vous voyez que pour des besoins personnels ça reste quand même assez raisonnable et là vous avez les détails de votre plan donc moi vous voyez que je suis avec le plan Pyg qui veut dire pay as you go donc je n'ai pas un abonnement mensuel c'est vraiment à chaque fois que j'utilise quelque chose que ce soit les proxy que ce soit le web Unlocker le crapping browser donc là on a tous les prix qui sont remis ici et bien je vais payer en fonction de l'utilisation que je fais de ces outils donc pour résumer on a les proxy donc les proxy que ce soit résidentiels ou des proxy de centre de données qui nous permettent tout simplement de changer d'adresse IP dans le cas on souhaite accéder à un site Web depuis une zone géographique précise ou parce que notre IP a été bloqué on a ensuite le web Unlocker qui lui va beaucoup plus loin avec également la possibilité de changer d'IP mais de façon automatique avec une résolution également décapchat le rendu du Javascript et l'empreinte de navigateur par empreinte de navigateur on entend par là tout ce qui fait qu'un navigateur semble être utilisé par un humain donc ça va être les enentêtes les headers en anglais les cookies et cetera et pour finir donc on a le scrapping browser qui permet également la résolution des CapChat la rotation automatique des IP le rend du javascript l'empreinte du navigateur mais également l'utilisation avec des outils comme playwright pour pouvoir faire des interactions avec la page donc c'est l'outil ultime qui permet de résoudre toutes les situations de blocage potentiel mais également de faire exactement la même chose que ce que vous feriez si vous étiez un humain qui naviguait sur un site web pour créer votre compte sur bright data rendez-vous à l'adresse brdta donc l'abréviation de Bright data.com/docstring je vous conseille d'utiliser le lien qui est dans la description si jamais il y a un changement ou quoi que ce soit ce lien sera assurément à jour donc vous êtes assuré avec le lien dans la description de bien avoir les 20 dollars de crédit gratuits qui sont offerts avec cette formation donc vous accédez à brdta.com/docstring vous allez arriver sur le site de Bright data et il ne vous reste plus qu'à cliquer sur Start free trial pour avoir la fenêtre qui va s'ouvrir dans laquelle vous pouvez créer un compte vous pouvez continuer avec votre compte Google ou créer un compte ici en entrant votre prénom votre nom de famille votre adresse mail et pour la taille de la compagnie vous pouvez tout simplement mettre 1 à 9 employés si vous utilisez ça pour des besoins personnel vous cliquez sur la checkbox ici et ensuite vous pourrez créer votre compte vous allez ensuite recevoir un email il vous suffit de cliquer sur le lien dans l'email pour valider la création de votre compte et vous arriverez sur la page d'accueil de Bright data et une fois que votre compte est créé et validé vous pouvez également retourner sur briitedata.com pour accéder ici en haut à droite à votre tableau de bord en cliquant sur user dashboard si jamais vous n'êtes pas sûr même après avoir vu cette formation de quelle solution est la meilleure pour votre besoin de scrapping n'hésitez pas à parler avec les experts de Bright data vous avez le lien directement ici vous allez pouvoir échanger avec eux afin de savoir quelle est la solution optimale pour vos besoins n'oubliez pas également en bas à gauche ici d'aller voir dans les options de billing pour voir si vous avez bien eu les 20 dollars de crédit qui vous sont offerts avec cette formation quand vous allez créer pour la première fois un outil que ce soit le réseau de proxy ou le web Unlocker et le scrapping browser quand vous allez activer le proxy vous allez voir qu'on va vous demander des informations supplémentaires les informations qui vous sont demandées notamment dans l'utilisation du réseau de proxy ça va être nécessaire si vous voulez utiliser le réseau de proxy résidentiel sur des sites qui ne sont pas supportés par défaut donc vous allez voir dans la liste ici il y a beaucoup de sites par défaut auxquels vous pouvez accéder sans passer par ces vérifications mais si vous écoutez l'entrevue que j'ai fait avec Rony shalid vous allez voir qu'ils ont tout un processus qui est certes un petit peu long mais qui permet de s'assurer de l'utilisation correcte de leur réseau donc un processus qui s'appelle No your customer ils veulent en fait tout simplement s'assurer que vous allez utiliser leur réseau pour des besoins qui ne vont pas contre leur conditions d'utilisation donc là encore je vous renvoie à mon entretien avec Rony Charal si vous voulez avoir plus d'informations sur le sujet et voir à quel point c'est important d'avoir ces mesures même si ça ralentit un un petit peu le processus d'boarding c'est très important à la fois pour vous et pour bright data d'avoir ces processus en place je sais que ça peut être frustrant mais pour moi c'est vraiment la marque d'une compagnie qui prend ce sujet à cœur et qui fait les choses bien donc je vous laisse explorer tout ça les différents outils qui sont disponibles ne vous inquiétez pas ça ne va pas vous charger de l'argent même si vous créez les outils il faut vraiment les utiliser et on va voir comment le faire avec du python pour utiliser ces outils mais ne vous inquiétez pas vous pouvez par exemple ici créer un scrapping browser pour voir à quoi ça ressemble sans avoir besoin de l'utiliser et sans avoir d'argent qui va être retiré des 20 dollars de crédit que vous avez tant que vous ne l'utilisez pas si vous n'avez pas envie de faire de code vous pouvez également aller voir tous les datasets qui sont disponibles alors ça coûte assez cher c'est vraiment pour des usages très précis et professionnels mais ça peut être intéressant de voir quand même des extraits c'est toujours intéressant de voir le type de données qui sont à disposition donc par exemple ici si je vais regarder pour Airbnb vous allez voir qu'on a pas mal d'informations qui sont donc ce qu'on appelle des datasets qui sont des données que vous pouvez acheter pour avoir directement des données à exploiter pour faire des analyses des statistiques et cetera dans cette partie on va voir comment utiliser le réseau de proxy résidentiel de brght Data pour contourner les blocages par limitation de requête et donc le blocage d'une adresse IP mais avant de passer à la pratique on va d'abord s'intéresser à ce qu'est un proxy et comment cette technologie fonctionne un proxy c'est tout simplement quelque chose qui va être entre vous et le serveur auquel vous voulez accéder dans un cas classique vous avez votre ordinateur personnel avec une adresse IP qui vous est donnée par votre fournisseur d'accès à Internet par exemple en France ça peut être Orange buig SFR et cetera et vous avez un site auquel vous souhaitez accéder donc vous allez envoyer une requête vers les serveurs de ce site par exemple ici lebcoin.fr vous faites donc une requête vers ce serveur et le serveur vous renvoie la réponse et vous pouvez faire cela encore et encore jusqu'à ce qu'un moment peut-être le serveur vous bloque parce qu'il considère que soit vous êtes un script soit vous avez fait trop de requêtes même m si vous ne passez pas forcément par un script il peut décider quand même que ça suffit vous avez trop abusé et il bloque donc votre adresse IP ça peut être un blocage de plus ou moins longue durée il peut décider de vous bloquer pour quelques secondes quelques minutes voire indéfiniment et c'est là qu'on peut faire intervenir donc un proxy le proxy va se placer entre vous et le serveur auquel vous souhaitez accéder vous allez donc faire une première requête vers un serveur qui est le serveur de proxy qui va transmettre votre requête au site auquel vous souhaitez accéder et de la même façon en retour le serveur va envoyer au proxy les informations que vous souhaitez récupérer et le proxy va vous les transmettre pour que vous puissiez y avoir accès et ce serveur qui sert de proxy il a également son adresse IP qui va être différente de la votre et c'est de cette façon que vous allez pouvoir continuer à faire des requêtes grâce à ce proxy vers le site qui vous intéresse mais là encore le proxy peut à un moment être bloqué de la même façon que vous le site Le beaucoin peut considérer que ce proxy avec cette adresse IP a également fait trop de requêtes et dans ce cas-ci vous pouvez utiliser une rotation de proxy rotation qui va être gérée automatiquement par le service de proxy de Bright data que je vais vous présenter et ainsi en changeant d'adresse IP vous pouvez de nouveau accéder au site et ainsi de suite à chaque blocage Vous changez d'adresse IP et ainsi vous vous assurez de ne jamais être dans une situation de blocage les proxy c'est bien important de comprendre qu'il y en a deux types il y a les proxy de centre de données donc les fameux Data Center et les proxy résidentiels la différence entre les deux c'est que les proxy de centre de données ils vont être plus rapides moins cher et plus stable alors plus stable qu'est-ce que j'entends par là non pas qu'ils vont fonctionner mieux que les proxy résidentiel parce que vous allez voir que assez rapidement ces proxis peuvent être bloqués quand je dis plus stable c'est-à-dire que les serveurs qui sont dans les centres de données dispose généralement d'une meilleure connexion et de meilleur matériel que ce qu'un particulier peut avoir chez lui c'est donc dans ce sens que je parle de stabilité ici dans le sens où vous allez avoir du matériel qui va être beaucoup plus performant au niveau du proxy résidentiel on a par contre quelque chose chose qui est beaucoup plus difficile à détecter de la part des sites web parce qu'un proxy résidentiel c'est exactement la même chose que si vous utilisiez votre propre ordinateur personnel pour accéder à un site donc il n'y a pas de différence pour le site web qui reçoit la requête entre vous et un proxy résidentiel il est donc plus fiable dans ce sens mais il peut être un peu plus lent que un proxy de centre de données parce que forcément ça va passer à travers des connexions qui vont être beaucoup plus éclectique que ce qu'on pourrait avoir avec un centre de données et ça va être également plus cher que un prox de centre de données donc le proxy résidentiel c'est la solution vers laquelle on va se diriger si on veut être assuré de ne pas être bloqué le proxy résidentiel la différence c'est que l'adresse IP va être fournie par un FAI un fournisseur d'accès à internet comme on l'a dit donc par exemple AT&T aux États-Unis ou en France orange et cetera et donc c'est ça qui fait que l'adresse IP que vous allez utiliser et le réseau de proxy résidentiel va être la meilleure solution si vous voulez être absolument sûr de ne jamais être bloqué les proxis de centre de données pour en avoir utilisé c'est des proxy que vous pouvez utiliser dans des cas plus spécifiques quand vous savez vraiment que vous n'allez pas être bloqué mais la plupart des sites grand publics bloqu directement ces proxy qui passent par les centres de données donc si vous voulez accéder au sitite web que vous utilisez généralement le proxy résidentiel va être à privilégié dans le cas de Bright data il dispose des deux donc vous pouvez choisir et dans notre cas on va voir comment mettre en place les solutions de proxy résidentiel donc pour utiliser le réseau de proxy résidentiel vous pouvez l'ajouter sur votre tableau de bord vous cliquez sur Add ici et vous ajoutez residential proxies moi j'en ai déjà un qui est créé ici donc je vais pouvoir cliquer dessus pour accéder à sa configuration vous avez ici le host le USERNAME et le password et c'est ça qu'on va utiliser pour générer l'URL qu'on va utiliser en tant que proxy vous avez différentes options ici vous pouvez ajouter un autre mot de passe si vous le souhaitez pour avoir différents mot de passes pour différentes personnes ou différents usages vous pouvez également mettre des adresses IP ici qui vont être autorisé par défaut elles sont toutes autorisées il n'y a aucune adresse de bloqué donc vous pouvez mettre ici des adresses IP qui vont être les seules autorisé à utiliser ce réseau de proxy et vous avez quelques exemples de code ici à droite avec la documentation n'oubliez pas d'activer votre proxy pour pouvoir l'utiliser et on va voir les exemples de code et comment on peut les utiliser avec le module request dernière chose ici vous avez la configuration qui est assez intéressante parce qu'on peut spécifier ici dans geolocation targeting un pays et également une ville donc si vous souhaitez pouvoir cibler également un état ou un pays ou même un zip code donc un code postal vous pouvez les ajouter ici ça va être un petit peu plus cher je vais rajouter City ici pour vous montrer comment on peut cibler un pays et une ville précise vous voyez qu'ici le coût a augmenté donc je vais cliquer sur Save on va me dire que je vais passer d'un package de 10.5 dollars par gig à 21 par gig donc je peux confirmer ici avec yes et on va avoir également un dernier onglet statistique ici avec un aperçu de la bande passante que j'ai utilisé avec ce proxy donc si je reviens dans Access parameter ici on peut cliquer sur checkout code and integration examples et vous allez avoir ici des exemples avec l'API avec Python donc vous voyez on a un script assez compliqué ici on va voir que ça a pas besoin d'être aussi compliqué que ça là on a un script qui va vérifier en fonction de votre version de Python si c'est avec Python 2 ou Python 3 quelle librairie utiliser donc là par exemple vous avez six et ici vous avez urlb.request nous on va utiliser le package request qu'on a téléchargé dans notre projet et ce qui nous intéresse ici c'est juste cette chaîne de caractère donc le dictionnaire avec la clé HTTP et la clé HTTPS qui va contenir l'URL de votre proxy on va retrouver ici le nom d'utilisateur le host et le mot de passe qui vont être intégré directement dans l'URL donc vous pouvez copier tout ça ici et on va revenir dans notre script pour voir comment on peut l'implémenter donc dans mon script ici je fais une requête vers cette URL qui est l'URL qui est disponible ici sur votre tableau de bord donc vous voyez lumetest.com/myip.jason donc vous pouvez accéder à cette url si vous voulez voir ce que ça donne vous allez avoir un retour en Jason avec votre adresse IP le pays la ville et cetera et donc si je reviens dans mon script je vais faire une requête vers cet API qui va me permettre de récupérer ces informations donc je lance le script et là on voit que pour l'instant je suis bien localisé au Portugal à Porto avec mon adresse IP ici et maintenant je vais prendre le dictionnaire que j'ai copié je vais le mettre dans une variable que je vais appeler proxy et on va coller notre dictionnaire ici avec la clé HTTP et la clé HTTPS et ensuite il ne reste plus qu'à passer cette variable ici à un paramètre qui s'appelle également proxy donc ça c'est bien le nom du paramètre ici on pourrait l'appeler Patrick c'est juste le nom de la variable et là on a proxis qui est le nom du paramètre auquel on va donner ce dictionnaire avec les proxy et là si je relance vous allez voir que notre adresse IP ainsi que le pays et la ville auront changé parce que on va passer cette fois-ci par un IP donc vous voyez que c'est un petit peu plus long c'est ce que je vous disais dans des parties précédentes ça va prendre un petit peu plus de temps puisqu'on a un proxy entre nous et la requête donc on va faire notre requête au proxy le proxy va transférer notre requête dans ce cas-ci à cette url lum test et ensuite lum test va renvoyer la réponse au proxy qui va de nouveau nous la renvoyer donc on a une boucle en plus qui fait que ça prend un petit peu plus de temps donc vous voyez que là je suis localisé en Australie à Sydney et que mon adresse IP a bien été modifiée et si je reviens sur mon tableau de bord en configuration vous pouvez donc comme on l'a vu ici ajouter un pays et une ville si vous cliquez sur learn more ici vous allez arriver vers une page qui vous explique comment cibler un pays et une ville donc on voit ici qu'il faut modifier notre URL en rajoutant country t le nom du pays et City et le nom de la ville si on souhaite également cibler une ville donc je vais revenir ici on va voir comment on peut par exemple cibler la France donc après zone residential ici je vais rajouter t country TFR et si je relance là vous allez voir que cette fois-ci notre proxy est bien localisé en France avec une ville qui pour l'instant va changer à chaque fois donc si je le relance on n pas ciblé la ville là vous voyez on a une ville différente on va arriver à d'autres villes encore vous voyez on a des villes différentes à chaque fois et si vous voulez cibler une ville vous pouvez le mettre ici donc avec T City T et là on va mettre Paris et je vais le rajouter également ici et si je relance là cette fois-ci on va bien être en France à Paris à chaque fois donc si vous souhaitez cibler une ville n'oubliez pas ici de bien rajouter City si vous enlevez City que je sauvegarde ok vous allez voir qu'on va obtenir une erreur ici donc proxy error parce que j'ai renseigner une ville ici mais dans ma configuration j'ai enlevé la possibilité de le faire dans geolocation targeting donc ça c'est très pratique si vous souhaitez cibler un site avec une version spécifique puisque les sites peuvent varier en fonction de là où vous vous trouvez dans le monde c'est assez courant qu'on ait des versions qui soient différentes également qu'on ait des prix différents également en fonction de l'endroit depuis lequel vous accédez à un site donc ça peut être très pratique ici de pouvoir fournir ici le pays qu'on souhaite utiliser pour notre proxy dans cette partie on va voir comment utiliser le web Unlocker de Bright data donc le web Unlocker il vous permet de débloquer les sites web avec une gestion automatique aussi des proxy donc exactement comme le réseau de proxy résidentiel il va faire tout ça automatiquement et il va également vous permettre d'avoir le rendu du javasript le web enlocker il va s'utiliser avec le module request avec Python et ça va être exactement la même chose que pour le réseau de proxy donc sur votre tableau de bord vous pouvez ajouter un nouveau web Unlocker et lui donner un nom moi j'en ai déjà créé un donc je vais aller directement sur la page de ce web Unlocker et vous allez voir que c'est vraiment exactement la même chose que pour le réseau de proxy on a le host le USERNAME le password ensuite on a les adresses IP qui sont autorisées les adresses qui sont bloquées et on va pouvoir aller également dans la configuration si on le souhaite choisir un pays éventuellement un état ou une ville également donc pour l'instant j'ai juste le pays qui est ici mais je peux rajouter le City et on pourra comme pour le réseau de proxy ajouter dans l'adresse qu'on va donner à notre module request la zone qu'on souhaite cibler et on a également les statistiques ici qui nous indiquent la bande passante qu'on a utilisé donc si je reviens dans Access parameters n'oubliez pas d'activer votre proxy et on va pouvoir cliquer ici pour vérifier les exemples de code et vous voyez ici qu'on a exactement le même code avec la vérification sur python 2 ou Python 3 donc la seule chose que vous avez besoin de récupérer là encore c'est ce di dictionnaire qui va contenir la clé HTTP et HTTPS et si je reviens dans mon script de scrapping je peux donc remplacer ce dictionnaire que j'utilisais pour le réseau de proxy par celui-ci donc vous voyez que c'est quasiment la même chose on a ici les informations avec le host le USERNAME le password et je vais ensuite passer cette information là je l'ai mis dans une variable donc je l'avais appelé Patrick juste pour vous montrer que on pouvait l'appeler n'importe comment et que ensuite c'est bien au paramètres proxy qu'il faut passer cette variable vous n'êtes même pas obligé de faire une variable si vous le souhaitez vous pouvez mettre mettre ces informations directement ici en tant que dictionnaire et si vous relancez le script en l'état vous allez voir que dans ce cas-ci on a une erreur donc c'est normal c'est parce qu'il faut en fait enlever la vérification des certificats SSL pour l'utilisation du unblocker et ça peut se faire très facilement en rajoutant ici l'argument verify que l'on va mettre à false donc si je relance vous allez voir que cette fois-ci on va bien récupérer les informations donc là on est dans ce cas-ci aux États-Unis à hashburn avec une autre adresse IP on a également un avertissement ici qui nous dit que on a une requête qui n'est pas vérifiée alors ce n'est pas un problème en fait c'est juste la requête vers le proxy que l'on va faire sans vérification mais le proxy lui après il va pouvoir faire des requêtes de façon sécurisée vous voyez ici qu'on a deux clés HTTP et HTTPS et c'est juste la requête vers le proxy qui va être faite en http mais ensuite le proxy lui va pouvoir faire des requêtes sécurisées en HTTPS et si jamais vous voulez enlever cet avertissement c'est possible de le faire avec la bibliothèque URL lib donc on va l'importer on va faire import URL lib 3 et on va faire URL lib 3.disable warnings et on va faire URL 3.exception.insecure request warning donc ça ça va désactiver cet avertissement si jamais vous ne voulez pas l'avoir à chaque fois dans votre terminal donc là je peux relancer le script et vous allez voir que cette fois-ci on aura juste la ligne voilà qui nous dit qu'on est dans ce cas-ci encore une fois à hashburn aux États-Unis et vous voyez qu'il y a des petites différences avec le réseau de proxy là quand on relance le script on voit qu'on est toujours dans la même location avec le même adresse IP donc le web Unlocker il va faire beaucoup de choses en plus du réseau de proxy donc donc il va vérifier si vous êtes bloqué ou non si vous êtes bloqué avec un capcha il va essayer de le débloquer si jamais même après ça parce que ça arrive des fois quand il arrive à débloquer le capcha que le site bloque quand même l'adresse IP parce qu'il considère que le comportement ressemble à un bot et bien dans ce cas-ci il va changer l'adresse IP à ce moment-là pour pouvoir débloquer et passer sur un autre proxy donc il va faire tout ça automatiquement en arrière-plan et c'est une très bonne solution du coup pour éviter toutes sortes de blocage mais vous voyez que dans l'utilisation on a quasiment la même chose qu'avec le réseau de proxy on passe tout simplement les proxy à notre module request avec le verify qui est égal à false donc là on passe encore par le module request et on va voir dans la prochaine partie avec le scrapping browser comment cette fois-ci on peut vraiment utiliser un navigateur headless avec playri en utilisant le scrapping browser de Bright data dans cette partie on va voir comment utiliser le scrapping browser de Bright data qui est une nouveauté de leur offre le scrapping browser l'avantage c'est qu'il peut être utilisé avec des librairies comme playwright qu'on va voir dans d'autres parties avec une utilisation sur le site Airbnb dans ce cas-ci je vais juste vous montrer les bases de comment l'utiliser vous allez voir que c'est assez simple à mettre en place avec là encore tous les exemples de codes qui nous sont fournis par bright data donc de nouveau sur votre tableau de bord vous pouvez ajouter un scrapping browser en cliquant sur Add et ajouter le scrapping browser vous pouvez lui donner un nom moi comme j'en ai déjà créé un je vais me rendre sur la page de mon scrapping browser ici et on va avoir ensuite les informations de nouveau avec le host le USERNAME et le password et les adresses IP qui sont autorisées ou qui sont bloqué dans la configuration on n pas grand-chose on a ici juste quelques options avancées qui nous permettent de spécifier si on souhaite mettre des headers et des cookies spécifiques donc par exemple vous pouvez chercher ici si on veut voir avec Amazon est-ce qu'il est possible de rajouter des entêtes c'est le cas donc vous voyez ici on est prêtapouver pour modifier toutes ces entêtes et tous ces cookies sur la requête qui serait effectuée vers Amazon donc si par exemple on souhaite changer le user agent vous voyez qu'on peut le faire ici on a cette possibilité avec notre requête de modifier ces des informations personnellement je n'ai jamais eu besoin de changer quoi que ce soit tous les blocages sont débloqués automatiquement par le scrapping browser qui s'assure de faire le travail à ma place donc ça me va parfaitement donc n'oubliez pas d'activer votre proxy et vous pouvez ensuite aller voir les codes d'intégration alors là vous allez voir qu'on a pas mal plus de choix on a les choix avec différentes librairies notamment avec note GS Python et c#arp nous ce qui va nous intéresser donc c'est le python et à l'intérieur de Python on peut choisir différentes librairies ppettir playwright ou séenium donc nous on va utiliser séenium et là vous vous avez un exemple de code alors il y a pas mal de choses qu'on va enlever ici je vais copier le code et je vais vous montrer ce que ça donne dans PCH donc je vais coller le code ici alors n'oubliez pas d'installer playri on va l'installer avec PIP dans notre environnement virtuel donc PIP install playri ensuite vous devez faire playri install pour installer les navigateurs dont il va avoir besoin donc il va installer Chrome et Firefox si mes souvenirs sont bons moi dans ce cas si ils sont déjà installés donc il ne va pas refaire l'installation mais vous vous devriez avoir ici un indicateur du téléchargement et de l'installation de ces navigateurs donc donc je vais revenir dans mon script vous voyez ici que le script de base qui vous est fourni sur bright data il utilise l'API async de playwright nous on va utiliser la librairie synchrone donc ici à la place de async on va mettre Sync API et dans l'import on va importer Sync playri et là on va presque enlever tout ça ici là vous voyez à chaque fois on a des Sync a wait donc notre code va être beaucoup plus simple avec l'API Sync et dans notre cas on va se focaliser uniquement sur la PII synchrone de playwright la seule différence donc comme vous voyez ici c'est qu'il faut utiliser les HN et les wait à chaque fois si vous voulez faire des requêtes asynchron pour en faire plusieurs en même temps et avoir la pay asynchrone qui va automatiquement attendre avant de continuer les prochaines action donc dans ce cas-ci moi ce que je vais faire c'est juste copier cette ligne on va également simplifier le code en enlevant la fonction donc je vais juste garder la variable browser ici et je vais enlever tout le reste ici on va voir comment naviguer par la suite là je vais enlever ma fonction main on va aussi enlever cette structure conditionnelle donc vous voyez il y a pas mal de choses qui sont enlever et on va juste garder ce wid qu'on va mettre au début donc en fait ici on va faire un context manager qui va nous permettre d'utiliser playri donc là ce n'est pas a Sync playri mais juste Sync playri donc ça c'est ce qu'on a importé tout en haut de notre script je vais enlever l'impimport de ync Io également donc vous voyez ça fait déjà pas mal de ménag et là à la place de PW du coup je vais prendre la variable que j'ai créé ici playri donc si je reviens qu'est-ce qu'on a ici on a tout simplement notre import de la librairie Sync de playwright on a cette variable globale ici qui est tout simplement les informations pour se connecter au scrapping browser avec le host le USERNAME et le password et ensuite ici notre context manager donc on va créer une instance de playwright à partir de l'API Sync playwright et on va faire playwright.chromium.connect over CDP donc là vous pouvez choisir le navigateur que vous souhaitez utiliser on peut également utiliser Firefox moi je vais garder chromium ici et on va se connecter à notre scrapping browser avec cette adresse qui est donc dans la variable globale ensuite je peux créer une nouvelle page donc je vais faire browser.nepage et avec cette page on va pouvoir naviguer quelque part avec goto donc là dans ce cas-ci je veux dire tout simplement qu'on va aller sur la page de Google et je vais après cette ligne faire un page point pause pour que le script se mette en pause et qu'on puisse voir ce qu'il se passe donc je vais lancer mon script et vous voyez que là rien ne se passe donc on n pas de navigateur qui s'ouvre ici donc c'est normal avec playri on avait vu si je fais ici juste un launch que on peut spécifier headless égale à false et si je lance dans ce cas-ci on va bien avoir un navigateur qui s'ouvre donc ce n'est pas le cas dans ce cas-ci avec le scrapping browser quand on se connecte avec Connect over CDP par contre ce qu'on peut faire donc je vais mettre juste un point de débug ici pour arrêter le script et je relance mon script en debug on va voir que on peut accéder à ce navigateur si je reviens sur la page du scrapping browser on va avoir un debugger ici donc chrome dev tool debugger si je clique là vous voyez qu'on a une connexion qui apparaît donc ça c'est juste parce que j'ai lancé mon script si j'arrête le script ici cette connexion ne va plus apparaître donc là je relance je quitte je reviens sur Chrome dev tool et là vous voyez qu'on a aucune session qui est active donc c'est bien parce qu'on a une session ici sur pcharm qui est lancée qu'on va pouvoir y accéder directement depuis bright data donc je reviens ici je reclique sur Chrome dev tool là on a bien notre session et et quand on clique dessus on va avoir un nouvel onglet qui s'ouvre avec notre navigateur exactement comme si on l'avait ouvert avec playri sans passer par cette connexion donc là on va retrouver la page de Google on a notre site qui s'ouvre dans un nouvel onglet et on voit notre site et tout ce qui va se passer donc là si je faisait d'autres actions ici par la suite et que je continue avec mon debugger on verrait ces actions qui seraient répété ici sur notre page dans le debugger de Bright data donc on verra dans d'autres parties de cette formation comment mettre tout ça en pratique sur le site de Airbnb mais vous voyez que que la base du code est assez simple on va juste rajouter ici cette connexion over CDP qui est donc un petit peu différente de ce qu'on avait fait quand on utilisait playwright avec juste le launch et on va passer par cette fenêtre pour voir ce qu'il se passe en passant par le debugger de Bright data on va voir également des techniques pour l'ouvrir automatiquement pour ne pas avoir à chaque fois à passer par le chrome dev tool sur le tableau de bord donc ne vous inquiétez pas il y a des façons de faire plus facil avec du code qui nous permett directement dans notre script de décider de l'ouvrir ou non et ça va s'ouvrir automatiquement pour nous dans un nouvel ouelle page chrome pour qu'on puisse voir ce qu'il se passe donc voilà pour l'utilisation basique du scrapping browser là encore n'oubliez pas vous pouvez ajouter des adresses IP ou les bloquer si jamais vous avez des problèmes c'est peut-être parce que votre IP est bloqué si c'est le cas bright data va vous le dire il va vous envoyer un email donc il fait ça par mesure préventif sur tous ces outils si jamais il voit qu'il y a quelque chose de suspicieux mais s'il n'y a aucune raison donc de bloquer votre IP vous pouvez venir ici et juste supprimer l'IP qu'il aura rajouté ici qui sera votre adresse IP donc par défaut il y en a aucun dans allow et blocked donc ça veut dire que tout le monde peut y accéder mais si jamais vous voulez le restreindre ou vous y assurer que vous n'êtes pas restreint vous pouvez aller voir ça ici donc vous voyez ces trois outils très faciles à utiliser il suffit de les ajouter scrapping browser web Unlocker residential proxy à chaque fois vous avez les exemples de codes qui sont disponibles sur les interface de ces outils donc c'est très facile à utiliser et dans les prochaines parties donc avec les projets Airbnb et eCom notifier on va voir de multiples exemples dans lesquels on va utiliser tous ces outils pour faire un scrapping éthique j'en profite pour faire une petite parenthèse de 10 secondes si tu souhaites te former à Python une seule adresse dogstring.fr tu peux te créer un compte c'est gratuit et tu auras beaucoup de contenu des exercices des quiz des glossaires des formations des projets des parcours cré-toi un compte tu vas pouvoir découvrir tout ça et n'hésite pas également à nous rejoindre sur le serveur discord de doc string on a des challenges toutes les semaines des vocaux des salons d'aide donc rejoins-nous tous les liens sont dans la description pour ce premier projet et ce premier cas d'usage situation réelle on va utiliser un site web connu de tous Airbnb c'est un script que j'utilise moi-même pour planifier mes vacances puisqu'il permet de récupérer dans une ville donnée le mois de l'année qui a les prix les plus bas on peut ainsi savoir s'il est préférable de partir par exemple en janvier en mars ou en août pour ça on va mettre en place un scrapping éthique grâce au scrapping browser de Bright data on va voir comment naviguer à travers le site exactement comme un humain le ferait en naviguant sur chaque page et en entrant les informations qui nous intéressent et on verra comment récupérer une fois sur les pages qui nous intéressent les informations à partir du HTML pour faire la moyenne des prix pour tous les mois de l'année et ainsi savoir quel est le mois le plus intéressant pour nous donc j'espère que vous êtes prêts pour ce cas d'utilisation réelle on va voir tout ça ensemble et en détail et on commence tout de suite avec la première partie j'en profite également pour te rappeler de mettre un pouce bleu si ce n'est pas encore fait ça aide énormément la vidéo également partage-la partout où tu peux également n'hésite pas à me dire en commentaire quel autre site tu aimerais voir dans une vidéo future quel site tu as essayé peut-être de scrapper et sur lequel tu as eu des problèmes ça m'intéresse de savoir comme ça je pourrais faire des vidéos sur le sujet la première chose à vérifier avant de récupérer les données d'un site web c'est de vérifier s'il n'existe pas déjà une API publique qui nous permet de récupérer ses données l'utilisation d'une API est plus simple et elle nous permet de faire les choses de façon cadrée en allant récupérer les données de la bonne façon selon les spécifications du site donc comment vérifier l'existence d'une API et bien vous pouvez tout simplement taper le nom du site web suivi par API et vérifier ce qu'il y a de disponible et vous allez voir que dans le cas de Airbnb il y a bien une API qui est disponible mais elle n'est pas publique et c'est une API qui permet de gérer en fait les annonces que vous avez et non pas de récupérer des informations général sur le site donc si je prends le premier lien par exemple vous voyez ici qu'on a bien une API mais qu'il faut demander donc une autorisation pour pouvoir y accéder donc vous devez être autorisé par Airbnb à utiliser leur API et vous voyez que on ne trouve pas non plus de documentation la recherche d'une documentation ça peut être un autre moyen également de vérifier si une API est disponible publiquement je vais prendre un autre exemple stripe il dispose d'une API et vous allez voir en tapant stripe API documentation qu'on arrive très facilement à trouver cette API et toute la documentation qui va avec donc dans notre cas on a vérifié l'existence d'une API publique qui fournit les données que je recherche on avait donc bien une API mais elle n'était pas publique et elle ne me permettait pas même en utilisant cet API de récupérer les données de prix que je recherche puisque cet API sert uniquement à gérer les annonces 2ème point qu'on va s'assurer de respecter c'est de récupérer des données à un rythme raisonnable donc dans notre cas on ne va pas faire de script asynchrone on va utiliser l'API synchrone de playwright et on ne va pas faire plus qu'une requête à la fois et quand on va utiliser également le scrapping browser de Bright data il y a des mécanismes qui sont faits par bright data pour s'assurer que vous ne faites pas un scrapping trop agressif pour que les performances du site web ne soit pas détérioré si vous voulez en savoir plus sur ce sujet je vous renvoie vers l'entrevue que j'ai réalisé avec Rony Chalit dans lequel il explique justement à quel point bright data va justement constamment monitorer les sites Web sur lesquels il y a du scrapping pour s'assurer que les performances ne sont pas détériorés on va également respecter le contenu récupéré et le droit d'auteur on ne va pas le présenter comme le nôtre dans ce cas-ci je vais juste récupérer des informations de prix je ne vais pas les republier quelque part je ne vais rien faire d'autre que les utiliser pour mon information personnelle pour ensuite prendre une décision et décider le mois de l'année dans lequel je préfère partir en vacances parce que les prix seront plus bas donc il n'y a aucune réutilisation du contenu récupérer ici et donc pas de risque de présenter ce contenu comme le mien de la même façon on ne va pas utiliser ce scrapping pour porter atteinte ou dupliquer des données existantes là encore le contenu qu'on récupère ne sera pas publié ou dupliqué ou présenté ailleurs c'est vraiment de l'information qu'on va récupérer uniquement pour notre besoin personnel donc on ne va ainsi absolument pas porter atteinte à ces deux derniers points la dernière chose que j'aime bien faire c'est de vérifier le fichier robots.txt qui est disponible donc à l'adresse airbni.fr/robots.txt et vous allez voir que dans ce fichier en plus de toutes les règles d'utilisation selon les bots on a un petit message d'accueil qui nous invite à aller postuler si on est un humain et qui nous dit que si on est un bot qui aime faire du crawing donc aller récupérer des informations sur les pages comme on le ferait avec du scrapping il suffit donc juste de s'assurer des house rules donc les règles de la maison et de ne pas aller sur des dossiers ici qui sont marqués comme diesar donc voilà vous voyez que ils sont conscients qu'on peut bien faire du scrapping see you on the next roll ils sont assez sympas ils sont conscients de ça et vous allez voir que on on va pouvoir donc réaliser un scrapping sur ce site je vais descendre ici là on a les règles pour les différents bots on a par exemple Yandex on va voir Bing Google et cetera on va descendre tout en bas dans la catégorie qui concerne tous les autres user agent et ici on voit qu'on a tous ces dossiers qui sont en diesel out et si je vais voir dans la recherche si je fais une recherche puisque c'est cette page ici qu'on va scrapper je vois que là je suis dans le dossier/s et ensuite plein d'information sur la recherche que j'ai effectué donc ce dossier/s si je retourne sur le robots.txt on voit qu'il n'est pas contenu dans cette liste de dossiers dielow donc voilà pour tous les éléments que je voulais vérifier avant de commencer le scrapping pour s'assurer de respecter un scrapping éthique avant d'écrire la moindre ligne de code il est important de vérifier à quoi ressemble le site qu'on va scrapper tout ça pour savoir simplement à quel point le scrapping va être facile ou non en effet il y a des sites qui sont très bien organisés avec des idées très spécifiques pour chaque élément de la page ou des classes qui vont se répéter é en fonction d'éléments similaires et d'autres qui sont un peu plus difficiles à scrapper car par exemple on va avoir des classes totalement aléatoires sur chaque élément et donc il va falloir utiliser d'un peu plus de ruse donc je me rends sur le site de Airbnb avec le mois d'avril pour Rio de janéo et je vais faire un clic droit pour inspecter la page en faisant donc inspect ici ça devrait être la même chose pour la plupart des navigateurs ce qu'il nous faut en fait c'est ces outils de développement qui vont nous permettre d'analyser le code HTML de la page donc donc là si je défile un petit peu dans les annonces on va voir déjà qu'on a différentes informations de prix on en a certaines qui sont uniques comme ici et d'autres avec un prix qui est barré et un prix réduit pour analyser le html de ces parties qui nous intéressent on va cliquer sur cette petite icône qui nous permet de sélectionner des éléments dans la page et d'afficher le HTML correspondant ici pour ne pas avoir à chercher à l'intérieur de tout ce HTML à la main puisque vous voyez qu'il y a énormément de choses ici donc je vais cliquer sur cet élément ici et vous voyez que que ça va m'afficher un sélecteur qui me permet de sélectionner différents éléments dans la page donc là on voit que je peux par exemple sélectionner une carte au complet et pour sélectionner certains éléments il va falloir ruser un petit peu donc moi je le sais puisque j'ai longuement préparé cette formation donc par exemple pour le prix ici vous voyez qu'il faut aller vraiment tout en bas à gauche du prix et là on va pouvoir sélectionner cet élément si jamais vous n'arrivez pas à cibler un élément précis par exemple vous voyez qu'ici je n'arrive pas à cibler les étoiles donc le 4,86 donc ce qu'on peut faire c'est aller un niveau au-dessus donc cliquez par exemple ici ça va nous amener sur le lien de la carte et si on revient un petit peu en haut on a le div qui contient toutes les informations donc le lien pour cliquer sur la carte et un autre div en dessous qui va contenir d'autres informations donc là on a un div avec l'image et on a un autre div avec toutes les informations qui vont nous intéresser et on peut donc naviguer comme ça à l'intérieur de la structure à la main pour vérifier les éléments et arriver comme ça petit à petit à l'élément qui nous intéresse donc par exemple on retrouve ici l'élément de la note et si on vient ici on a l'élément du prix donc donc si je vais voir dans le Prix moi ce qui m'intéresse c'est de savoir à quel point il y a des choses qui vont se répéter sur la page donc je vais reprendre mon outil de sélecteur ici pour aller précisément sur cet élément donc on voit que c'est un span qui a une classe avec tyx JP1 ici donc c'est une classe qui ne veut pas dire grand-chose des fois on a des classes qui sont beaucoup plus explicites on pourra avoir par exemple une classe qui s'appelle price quelque chose là vous voyez que toutes les classes ici ont des noms un peu lfoc donc c'est des classes qui sont générées automatiquement et nous ce qui va nous intéresser c'est de savoir si cette classe se répète est-ce que à chaque fois pour les informations de prix on a une classe différente complètement aléatoire au quel cas ça va complexifier grandement notre scrapping où on a quelque chose qui se répète donc là je vais prendre cette classe je vais copier et je vais faire contrôle F pour pouvoir chercher cette même classe à l'intérieur de tout le fichier et là malheureusement on voit qu'on a une seule occurrence de cette classe dans tout le fichier alors je sais parce que j'ai déjà préparé cette formation que là en fait ce n'est pas un une classe unique en fait c'est juste que sur toute cette page c'est cette seule carte qui a un prix qui n'est pas barré si on va voir sur les autres cartes ici on voit qu'on a un prix barré et un prix normal et c'est le même cas pour toutes les autres cartes à part celle-ci donc là on a une seule occurrence non pas parce que cette classe est unique mais parce que la carte avec le prix qui n'est pas barré est unique sur la page si on va voir par contre ici avec le prix barré et le prix qui est le le vrai prix en fait de l'appartement si je vais voir ici là on va voir que cette fois-ci on a deux nom de classe donc on a le nom de classe pour le prix barré et on a le nom de classe pour le prix actuel et il est différent de celui qu'on avait si je copie ce nom ici et que je vais vérifier là cette fois-ci on voit qu'on a 1/ 23 donc une occurrence sur 23 et si on défile comme ça on va voir qu'à chaque fois on va pouvoir récupérer le prix barré donc là en fait on descend comme ça sur la page et à chaque fois on va récupérer le prix barré donc le prochain Prix pas le prix barré en fait mais le vrai prix actuel qui est à côté du prix barré donc nous c'est le prix qui va nous intéresser puisque le prix barré c'est le le prix sans la réduction nous on veut avoir le vrai prix qu'on payerait si on irait louer cet appartement donc là vous voyez que on a de 4 figure en fait sur la page mais avec une classe qui se répète donc on a le premier cas de figure ici avec un prix sans réduction qui va être une classe spécifique et le cas des locations qui ont un prix réduit avec cette classe qui cette fois-ci se répète donc ça me rassure ça veut dire que en fait on a bien un même nom de classe qui n'est pas très explicite mais qui va se répéter sur la page et qu'on va pouvoir utiliser pour récupérer le prix de la page donc il faudra juste gérer le cas de figure où on a un prix qui n'est pas réduit et donc vérifier à chaque fois pour chaque carte est-ce qu'on a un prix réduit ou non et en fonction de cette information récupérer soit le prix directement soit le prix réduit de la location donc vous voyez que malgré un code html ici qui est très chaotique avec énormément de choses dans tous les sens on a quand même identifié avec cette analyse que on a des éléments qui nous permettent de récupérer les informations qui nous intéressent facilement et si on va voir à d'autres endroits on voit qu'on a quand même malgré toutes ces classes là encore qui sont un petit peu du charabia des éléments ici comme les test ID qui sont beaucoup plus explicites donc le cart container ici par exemple qui nous nous permettrait de récupérer le le containeer total de la carte donc de la location qui comprendrait le titre de la location les informations ici comme sesjourné chez Bryan suite à Rio et cetera et le prix donc on a quand même beaucoup d'éléments sur la page qui vont nous permettre de faire un scrapping efficace sans trop se complexifier la vie et ça c'est de bonne augure pour la suite dans cette formation on va utiliser pycharm et je vais donc l'utiliser pour créer mon projet python donc je vais le mettre dans mes documents je vais l'appeler Airbnb scrapper tout simplement et on va utiliser pycharm pour nous créer un nouvel environnement virtuel vous pouvez bien sûr faire toutes ces opérations directement depuis un terminal sans souci donc je vais utiliser un nouvel environnement virtuel avec Virtual que je vais placer à l'endroit par défaut à l'intérieur d'un dossier van et je vais également laisser cocher cette case pour créer un fichier main.py par défaut qui contiendra un code de base donc je clique sur Create pour lancer la création du projet et voilà qu'il est correctement créé on voit voit que j'ai bien ici mon fichier main.py avec tout simplement la structure conditionnelle ici qui me permet d'afficher une information à l'écran on a aussi une configuration qui est créée automatiquement qui va nous permettre d'exécuter ce script si jamais vous créez votre script à la main vous pouvez tout simplement faire un clic droit ici et cliquez sur run main pour créer automatiquement une configuration qui va vous permettre de lancer votre script donc si je lance le script ici on voit qu'on a notre highpy charm qui est affiché dans la fenêtre en bas de l'écran donc moi je vais enlever cette fonction ici je vais enlever également tous les commentaires on va enlever également le dernier commentaire ici et tout ce qu'on va faire c'est garder cette structure conditionnelle et pour l'instant on va mettre un pass à l'intérieur on voit qu'on a donc bien notre dossier ici airbn bcrapp qui correspond au dossier du projet et on va pouvoir maintenant installer les bibliothèques dont on va avoir besoin pour effectuer le scrapping donc pour ça je vais ouvrir un terminal on a un petit raccourci ici sinon vous pouvez aller dans View et aller dans tool Windows et vous allez retrouver le terminal quelque part ici qui doit être tout en bas ici terminal et ça va nous permettre d'ouvrir un terminal directement à l'intérieur de notre projet avec l'environnement virtuel déjà activé donc ce qu'on va faire ici c'est utiliser PIP pour installer les bibliothèques donc on va faire PIP install et on va installer beautiful soup 4 donc tout en minuscule comme ça avec le 4 à la fin je valide avec entrée on va installer également la bibliothèque request donc je refais un PIP install et je mets request ici c'est la bibliothèque qui va nous permettre de faire des requêtes vers le site de Airbnb et pour finir on va installer la bibliothèque playwright qui est une bibliothèque qui nous permet d'automatiser des tests unitaires mais également de faire du scrapping d'une façon très très intelligente qui va nous simplifier grandement la tâche et qui va nous permettre de le faire via un navigateur qui va être ce qu'on appelle headless c'est-à-dire que le navigateur va pouvoir faire du scrapping sans être ouvert et on va pouvoir ainsi lancer ce script sur un serveur qui n'aurait par exemple pas d'interface graphique donc je lance l'installation avec pif install playwri et une fois qu'on a installé playri il faut lancer une dernière commande qui est bien important qui est playri install qui va installer tous les éléments qui vont nous permettre d'utiliser ces fameux navigateurs headless donc c'est des navigateurs qui vont être des versions similaires à ce qu'on connaît donc comme Chrome Firefox et cetera et on va voir qu'on peut également choisir quand on utilise playri quel navigateur on souhaite utiliser et pour ça il faut donc installer ses navigateurs donc ça va tout simplement être dés exécutables alors je lance l'installation vous voyez que là il va télécharger chromium qui est le moteur de navigateur derrière la plupart des navigateurs que vous utilisez comme chrome ou encore des plus récents comme et vous voyez qu'il va installer également d'autres choses donc on a par exemple Firefox ici on a ffmp qui va être utilisé si on souhaite faire des enregistrement de notre scrapping et voir de façon plus visuelle ce qu'il se passe lorsqu'on fait du scrapping ou encore prendre des captures d'écran des pages sur lesquels on navigue donc une fois qu'on a fait tout ça on a tout ce qu'il nous faut on a request beautiful soup playri et c'est pour l'instant les trois bibliothèques dont on va avoir besoin pour commencer notre scrapping avant d'utiliser des outils comme playwright qui sont un peu plus avancés et qui vont nous permettre d'effectuer un scrapping exactement de la même façon qu'on le ferait manuellement c'est-à-dire en se déplaçant d'une page à l'autre en rentrant des informations dans la barre de recherche et cetera on va déjà commencer par un scrapping très simple avec la bibliothèque request qui va nous permettre d'effectuer une simple requête HTTP vers l'URL qu'on souhaite scrapper pour vérifier si on peut récupérer des informations de cette façon donc ce n'est pas forcément la face façon la plus avancée de faire mais c'est déjà bien de vérifier si on peut le faire puisque pour de nombreux sites ça peut être une façon très efficace et simple de faire un scrapping avec seulement quelques lignes de code donc ce que je vais faire c'est commencer par importer cette bibliothèque qui est request et il ne faut bien sûr pas oublier le S ici c'est une erreur que je vois très souvent donc des gens qui pensent qu'il faut utiliser request comme ceci c'est bien request avec un S sinon vous aurez une erreur et je vais ensuite copier donc l'URL qui nous intéresse qui est une URL assez longue vous allez voir vous la trouverez dans la source des formation vous pouvez utiliser n'importe quel autre URL d'une page qui contient des informations qui vous intéresseraient sur Airbnb nous ce qui va nous intéresser ici c'est les informations sur les locations areo de Jero et donc on va mettre cet URL ici dans notre script qui est tout simplement une longue chaîne de caractère on va ensuite faire une requête avec donc request et une requête qui va être de type get donc je vais faire tout simplement request.get vers cet URL et on va récupérer le résultat dans une variable qu'on va appeler response qu'est-ce qu'on va faire ensuite et bien tout simplement faire un print de response.text pour vérifier ce que ça nous retourne donc pour l'instant je reste très simple on verra par la suite comment on peut grandement améliorer notre script pour s'assurer que tout fonctionne correctement et dans le cas d'un script simple comme celui-ci qu'on peut quand même ajouter une gestion d'erreur du logging pour savoir ce qui se passe et cetera pour l'instant je vais juste vérifier si j'ai bien quelque chose qui m'est retourné ici si on a une erreur ou quoi que ce soit donc là je vais mettre tout ça à l'intérieur d'une fonction donc je vais créer une fonction main tout simplement je vais indenter tout ça à l'intérieur de cette fonction et là on va appeler cette fonction main ici à l'intérieur de cette structure conditionnelle si jamais vous vous demandez à quoi sert cette variable name et cette structure conditionnelle on a un glossaire complet sur le sujet sur docstring que je vous invite à aller consulter et qui explique précisément à quoi sert cette structure conditionnelle de retour dans mon script je vais donc lancer le script en cliquant ici en haut à droite pour vérifier ce que ça me retourne et on voit ici qu'on a beaucoup beaucoup d'éléments donc on a bien du code HTML et ce que je vais faire c'est là encore tout simplement une recherche donc avec cont F ou commande F sur Mac et je vais coller le nom de la classe qu'on avait tout à l'heure donc on voit notre classe ici on voit qu'elle apparaît 17 fois donc ça veut bien dire que on a cette répétition qu'on avait quand on a analysé notre page et on retrouve bien le prix ici donc ça indique bien que tout fonctionne que l'on peut récupérer avec une simple requête vers notre URL les informations on voit également qu'on n'est pas bloqué par le Javascript puisque sur les sites moderne de style Airbnb généralement on a des API JavaScript qui vont aller chercher du front au bac les informations et il n'est pas rare que quand on fasse une requête toute simple comme celle-ci avec request qui ne peut pas utiliser de JavaScript et bien on est tout simplement aucune information qui soit retournée avec notre requête simple comme ceci donc là c'est déjà assez cool de voir qu'on peut récupérer directement les information qui nous intéresse comme ceci et qu'on a pas forcément besoin de passer par un outil comme playwright même si encore une fois playwright va nous permettre de faire un script beaucoup plus avancé et beaucoup plus crédible pour un site comme Airbnb pour éviter d'être bloqué puisque là si si vous faites une requête simple comme celle-ci on va très rapidement être identifié comme un bot de scrapping donc il y a plein de façons d'éviter ça mais c'est sûr que ça va être plus difficile avec request que avec un outil comme playwright qui va nous permettre d'émuler beaucoup plus facilement le comportement d'un humain sur le site donc avant de terminer cette partie ce que je vais faire c'est tout simplement renommer cette fonction on va l'appeler fetch content on va lui mettre un paramètre qui va être une chaîne de caractère donc là je mets tout simplement une indication de type on va en effet essayer dans ce projet d'avoir un script le plus propre possible cible donc je mets également ici une annotation de type pour indiquer qu'on va retourner en retour une chaîne de caractère et pour l'instant donc je vais enlever cette url ici et je vais la passer dans l'appel de la fonction donc je vais mettre URL égal à URL et on va remettre l'URL ici au début et ce que je vais faire ici au lieu d'un print c'est tout simplement retourner response.text là encore on verra par la suite comment on peut avoir un script un peu plus robuste en cas d'erreur avec cette requête mais voilà pour l'instant on a déjà quelque chose qui est un peu plus clair et qui est mieux organisé pour la suite de notre script je vais terminer en mettant une doc string ici en indiquant fetch content of the page with given URL on va pas faire plus que ça pour l'instant juste une doc string on a ensuite les annotations de type ici qui nous indique clairement ce qu'on attend en input et ce qui va être retourné en output avec ici une chaîne de caractère à partir de la requête effectuée vers l'URL quand on fait du scrapping on l'a vu il faut éviter au maximum de faire des requêtes inutiles des requêtes qui qui également prennent du temps à faire à chaque fois nous on veut développer rapidement mais sans non plus surcharger le site sur lequel on va faire du scrapping pour ça ce qu'on va mettre en place dans cette partie c'est l'écriture du contenu de notre fichier html sur le disque pour pouvoir lors de nos tests et notamment tous les tests qu'on va faire pour récupérer le contenu de la page lire directement le fichier HTML depuis le disque pour que ce soit donc plus rapide à exécuter à chaque fois et pour éviter de faire des requêtes inutiles vers le site de Airbnb donc dans cette partie on va rajouter deux fonctions une fonction pour écrire le fichier html sur le disque et une fonction pour lire le contenu depuis le disque et on utilisera ensuite ces deux fonctions pour au choix écrire ou lire le fichier depuis le disque ce que je vais faire également c'est rajouter dans cette partie un loger pour qu'on puisse avoir un meilleur aperçu de ce qu'il se passe à l'intérieur de notre script quand on l'exécute la première chose que je vais faire c'est faire une variable qui va contenir le chemin vers le fichier HTML dans lequel on va écrire ou lire les informations pour ça je vais utiliser la bibliothèque pathlib pour pouvoir faire un chemin relatif vers le dossier dans lequel se trouve mon script donc je vais faire une variable constante que je vais appeler file Pat qui va être égal au chemin complet du fichier que je mets dans une classe Pat ici donc ça ça va me créer un objet de type Pat qui va contenir le chemin complet vers le script main.py et moi ce qui m'intéresse ici ce n'est pas le chemin vers le main.py mais le chemin vers le dossier parent donc pour ça je mets tout simplement point parent ça va me retourner le dossier parent du fichier qu'on va lancer et ensuite je vais faire un slash pour concaténer tout ça avec le nom du fichier que je vais appeler tout simplement airbnb.html on va ensuite utiliser le module logging pour utiliser un logger donc je fais un importe de logging ici et je vais faire un loger que je vais mettre dans une variable logger donc ça va être égal à logging.getlogger et pour le nom on va passer le nom du script donc c'est quelque chose que vous allez retrouver dans nombre de script ici d'utiliser directement cette variable name qui va être égale dans ce cas-ci au nom du fichier donc dans ce cas-ci main.p y et ça va donner donc un nom automatiquement à notre logueer et pour finir on va faire une configuration de base donc on ne va rien écrire dans un fichier ou quoi que ce soit nous on veut juste une configuration de base qui va écrire dans le terminal ce qu'il se passe grâce à notre loggeer donc on va faire une basicque config et on va mettre un niveau qui par défaut va être égal à loging.dbug on pourra par la suite changer si on veut faire par exemple des avertissements donc warning error et cetera pour l'instant on va le mettre sur dbugs et on a ainsi notre logueer qui est configuré de façon très basique mais suffisante pour ce qu'on va avoir besoin de faire pour l'instant donc qu'est-ce que je vais faire ici je vais déjà commencer par faire une fonction write to file cette fonction on va pas l'utiliser directement donc je vais mettre un tirer du bas ici pour que ce soit une fonction privée qui va être utilisée dans d'autres fonctions mais qui n'a pas vocation à être directement utilisé par quelqu'un qui utiliserait notre script donc je vais l'appeler write to file tout simplement et on va lui passer un paramètre content qui va être le contenu qu'on souhaite écrire à l'intérieur du fichier et en retour on va retourner un boulet 1 qui va indiquer si oui ou non le fichier a été correctement créé et si il existe sur le disque je vais mettre une doc string ici on va mettre tout simplement write content to file pas besoin d'en dire plus c'est assez explicite comme cela ce qu'on va faire ici c'est donc indiquer ce qu' se passe avec notre loger donc on va faire un debug tout simplement et on va dire writing content to file comme ça quand on va exécuter notre script on aura cette indication dans le terminal qui nous dit qu'on est bien passé à l'intérieur de cette fonction et qu'on est en train d'écrire à l'intérieur du fichier pour l'écriture on va faire quelque chose de très simple avec tout simplement l'ouverture du fichier donc qui est dans la variable fileepat en mode write donc avec le W on va mettre ça dans une variable F et on va faire f. write et on va écrire le contenu que l'on passe ici à notre fonction et pour finir ce qu'on va faire c'est retourner donc un boulet 1 qui va être filepat.exist donc ça va vérifier en fait tout simplement si notre fichier existe sur le disque donc si c'est le cas ça veut dire qu'il a été correctement créé et si ce n'est pas le cas et bien ça veut dire qu'il y a eu une erreur donc voilà pour cette fonction write to file rien de bien compliqué ici et on va faire tout de suite la fonction read from file qui elle aussi va être assez facile donc read from file qui elle aussi n'aura pas vocation à être utilisé directement donc on va mettre un tirer du bas au début et ça va nous retourner ici une chaîne de caractère qui va être le contenu du fichier donc je mets également une doc string ici read content from file et on va mettre là encore un loger point debug pour dire qu'on va lire le contenu du fichier le fichier quel est-il et bien c'est toujours notre fileepat ici donc là encore je vais utiliser le context manager avec with open fileepat cette fois-ci en mode lecture donc avec read R pour read et je vais mettre ça dans une variable F et je vais retourner tout simplement le contenu de ce fichier qui est bien donc une chaîne de caractère comme on l'a indiqué ici donc vous voyez ici qu'on passe directement par une constante file pass on pourrait rendre le script un peu plus flexible si on le souhaitait en mettant directement ce paramètre dans write to file et dans read from file pour pouvoir changer par exemple le nom et la location de l'endroit où on écrit le fichier nous on va tout mettre à l'intérieur de ce dossier ici donc je préfère passer ici par un chemin relatif à partir du fichier du script et de ne pas laisser le choix sur le nom du fichier on n' pas beaucoup d'intérêt ici à laisser le choix à l'utilisateur ce qu'on veut c'est juste pouvoir écrire sur le disque et lire depuis le disque le nom du fichier on en a pas grandchose à faire donc voilà pour ces deux fonctions write to file et read from file et on va pouvoir donc les utiliser cette fois-ci à l'intérieur de notre fetch content pour au choix aller chercher le contenu directement depuis le site donc le contenu à jour directement depuis rirbnb ou alors le contenu depuis le fichier qu'on aura écrit préalablement sur le disque pour ne pas avoir à faire de requêtes inutiles dans notre fonction fetch content ici on va toujours récupérer le contenu à partir d'Internet donc à partir de l'URL de Airbnb qu'on passe au module request dans cette partie on va donc modifier cette fonction fetch content pour aller chercher au choix le contenu depuis Internet avec request ou depuis le disque avec le fichier HTML qu'on aura écrit au préalable avec avec les fonctions write to file et read from file pour dans ce cas-ci lire depuis le fichier sur le disque la première chose qu'on va faire c'est modifier un petit peu ces deux lignes de code pour les rendre un peu plus robustes en utilisant un try accept afin de récupérer les erreurs potentielles qu' pourrai y avoir avec notre requête et afin de vérifier également si notre requête est correctement effectuée donc je vais faire un bloc try ici dans lequel je vais mettre ces deux informations et un bloc except dans lequel on va mettre une exception que l'on n'a pas encore importé qui va être à partir du module request donc on va faire from request.exceptions import request exception comme ceci et on va mettre cette exception ici dans notre bloc except donc except request exception as e donc on va récupérer cette exception dans une variable qu'on va appeler e et là on va faire tout simplement un logger.error pour indiquer quel est le problème qui va se passer ici donc on va dire tout simplement coulden fetch content from et on va insérer ici l'URL à partir de laquelle on a fait la requête et on va dire que c'est dû à l'erreur et là encore on va insérer avec des accolades l'erreur en question qu'on aura converti en chaîne de caractère pour pouvoir l'insérer à l'intérieur de cette chaîne de caractère et là on va lever l'erreur qui nous a été retourné dans la variable e avec raise donc de cette façon si jamais on a la moindre erreur qui arrive à l'intérieur de ce bloc et bien on va pouvoir le loguer avec notre logueer ici pour informer dans un fichier de log ou directement comme on va le faire ici dans notre terminal qu'il y a eu une erreur avec la requête à l'intérieur du block try on va là encore utiliser notre loger mais cette fois-ci pour dire qu'on va faire une requête donc on va dire making request to et on va insérer ici l'URL vers la requête ensuite on touche pas à cette ligne on va faire la requête avec request.get et ce qu'on va faire ici par contre c'est un raise for status et ça ce que ça va faire si on va voir la définition de cette fonction avec command B ou si vous faites clic droit et que vous allez dans si je me souviens bien go to ici ensuite vous allez dans declaration or usage vous allez voir ici dans cette définition qu'on va en fait lever une une erreur et indiquer quelle est cette erreur si jamais on a un code de statut donc status code ici qui est un code d'erreur donc par exemple entre 400 et 500 ou 500 et 600 donc nous ce qui nous intéresse ici c'est d'avoir un code qui est entre 200 et 299 un code de statut de succès si jamais ce n'est pas le cas et bien on va récupérer cette exception et loger là encore une fois que on a eu un problème lors de la récupération du contenu de cette page qu'est-ce qu'on va faire ensuite une fois qu'on a récupéré la requête une fois qu'elle a correctement été effectuée donc après ce race for status et bien on va l'écrire dans le fichier avec notre fonction write to file et pour le content et bien on va mettre une variable que je vais créer juste avant que je vais appeler HTML content qui va contenir response.text donc je vais la donner au contenu ici HTML content et on va retourner ce HTML content puisque c'est ce qu'on retournait auparavant dans la fonction avec return response.text directement là on retourne notre variable puisqu'on a besoin pour la passer ici on pourrait mettre response.text ici et ici ça marchera également mais là pour ne pas répéter le code je préfère faire une variable intermédiaire et on retourne bien ici donc une chaîne de caractère comme indiqué par notre annotation de type dans la définition de la fonction donc là qu'est-ce qui se passe jusqu'à présent on a tout simplement rajouté la gestion d'erreur et également l'écriture sur le disque du contenu de la page html en cas de succès ce qui va nous permettre ensuite de donner le choix à l'utilisateur de lire le contenu depuis le disque ou depuis la requête qui va être effectuée vers Airbnb donc je vais rajouter ici une condition avec un paramètre dans cette fonction qui va me permettre de récupérer le contenu depuis le disque donc on va dire tout simplement from disk qui va être de type bouléen et qui par défaut va être égal à false et on va dire que si on choisit de récupérer from disk et également on va vérifier que file P existe puisque ce n'est pas tout de vouloir récupérer les informations depuis le disque mais il faut aussi s'assurer que l'information existe déjà donc si on souhaite récupérer depuis le disque donc si ce paramètre est hatu et que le fichier existe et bien dans ce cas-ci on va tout simplement retourner le le contenu depuis le fichier avec notre fonction read from file qu'est-ce qu'elle fait et bien elle fait tout simplement un f. read de notre fichier qui est dans la variable fileepat donc ça c'est si le fichier existe s'il n'existe pas et bien tout simplement on ira faire cette requête ici pour récupérer le contenu depuis le module request donc avec cette requête pointget ici et avec le loger on va bien voir tout ce qui se passe ici puisque c'est bien important là avec le loger d'afficher ce qui se passe si quelqu'un lance le script pour la première fois en mettant fl disque il aura bien comme information le fait qu'on va quand même faire la requête puisqu'on a mis un loger ici si par contre le fichier existe déjà puisque dans le read from file on a bien mis reading content from file on verra bien que on ne fait pas de requête et que au contraire on va directement lire le contenu depuis le fichier si on fait la requête on aura là encore le logger.dbug qui va nous indiquer qu'on fait une requête vers l'URL donc je vais pouvoir tester tout ça pour vérifier que ça fonctionne bien je vais avoir mon seul point d'entrée ici qui va être fetch content donc comme je vous ai dit on ne va pas utiliser read from file ou write to file directement notre seul point d'entrée dans ce cas-ci ça va être le fetch content et on va lui dire avec l'URL et le from disk comment on souhaite récupérer le contenu donc pour l'instant je vais mettre from disk et on va le mettre on va commencer à le mettre à true et je vais mettre ici content et on va faire un print de content à la fin donc là normalement le fichier n'existe pas encore et vous allez voir avec le loger que même si on met from disk égal à chou on va quand même faire la requête dans ce casci donc je vais lancer mon script et on a bien le contenu qui est affiché puisqu'on a fait un print du contenu si on remonte alors là on ne voit pas on a plus l'historique je vais enlever le contenu et je vais relancer et je vais supprimer le fichier puisque là vous voyez qu'il a été correctement créé et sauvegardé sur le disque comme c'était prévu donc je vais supprimer ce fichier OK et je vais relancer le script sans le print pour qu'on voit bien alors je confirme le Do refactor je vais relancer pour qu'on voit bien cette fois-ci le debug donc là vous voyez qu'on a le debug de notre main et on a également le debug de URL lib donc le débug on fait une requête vers Airbnb et ensuite on écrit le Content donc le comp contenu du fichier sur le disque et on va refaire cette fois-ci donc de nouveau je relance le script sauf que cette fois-ci vous voyez qu'on a juste le reading content from file et vous voyez par la même occasion que ça va beaucoup plus vite cette fois-ci si jamais je souhaite quand même faire une requête donc je peux mettre from disk ég false je peux même omettre de mettre ce cet argument puisque par défaut si je vais voir la définition je l'ai mis à false donc par défaut on va aller récupérer le contenu depuis internet donc là si je fais ça même si j'ai le fichier sur disque si je relance le script là on voit qu'on fait bien la requête pour aller récupérer les données à jour depuis le site internet donc voilà pour cette partie dans laquelle on a grandement amélioré notre script avec une gestion des erreurs qui nous permet de savoir si quelque chose ne fonctionne pas je peux vous montrer par exemple ici si je mets autre chose on va mettre point et on va mettre un nom de un nom de domaine ici qui n'existe pas donc là vous voyez qu'on a bien une erreur et si je remonte ici on va voir le message voilà C unfetch content from qui vient de notre logueer donc si je viens ici on a bien un message erreur comme celui-ci donc non plus un débug mais erreur puisque là on passe dans loger.error donc ça fonctionne bien on a la gestion des erreurs et on a bien séparé les chos avec notre fonction pour lire notre fonction pour écrire et le point d'entrée ici pour récupérer les informations soit depuis le disque soit directement depuis le site web dans cette partie on va enfin s'intéresser à la récupération des données à partir du code HTML de la page si vous allez voir le fichier HTML qui a été sauvegardé sur le disque vous allez voir que c'est un petit peu bordelli on a beaucoup de choses ici et le fichier n'est pas mis en forme si vous voulez remettre en forme pour avoir une structure HTML un peu plus lisible vous pouvez aller dans code si je me souviens bien ici et on va retrouver ici reformat file ou reformat code et ça va remettre en forme le code pour qu'il lui ait les bonnes indentations et tout ce qu'il faut donc ça se peut que ce soit un petit peu long parce qu'il y a énormément de contenus sur cette page si je descends vous allez voir qu'on a beaucoup beaucoup beaucoup de lignes HTML on est à 30000 lignes ici de de HTML de JavaScript et cetera et donc il y a beaucoup de choses ici dans lesquelles on va devoir faire une sélection également vous allez voir quelque chose d'assez surprenant si je viens en haut à droite ici pour ouvrir le fichier dans un navigateur on va prendre par exemple Chrome vous allez voir quelque chose d'assez surprenant à savoir que on a le contenu qui est affiché mais qui semble disparaître tout de suite après alors ça j'ai l'impression que c'est des précautions en fait qui sont prises par rirbnb ou je ne sais pas si c'est voulu ou pas mais en tout cas si je viens ici dans le inspect et bien ici on aura plus les don qu'on souhaite donc je pense qu'il y a un script quelque part ici qui doit modifier les informations une fois qu'on charge la page j'avais essayé en préparant cette formation de supprimer tous les tags de script ici du fichier HTML et j'avais réussi au final à avoir bien les données qui restaient mais ce n'était pas très pratique et ce n'est pas non plus très pratique de devoir aller analyser notre HTML directement dans ce fichier dans pycharm donc ce que je vais faire pour la formation c'est tout simplement retourner sur le site de Airbnb on va remettre notre Rio de Jero on va choisir une date ici et on va inspecter en fait directement le html depuis la page live et ça devrait être la même chose directement dans notre fichier donc ça ne devrait pas poser de problème puisque tout le code va être similaire c'est juste que là on l'a en live en direct et on va faire notre étude à partir de ça donc la première chose qu'on va faire ici c'est créer une fonction donc je vais la mettre tout de suite après le fetch content on va l'appeler get average price puisque nous ce qui va nous intéresser c'est de récupérer le prix moyen de la page à laquelle on va accéder donc on va va lui passer en entrée le code HTML de la page et en sortie on va retourner un nombre entier qui va être la moyenne du prix de toutes les locations on pourrait également retourner un nombre décimal un float moi dans ce cas-ci je n'ai pas besoin de cette précision extrême je peux m'entenir à un int donc on va dire ici from the html we get the average price tout simplement et ici on va déjà faire une liste qui va nous permettre de stocker les prix et par la suite on fera un petit calcul mathématique très simple pour retourner la somme de tous ces prix divisés par la longueur de la liste ce qui va nous donner la moyenne des prix sur la page donc ce qu'il faut faire déjà c'est utiliser beauatiful soup et le parseur HTML de cette librairie pour pouvoir naviguer plus facilement à l'intérieur de la structure du HTML donc je vais rajouter l'import au début du fichier d'ailleurs c'est une bonne chose de mieux séparer les imports vous pouvez là encore si je me souviens bien le faire en faisant reformat file où on avait directement en fait le optimize inimport ici qui va automatiquement remettre les imports comme il faut c'est-à-dire enlever ceux qui ne sont pas nécessaires là ils sont tous utilisés mais si jamais on avait quelque chose qui n'était pas utilisé ils serait en gris et avec cette option et bien il serait tout simplement enlevé du fichier puisque il enlève les modules qu'on utilise pas et également il y a cette séparation qui a été faite vous voyez ici entre les modules de la bibliothèque standard que sont logging et paathlib et les modules de bibliothèque tierce qu'on a installé comme request et on va continuer ici donc en mettant beautiful soup également à la suite puisque c'est également une bibliothèque qu'on a dû installer en plus et qui ne fait pas partie de la bibliothèque standard donc je veux dire from BS4 import beautiful soup et on va utiliser donc ce beautiful soup pour transformer notre chaîne de caractèrees HTML en arbre à travers lequel on va pouvoir naviguer plus facilement donc je veux dire soup é= beautiful soup on va lui passer notre HTML et on va passer l'analyseur qu'on souhaite utiliser pour analyser ce HTML donc si vous allez voir dans beautiful soup vous allez voir les différents parseur qui sont disponibles on a lxml lxml XML HTML parsur et HTML 5 lib nous dans notre cas on va utiliser html par parce qu'il est un peu plus rapide que HTML 5lib il va donner des résultats un peu moins bons si vous avez un fichier HTML qui n'est pas correctement formaté mais là dans ce cas-ci on va faire confiance à Airbnb pour nous retourner du HTML qui est correct et qui ne comporte pas trop d'erreur donc je vais passer avec celui-là donc HTML parsur pour analyser le html que je vais lui passer et ensuite on va devoir donc récupérer les différentes informations de prix donc si je reviens sur mon site on a tous les logements qui sont disponibles ici avec dans ce cas-ci presque tout le temps un prix réduit euh à part par ici donc ça c'est parfait on va pouvoir gérer les deux cas de figure donc je vais commencer avec le premier cas de figure ici avec le prix en réduction donc on va reprendre notre outil d'inspection ici et on va aller voir la classe qui correspond à ce prix donc c'est la classe ici donc ça c'est le prix qui est réduit donc ce n'est pas celui qui nous intéresse nous ça va être celui-ci le 1 y74 et cetera donc je vais copier ce nom de classe je vais retourner dans mon fichier et je vais le mettre ici en commentaire pour qu'on l' comme référence et je vais prendre également le prix ici qui est le prix sans réduction donc c'est cette classe ici qui contient le prix je vais l' encore copier et le mettre ici donc en fait ce qu'il va falloir faire ici c'est vérifier si on a déjà celui qui existe ici puisque ce n'est pas le cas dans le prix réduit si je reviens là en fait on va avoir la classe du prix original qui ne nous intéresse pas ici la classe du vrai prix qui est 1Y et cetera donc on va déjà vérifier si on a cette classe si on a le 1Y et si ce n'est pas le cas et bien on va récupérer cette classe tyx JP1 et ce que je vais faire c'est remonter un petit peu plus haut puisque moi je ne veut pas chercher sur toute la page au complet ce que je veux c'est chercher dans chaque annonce cette information donc si je remonte un petit peu dans la hiérarchie on va essayer de voir s'il y a pas un endroit où on a quelque chose qui nous permette de récupérer la carte au complè qui va contenir l'image la description et ces classe avec le prix donc si je reviens un petit peu là on est dans les descriptions avec le nom de l'annonce on voit un test ID ici qui pourrait être très pratique pour aller récupérer le nom de l'annonce et si je remonte ici jusqu'à la carte on va essayer de remonter le plus haut possible donc par exemple jusqu'à ce div donc là on a des div et là on a un méta et cetera donc nous c'est ce qui nous intéresse ici le div donc là on a des div qui n'ont ni classe ni ID donc ce n'est pas très intéressant si on descend ici par contre là on va voir un Data test ID cart container donc ça ça pourrait être une bonne première option ensuite ici on a le lien pour cliquer sur la location et si on descend ici on va aller vérifier si on a pas des choses qui pourraent être un peu plus spécifiques ici là on a le card title donc là on est déjà un petit peu trop bas donc je vais remonter là où j'étais avec les deux div là on a les méta et là là je vais essayer de remonter le plus haut possible donc là encore on a des dir avec pas grand-chose des transitions style et là on a un item propre item list element qui pourrait être pas mal aussi avec les Méas donc je pense que je vais m'arrêter ici au item propres on va pouvoir récupérer les éléments qui ont ça je vais aller vérifier quand même que c'est bien quelque chose qui est unique et qui correspond à chaque carte donc je vais faire un contrôle F contrôle V pour pter ici là on a 1/ 24 je vais descendre un petit peu on a bien les cartes et ça me semble être pas mal on a à chaque fois les différentes cartes qui sont retournées la première la deuxième et cetera et on va aller jusqu'à la fin j'imagine comme ça donc ça semble être pas mal on a aussi d'autres annonces ici à des dates similaires qui contiennent donc les différentes informations dont on a besoin donc il y a celui-là et il y a le card container si je me souviens bien qui était un autre endroit où on pourrait aller qui contient aussi toutes les informations ça je le vois puisque quand je mets en surbrillance on voit que le carré en surbrillance contient bien toutes les informations l'image le titre et le prix donc on pourrait utiliser le Data test ID card container ou le item pro item list element qu'on avait au-dessus ici à vous de voir le DAT test ID c'est pas mal puisque ça c'est des choses qui sont utilisées par des outils de test donc c'est quelque chose qui devrait qui ne devrait pas trop bouger donc dans mon cas je pense que je vais utiliser celui-ci pour cibler les cardes puisque ça risque de ne pas bouger même avec d'autres mises à jour alors que le item propre item list element j'ai un peu plus de doute là-dessus donc je reviens dans pcharm et on va récupérer tous les div qui contiennent ce data test ID égal à carte container donc là encore je vais le mettre dans un comter pour l'avoir en référence on va créer une variable dives et on va faire tout simplement soup point find all donc find all puisque là on va avoir plusieurs occurrences qui nous seront retourné si on voulait récupérer uniquement le premier par exemple on pourrais faire un find là je veux tous les récupérer donc je veux récupérer les div et qu'est-ce qu'on va récupérer on va récupérer le Data test ID qui va être égal à carte containur alors normalement si on avait pris le item propre on pourrait le mettre comme ça en propriété comme ça item list et lement ça marcherait etéement comme ceci là comme on a un paramètre ici avec un tiret ça ne marchera pas de cette façonlà puisque on ne peut pas mettre des tirets comme ça et vous allez le voir avec la coloration syntaxique et les messages d'erreur on ne peut pas mettre un tiret ce n'est pas valide comme nom d'argument pour une fonction donc ce qu'on peut faire ici c'est mettre un dictionnaire à la place avec des chaînes de caractère donc une clé et une valeur comme n'importe quel dictionnaire et ça va marcher de la même façon que si on passait un argument avec sa valeur et là ce qu'on va mettre donc c'est carart container à la place de item list element donc je vais pas aller plus loin pour l'instant et je vais faire tout simplement un return de zéro pour terminer ma fonction ici on retournera bien entendu le bon résultat par la suite mais je veux juste déjà tester que tout fonctionne donc là je vais retourner ici dans mon name al main on va remettre le from disque égal à TR puisque comme on a vu et bien on ne veut pas faire des requêtes inutiles donc je vais partir du contenu qui est sur le disque et je vais faire un donc je crois que c'est get average price voilà HTML égal à content et on va mettre donc un point de débug comme je l'ai mis ici pour voir ce que va contenir le div et je vais lancer mon script non plus cette fois avec la flèche verte mais avec le point de débug ici puisqu'on va vouloir s'arrêter dans notre script après le div pour vérifier qu'on a bien récupéré ce qu'on souhaite donc là j'ai bien le point qui s'est arrêté ici donc on a récupéré le soup à partir du HTML et là on a bien des informations dans le div donc si je vais voir dans la petite fenêtre ici si elle n'est pas affichée vous pouvez aller dans le debug ici ou aller dans View et c'est dans tout le Window debug vous allez pouvoir afficher les variables qui sont contenus dans votre script au moment où vous êtes arrêté au point de débug et si je vais voir dans le div ici j'ai 18 résultats et on a bien les différents éléments qui semblent correspondre aux différents dives donc là ça ne semble pas fonctionner ne veut pas l'afficher donc ce que je vais faire c'est aller dans la petite dans le petit panneau ici et on va examiner un petit peu plus tout ça à la main donc je vais afficher en string le dives donc le premier dives je vais appuyer sur Entrée pour valider et là vous voyez là j'ai bien récupéré une chaîne de caractère puisque là on avait un objet tag et il ne semblit pas il ne semblait pas être très coopératif pour me montrer ce qu'il conenait donc là je récupère en chaîne de caractère le premier div on va aller dans View et on va faire un petit search pour vérifier qu'on a bien le nom de la classe qu'on cherchait donc je fais un contrôle F là encore alors on n pas cette classe ici je vais essayer avec l'autre qui correspondait au prix sans réduction je crois donc voilà on a bien le 256 € ici qui correspond au prix donc là on avait le prix voilà le prix sans réduction et le prix avec réduction donc ça contient bien ce dont on a besoin et on va pouvoir continuer pour cl à travers C div et récupérer les informations qui nous intéressent donc maintenant qu'on est sûr d'avoir les bonnes données on va récupérer les informations de prix qu'on avait vu à l'intérieur des spans qui contenaient cette classe ou cette classe donc ce que je vais faire c'est boucler à travers chaque div donc on va faire une boucle for très simple et on va créer une variable Price qui va être égale à div.find et là ce qui va nous intéresser c'est donc un span qui va contenir la classe donc pour classe ici comme c'est un mot réservé il faut mettre un tiret du bas c'est le nom de l'argument qui va nous servir à définir la la classe qu'on souhaite cibler et ici je vais mettre la première classe qu'on avait donc celle-ci et si jamais ce div n'est pas trouvé donc là je crois que c'était dans le cas d'un prix qui n'avait pas de réduction donc si on a un prix qui a une réduction ça veut dire que ça ça retournera non ici on aura aucun élément donc ce qu'on va faire c'est faire un or et on va refaire donc la même chose donc je vais tout simplement coller ce que j'avais déjà ici et on va mettre l'autre classe donc la classe tyx ici donc c'est-à-dire que là on va prendre l'un ou l'autre si celui-là est trouvé on va prendre celui-là sinon on va prendre l'autre tout simplement donc ça va nous assurer s'il y a un prix réduit de prendre le prix qui est réduit et s'il n'y a pas de prix réduit et bien de prendre le seul prix qui est disponible sur la cararde de l'annonce ensuite qu'est-ce qu'on va faire bien on va tout simplement faire une petite vérification ici puisque on pourrait tomber dans des cas de figure ou pour une raison une autre il n'y aurait aucune des deux classes et dans ce cas-ci on ne peut pas continuer avec notre script puisque on ne peut pas on n pas l'information de prix donc on va dire if not price donc si price après tout ça est égal à non et bien on va faire un warning cette fois-ci on va juste faire faire un avertissement on ne va pas faire une erreur on va juste dire qu'on a pas réussi donc Coon find price in div et on va mettre ici le code du div en question donc là on fait juste un warning et on continue avec le prochain div pour récupérer le prix donc à ce niveau-là je vais juste faire un print de price on va abandonner le debug pour le moment je vais juste donc arrêter l'instance du script que j'avais en cours et je vais relancer pour voir ce que ça nous retourne donc là on a bien les différents pan avec les informations qui nous intéressent avec les informations de prix donc et ce qui va nous intéresser nous c'est bien sûr uniquement le prix et pas tout ce qui est autour donc le span le symbole euro et cetera donc pour récupérer déjà le texte à l'intérieur de la balise je peux utiliser l'attribut texte donc je vais relancer là vous allez voir que déjà on va enlever toutes les balises qui vont être autour et là ce qu'il reste et bien c'est tout simplement à récupérer uniquement les nombres et ne pas récupérer les espaces le symbole d'e rau et tout ce qui pourrait être autre que le nombre brut du prix de la location donc pour ça moi ce que je vais faire c'est utiliser le module rjax de Python qui est très pratique pour ça qui va me permettre de supprimer en fait tout simplement tous les caractères qui ne sont pas des nombres de la chaîne de caractères donc je vais importer le module re qui signifie regular expression pour regex regex donc c'est un raccourci pour regular expression donc ces expressions régulières elles vont nous permettre de récupérer uniquement les nombres de notre chaîne de caractères pour ça je vais utiliser la fonction sub qui va nous permettre de soustraire des éléments d'une chaîne de caractère et le pattern que je vais lui donner donc ça va être une expression régulière je mets un r ici devant ma chaîne de caractère pour qu'elle soit interprétée comme une chaîne de caractère brut donc une RAW string puisque dans les chaînes de caractères pour les expressions régulières on va avoir beaucoup de symboles qui pourraent être interprétés différemment dans une chaîne de caractère si on ne met pas le r donc par exemple des retours à la ligne ou des choses qui pourraient perturber notre le bon fonctionnement en fait de notre chaîne de caractère donc des caractères en fait qui pourraent être interprétés nous on ne veut pas qu'il soit interprétés on veut vraiment que ce soit juste les caractères tels qu'on les met et c'est pour ça que pour les expressions régulières on met le r ici pour indiquer qu'on veut une RAW string donc une chaîne de caractère brut donc là ce que je vais mettre c'est un slash si j'arrive à le trouver voilà slash D qui signifie qu'on souhaite supprimer tout ce qui n'est pas un digit donc tout ce qui n'est pas un nombre on souhaite le supprimer en tout cas le remplacer nous dans notre cas on va le supprimer on pourra mettre autre chose ici on pourra mettre Patrick pour remplacer par Patrick nous ce qu'on veut ce n'est pas remplacer mais juste les supprimer donc c'est un peu comme un replace le replace qu'on retrouve sur les chaînes de caractères dans ce cas-ci c'est la fonction sub qui nous permet de soustraire ces éléments en fait de les remplacer donc dans ce cas-ci de les soustraire puisque je men chne de caractère vide de l'élément qu'on va lui passer qui dans ce cas-ci va être price. text je vais récupérer ça dans une variable que je vais appeler price tout simplement donc je vais écraser le price qu'on avait ici on pourrait si on le veut séparer pour que ce soit un peu plus clair dans le nom des variables et mettre ici priceed.text pour ne pas clasher entre ces noms et que ce soit un petit peu plus clair donc là je vais refaire un print de Price pour vérifier qu'on est toujours sur la bonne voie je relance le script et là ça fonctionne vous voyez qu'on a bien réussi à récupérer les prix sans les symboles euros sans les espaces et quoi que ce soit donc ce qu'on va faire ensuite c'est tout simplement vérifier à ce stadel que on a bien quand même juste des nombres puisque nous ce qu'on va vouloir faire c'est des opérations sur ces éléments pour l'instant si on fait un print de type de Price vous allez voir qu'on est en présence de chaîne de caractère donc on ne va pas pouvoir additionner soustraire et cetera ces informations pour ça il faut les convertir en nombre avec la fonction int le problème c'est que si on essaie de convertir si jamais en fait on a un problème quelque part normalement ça ne devrait pas être le cas puisque ici on enlève tout ce qui n'est pas un nombre mais on n'est jamais trop sûr donc moi je préfère rajouter une vérification pour vérifier que on a bien que des nombres à l'intérieur de cette chaîne de caractère avec is digit ici qui va vérifier qu'on a bien que des nombres de 0 à 9 donc si c'est le cas et bien tout simplement on va ajouter à notre liste donc avec un happened le Price qui va être converti en nombre ce qui va nous permettre ensuite de les additionner et de faire une moyenne de toutes ces informations et ici on va tout simplement faire un loger point dbug pour indiquer qu'on a bien trouvé un prix correspondant donc on va indiquer le prix ici on va dire price find et on va avec les accolades ici insérer le prix qui a été trouvé on l'ajoute ensuite donc dans notre liste et si ce n'est pas le cas donc si jamais on na pas de digit il y a un problème quelconque là on va refaire un loger point warning en disant que le prix et là on va intégrer sa valeur ici avec les accollades on va dire is not a digit donc comme je vous dis normalement il y a pas vraiment de cas de figure dans lesquels on devrait rentrer à l'intérieur de ça puisque avec la reex on s'assure déjà de supprimer tout ce qui n'est pas un nombre mais je préfère quand même le faire de façon un peu plus claire ici si jamais on changeait la reex ici pour quelque chose d'autre et bien ça permettrait quand même de récupérer les erreurs potentielles si jamais quelqu'un choisissait de modifier cette chaîne de caractère dans la Rex pour quelque chose qui soit un peu plus un peu moins précis et qui permettrait potentiellement de laisser échapper des nombres dans notre chaîne de caractère et qu'est-ce que je vais faire donc au final je vais déjà relancer le script pour voir si on a bien tout ce qu'il faut donc là on a bien les price found avec les les différentes valeurs ici et je vais faire un print à la fin de Price pour voir si on a bien toutes les valeurs à l'intérieur de la liste donc ça semble bien être le cas donc ce que je vais faire ici tout simplement à la fin et bien c'est retourner la moyenne de tout ça donc je vais enlever les bouts de codes que j'avais ici et donc pour faire la moyenne des prix à l'intérieur de la liste c'est assez simple on va faire une somme de toutes les valeurs à l'intérieur de la liste et diviser tout ça par la longueur de la liste et on va également rajouter une petite fonction round pour faire un arrondi de tout ça au cas où on ait des valeurs décimal d'ailleurs il faudrait vérifier je crois que sur Airbnb de ce que j'ai vu il y a que des valeurs donc que des nombres entiers si on avait des valeurs décimales il faudrait probablement rajouter des vérifications puisque on pourrait avoir selon les pays un point ou une virgule et ça ne passerait pas forcément tous dans le int ici là j'ai vu que des nombres entiers donc ça ne devrait pas poser de problème mais voilà je préfère rajouter le round ici pour s'assurer d'avoir un conton à la fin et on va quand même rajouter une petite vérification on va vérifier en fait qu'on a bien des informations dans price ici parce que imaginez et que en fait pour une raison ou une autre on passe à chaque fois dans le continue ici et bien price serait une liste vide et on ferait donc ici une division par Z0 et on se retrouverait donc avec une erreur de Z0 division error donc je vais quand même vérifier ici qu'on a bien l'Ender Price qui est défini donc qui est plus grand que zé sinon on va faire else 0 tout simplement on va retourner une valeur quand même mais qui sera égale à zé donc voilà pour la récupération de la moyenne de tous ces prix on fait avec ce petit if ici donc c'est une tout simplement une condition ternaire qui nous permet de faire un IF else sur une seule ligne euh qui nous permet donc d'éviter cette zer division erreor au cas où on ne récupère aucun prix je vais refaire un petit reformat de mon code là il y a des lignes un petit peu en trop moi j'ai mon raccourci clavier pour ça qui est option commande l sur Mac sinon ça se trouve dans code et vous allez retrouver le reformat code ici qui va automatiquement remettre votre script et par la même occasion enlever les petits avertissements que vous aviez qui si je me trompe pas été juste des avertissements voilà euh par rapport au fait qu'il y a trop de lignes blanches ici donc c'est des choses choses qui sont bien définies dans la PEP 8 de Python euh à savoir quel combien de lignes il faut avoir entre chaque élément entre chaque fonction et cetera donc là vous voyez j'en avais un petit peu trop j'avais trois lignes au lieu de deux donc moi je fais très souvent ce petit raccourci clavier qui me permet de tout remettre automatiquement bien comme il faut et d'enlever ses avertissements dans le code donc voilà pour cette partie normalement ça devrait être tout bon on va quand même tester qu'on a bien quelque chose de cohérent donc je vais faire juste avant ici un print de Price pour voir si c'est cohérent avec la liste qu'on a et là on va faire une variable qu'on va appeler average price et on va l'afficher à la fin pour voir si c'est cohérent comme je vous dis donc là on a euh un une moyenne de 1005 et si on regarde avec les nombres qu'on a ici ça semble être assez cohérent voilà on a 256 1200 1600 donc on aussi entre des valeurs assez basses comme 256 euh et assez hautes comme 1700 donc ça me semble assez logique qu'on se retrouve avec un nombre final qui soit 2005 donc on pourrait bien sûr faire le calcul quand même pour vérifier que tout est bon mais normalement on a fait tout ce qu'il faut ici comme il faut pour récupérer ce prix de la bonne façon donc voilà pour cette fonction vous voyez il y a quand même pas mal de petites choses qui nous permettent de vérifier qu'on aura pas d'erreur on pourrait simplifier le code avec quelque chose d'un petit peu plus bourrin avec peut-être un try accept général qui essayerait de de récupérer les choses et de faire la conversion et de peut-être récupérer un value error si jamais on arrivrivait pas à faire cette conversion dans ce cas-ci j'ai préféré faire des IF donc if if else ici pour vérifier qu'on a bien les bonnes informations à chaque fois et récupérer ce dont on a besoin pour finaliser cette version de notre script on va rajouter quelques lignes de code pour pouvoir le lancer directement avec une URL depuis un terminal ce que je vais faire c'est tout en haut ici rajouter un module qui va être le module 6 qui va nous permettre de récupérer les arguments qui vont être passés à notre script et notamment le dernier argument qui va contenir l'URL de la page qui contient les données qu'on souhaite récupérer donc ce que je vais faire ici à la place de URL je vais mettre tout simplement 6.arcv arc V c'est une liste liste qui va contenir tous les arguments de notre script et moi je vais passer l'URL en dernier argument donc je vais tout simplement récupérer cet élément avec -1 puisque ce sera la dernière chose qu'on va passer à notre script ensuite ici je vais enlever le from disk puisque par défaut on va vouloir récupérer les dernières données en ligne depuis le site et ensuite je vais juste faire ici un print de average price pour afficher le prix moyen et pour finir je vais changer le mode de mon logging puisque si je laisse en débug ici je vais avoir toutes les données de dbug moi ce que je veux ici ce n'est plus avoir ces informations de débug mais juste les erreurs potentielles donc je vais le passer plutôt à error pour voir uniquement les erreurs qui pourraient arriver dans notre cas je crois qu'on a juste une seule erreur donc je vais regarder ici on a effectivement une seule occurrence de loger.erreor qui est dans le cas où on a une erreur sur la requête donc si jamais il y a une erreur avec l'URL qu'on a fourni donc je vais essayer tout ça là on a bien l'URL qu'on récupère je vais pouvoir ouvrir un terminal essayer mon script donc je vais utiliser Python 3 et je vais lancer main.py en donnant après donc donc en dernier argument ici l'URL qu'on a copié qui est l'URL de la page qu'on souhaite récupérer je lance et normalement je devrais bien avoir ici la valeur qui m'est retourné qui est bien dans ce cas-ci 1188 je vais tester avec une autre URL on va aller ici et remplacer Rio par par exemple Paris et je vais laisser la date ici rechercher je vais prendre cette url donc là on voit qu'on a des prix qui sont quand même un petit peu plus chers donc on devrait avoir une moyenne un peu plus élevé donc je retourne dans mon terminal je vais relancer donc avec Python 3 main.py et cette fois-ci avec l'url de Paris et on va voir si on est effectivement un peu plus élevé donc on est à 1834 ici en prix moyen pour cette url donc voilà pour les dernières lignes de code que je voulais rajouter pour pouvoir lancer facilement mon script depuis le terminal sans avoir besoin de modifier quoi que ce soit dans mon script pour pouvoir changer la page que je vais aller récupérer dans cette partie on va utiliser playright pour afficher notre page et par la suite récupérer les données qu'elle contiennent en naviguant de façon plus naturelle à l'intérieur du site grâce à toutes les fonctionnalités de la bibliothèque playwright qui est normalement utilisé pour faire des tests c'est-à-dire vérifier que notre code fonctionne bien notamment avec des tests qu'on appelle end to end c'est-à-dire des tests qui vont vérifier une suite d'action et non pas une seule action précise comme pourrait le faire un test unitaire en vérifiant directement notre code donc ce que ça nous apporte comme intérêt c'est qu'on va pouvoir vraiment naviguer sur les pages comme on le ferait à la main mais quand même avec du code que l'on va écrire dans cette partie et les parties qui vont suivre donc la première chose que je vais faire c'est importer playright dans ce cas-ci on va utiliser l'API Sync puisqu'on a deux API on a l'API asnc et laapi Sync donc la différence entre les deux c'est que la librairie async va nous permettre de faire des requêt asynchron ça nous permettrait par exemple de faire plusieurs requêtes en même temps sans attendre qu'une requête termine pour lancer une autre dans le cas de ce script pour garder ça simple et éviter d'avoir beaucoup plus de codes avec les wet notamment qui sont sont nécessaires dans un code Sync et bien on va utiliser la librairie Sync donc la librairie synchrone et ça va nous permettre aussi de garder quelque chose de éthique puisque comme on l'a vu dans les parties précédentes on souhaite également ne pas surcharger le site de requê qui pourrait être le cas avec des requêtes asynchrone puisqu'on pourrait envoyer plusieurs requêes en même temps dans notre cas on veut récupérer seulement quelques informations sur le site et on a donc pas besoin d'avoir quelque chose de très très performant avec plusieurs requêtes qui pourraient surcharger le site donc je vais importer cette librairie à partir de playri donc from playri.sync API on va importer Sync playri on va ensuite faire une fonction qui va être la fonction principale que je vais appeler run et je vais lui passer PW qui va être un paramètre qui va recevoir une instance de playwright on verra par la suite comment la passer à cette fonction et pour l'instant je vais juste mettre un pass à l'intérieur on va refaire notre structure main donc la fameuse if name égal main et à l'intérieur de cette structure on va lancer la fonction run avec un contexte manager donc on va dire avec Sync playri qu'on va récupérer dans une variable qu'on va appeler playright on va lancer notre fonction donc là on crée ici alors je vais refaire mon adantation là il y a eu un petit souci apparemment voilà donc avec cette instance qu'on va récupérer dans playwri on va passer donc on va lancer cette fonction que l'on va finaliser tout de suite on va lui passer donc PW cette instance de playwright et à partir de ça on va pouvoir créer notamment un navigateur qu'on va pouvoir afficher que ce soit en headless ou non donc headless comme ceci qui veut dire qu'on souhaite afficher ou non le navigateur donc nous dans notre cas au début on va vouloir l'afficher pour voir un petit peu ce qui se passe et par la suite on verra qu'on pourra le lancer sans afficher le navigateur donc tout va se faire en arrière-plan sans qu'on ait besoin d'ouvrir le navigateur et on va quand même pouvoir récupérer bien entendu les données qui seront dans le code HTML donc ce que je vais faire ici à l'intérieur de cette fonction c'est utiliser playwright donc utiliser cette variable ici PW pour créer un navigateur qui va être un navigateur chromium et que je vais lancer avec la fonction launch donc on fait une instance de Chromium qu'on lance et on peut spécifier ici si on souhaite être en headless ou non donc moi je vais le mettre à false puisque comme je vous ai dit dans les premiers tests on va vouloir vérifier que tout se passe bien en affichant le navigateur et je vais récupérer tout ça dans une variable que je vais appeler browser on va faire un petit print ici pour l'instant on va pas encore mettre de logging on pourra le mettre par la suite pour l'instant je vais juste mettre des prints pour voir un petit peu ce qui se passe donc on va dire connecting to scrapping browser et maintenant qu'on a notre navigateur on va pouvoir créer une page puisque le navigateur par défaut ne va pas afficher une page donc il faut créer cette page et ensuite dire où est-ce qu'on souhaite naviguer sur cette page donc je vais faire une variable page qui va être égale à browser.nepage qui va nous permettre de créer cette nouvelle page pour ensuite naviguer vers une URL donc pour l'instant je vais juste faire un go to et on va mettre par exemple Google tout simplement pour vérifier que tout fonctionne donc le goto ça nous permet de naviguer à une URL et d'afficher donc cette URL et pour finir on va faire un browser point close pour fermer le navigateur et c'est tout ce qu'on va faire pour l'instant et on va tester notre script pour vérifier que tout fonctionne donc là j'ai différentes façons de lancer ce script je peux cliquer sur la petite flèche ici je peux faire un clic droit et créer une nouvelle configuration automatiquement donc en faisant run main.py je peux aussi me rendre directement dans le terminal donc à l'intérieur de ce dossier j'ai créé un autre dossier scrapping advanced ici à l'intérieur duquel se trouve mon fichier main.py et je peux donc faire tout simplement Python 3 main.py pour lancer le script et voir ce que ça donne donc là on voit bien que le navigateur s'ouvre et il se ferme automatiquement puisque on n pas mis de points de débug ou quoi que ce soit qui nous permettent d'attendre donc ce que je vais faire ici c'est rajouter un petit temps d'attente généralement dans le scrapping vous allez voir très souvent le time point sleep qui permet d'attendre dans n'importe quel script Python un certain nombre de secondes avec playri on a une fonction pour ça qui s'appelle wait for time out donc on va attendre un certain nombre de secondes on va entrer cette valeur en millisecondes donc par exemple si je souhaite attendre 5 secondes on va mettre 5000 ici et là je vais relancer le le script cette fois-ci en faisant un clic droit et en créant une nouvelle configuration automatiquement donc avec run main ici ça va créer une nouvelle configuration et là on voit bien que on a le navigateur qui s'ouvre avec Google on attend 5 secondes et une fois que les 5 secondes sont écoulé on va fermer le navigateur avec browser.close donc si on va voir cette configuration vous allez voir rien de magique ici ce qu'on fait c'est tout simplement ce qu'on avait fait auparavant à savoir utiliser notre python donc le python de l'environnement virtuel pour lancer le script à l'intérieur de ce dossier donc le working directory ici donc c'est exactement la même chose que j'ai faite ici dans le terminal par défaut automatiquement il va sourcer notre environnement virtuel puisqu'on l'a créé avec pcharm et donc si je fais un witch Python 3 ici vous allez voir qu'on a bien le même Python qui est à l'intérieur de cet environnement virtuel que l'on va utiliser pour lancer notre script main.py un autre outil qui va nous être très utile pour la suite de cette formation et pour playwright en général c'est l'outil de dbug qui nous permet de vérifier les différentes étapes de notre script comme le débug qu'on aurait dans pcharm mais égal également d'avoir accès à des outils très puissants qui vont nous permettre de générer du code playright automatiquement avec les outils de débug que je vais vous montrer tout de suite donc pour ça on va définir une variable qui s'appelle PW debug donc playwri debug comme ceci tout en majuscule qu'on va mettre égal à 1 et on va mettre ensuite Python 3 main.py donc comme on l'a fait pour lancier notre script donc là ce qu'on fait c'est que sur la même ligne on définit cette variable d'environnement à 1 et ensuite on lance notre script donc c'est bien important vous pouvez bien entendu mettre cette variable dans votre configureation si vous souhaitez vous faire une configuration pour le débug on pourra voir comment faire par la suite là je vais lancer tout ça sur la même ligne je lance et vous allez voir que là on a deux fenêtres qui s'ouvrent cette fois-ci donc une fenêtre de débug qui va s'arrêter automatiquement au premier goto et là on retrouve les outils bien familiers de ceux qui font beaucoup de débug à savoir le stepover qui va nous permettre d'avancer étape par étape mais on a aussi d'autres boutons très intéressants comme le bouton record ou ce bouton qui va nous permettre de vérifier les éléments sur la page donc là je vais continuer en avant l Sant d'un pas avec le stepover on va se rendre sur notre page et on a bien la page de Google qui s'affiche et là par exemple vous allez voir qu'on peut vérifier quel est le bouton ici si on souhaite cliquer dessus donc je vais cliquer sur cette icône ici pour sélectionner les locators on se retrouve avec les mêmes outils de débug que ceux qu'on pourrait avoir avec Chrome ou n'importe quel navigateur sauf que là c'est vraiment un outil qui va nous sortir du code pour playwright donc là on voit le get by roll button avec le nom donc je peux cliquer dessus et le locator va apparaître ici on va pouvoir copier ce locator dans notre code mais encore mieux pour faire ces étapes et directement pouvoir copier le code on peut cliquer sur record et là vous allez voir que je peux refaire cette étape sauf que cette fois-ci ça va me créer un nouveau fichier avec le code nécessaire pour faire les actions que je vais faire dans le navigateur donc là vous allez voir qu'on peut continuer comme ça là je vois le label donc on va voir get search exact to donc je clique là encore à chaque clic que je fais on voit le code associé qui se met dans la petite fenêtre à droite là je peux mettre par exemple Python où on va mettre carrément doc string pour vérifier ce que ce que ça nous retourne doc string tutoriel par exemple et je vais appuyer sur entré pour valider et là vous voyez qu'on a bien donc ici toutes les opérations qu'on a faites qui se retrouvent dans la page donc je peux cliquer par exemple et revenir donc fermer ce navigateur fermer ça ici on va sortir de notre script et je peux coller ces informations ici pour pouvoir les exécuter donc je relance le script cette fois-ci on va aller dans notre configuration et je vais vous montrer comment mettre cette variaable d'environnement donc là on voit qu'on a les variables environnement pour l'instant on a juste python unbuffered é= à 1 qui est la variable par défaut je vais mettre un point virule ici et mettre PW debug é= à 1 et on peut renommer cette configuration par exemple en script debug par exemple je valide avec ok je relance cette configuration et là vous allez voir qu'automatiquement donc on a le débug qui arrive et je peux vérifier que tout fonctionne comme je l'ai fait donc en avançant pas à pas là on a un indicateur avec le point rouge qui nous montre l'élément sur lequel on va cliquer et on va continuer comme comme ça là on retrouve le point rouge avec la barre on va avoir le texte que je vais remplir et cetera et là on arrive à la fin et donc on ferme le navigateur donc ce petit débugger est très très pratique et on va l'utiliser dans la suite de cette formation pour analyser notre page et comment naviguer sur le site plutôt que de passer par le code HTML et d'analyser les classes et cetera on va pouvoir passer directement par ce debugger pour faire ces opérations à la main et les copier ensuite dans notre code dans cette partie on va voir comment utiliser le debuger de playwright pour naviguer à travers les différentes pages de recherche de Airbnb alors ce que je vais faire c'est déjà mettre mon url ici qu'on va utiliser à la place de Google pour afficher les résultats d'une requête vers Rio de janeero et passer à travers les pages de cette requête pour voir toutes les locations donc je vais mettre l'URL ici et là je suis toujours avec mon script debug qui a bien cette variable d'environnement PW dbug qui est égale à 1 et qui va lancer donc automatiquement le débuger de playwright quand on va lancer le script avant de lancer le script je vais mettre un point de débug ici pour ne pas fermer directement le navigateur une fois qu'on va être arrivé à cette page donc je lance le script en mode Debug et ça va ouvrir le debuger de playwright donc l'inspecteur ici je clique sur la petite flèche pour avancer pour exécuter ce page.g to pour qu'on ait la page qui s'affiche et ensuite on va donc arriver à ce point de débug qui ne va pas exécuter la ligne donc on va suspendre le programme ici pour ne pas fermer le navigateur et si je reviens donc dans le playwright inspectur avec la page je vais pouvoir cette fois-ci cliquer sur record pour inspecter la page donc là on voit qu'on a premièrement le pop-up pour les cookies alors je peux soit cliquer sur ok là on voit que le code qui va nous être retourné c'est un bouton avec le name ok qui est exact alors il se peut qu'il y en ait plusieurs sur la page un bouton avec OK dessus c'est quand même assez commun donc moi je vais préférer cliquer sur continuer sans accepter c'est un peu plus spécifique et là on voit qu'on a encore une fois un get by roll avec un bouton sauf que cette fois-ci le nom est est plus spécifique donc je clique là-dessus pour accepter le enfin pour ne pas accepter en fait les cookies dans ce cas-ci et on a bien notre code qui affiche dans l'inspecteur le page. get by roll donc le code qu'on avait d'afficher dans la fenêtre que je vais pouvoir ensuite copier dans mon script et si on descend ensuite ici on va voir que ce qu'on va pouvoir faire c'est naviguer dans les différentes pages en cliquant sur ce bouton donc le bouton qui a un label suivant on pourrait cliquer sur les pages individuellement mais le problème c'est que là en fait on va avoir à chaque fois un nom qui va être différ par exemple un lien ici avec name qui est égal à 2 ensuite 3 4 et cetera donc ce sera un petit peu pénible je pense que de cliquer sur la flèche ça va être plus plus spécifique et donc si je clique ici on va là encore une fois afficher le code dans l'inspecteur qu'on va pouvoir par la suite copier et maintenant il faut que je m'assure de ne pas aller plus loin que la page 15 donc ce que je vais faire c'est arrêter le record ici là je n'ai plus besoin de ça je veux juste me rendre sur la 15e page et voir qu'est-ce qu'on va pouvoir vérifier dans ce cas-ci pour s'assurer de ne pas euh de de ne pas continuer au-delà de la page 15 puisqu'il n'y a plus de page après donc là on voit que j'ai un petit symbole de désactivation et je vais faire cette fois-ci un clic droit inspect pour aller vérifier à quoi ressemble ce bouton et ce qu'on pourrait avoir comme attribut par exemple dessus pour vérifier si l'attribut est présent ou non et arrêter de faire défiler les pages quand cet attribut est présent donc je vais cliquer sur la petite flèche ici pour inspecter cette élément donc là on voit qu'on a un SVG pour la flèche et si je remonte ici on devrait avoir le bouton en question avec effectivement le ara label qui est égal à suivant donc ça c'est ce get by label qui va nous permettre de récupérer le bouton mais si on regarde bien ici on a d'autres attribut assez intéressant on a le disabled qui nous indique que le bouton est désactivé et le Arya disabled qui est un attribut qui est atchu qui nous permet de savoir également que le bouton est désactivé donc on va pouvoir se servir de ça pour faire une boucle et vérifier quand cet attribut est présent ou non pour arrêter de continuer à cliquer sur le bouton quand on va arriver à la dernière page donc je vais euh copier ces deux lignes ici je je vais faire contrôle C et je vais arrêter mon script et on va pouvoir coller ces lignes à la suite de notre goto pour effectuer ses actions donc notamment cliquer sur le bouton continuer sans accepter et ce get by label on va pour l'instant le couper puisqu'on va le mettre à l'intérieur d'une boucle pour à chaque fois cliquer sur ce bouton tant que on n pas ce fameux attribut Arya disable qui est tu donc je vais faire une boucle true puisque on ne sait pas encore combien de fois elle va boucler donc ce qu'on va faire c'est partir sur le postulat que on va continuer de boucler tant que on n pas contrrer ce ara disable qui est égal à true et si c'est le cas on fera un break pour sortir de cette boucle while donc ce que je vais faire c'est ici récupérer avec le get by label le bouton donc je vais par exemple dire next page Button et je vais enlever le clic puisque pour l'instant je ne veux pas cliquer dessus je veux juste le récupérer pour ensuite pouvoir faire une petite vérification ici par rapport à l'attribut dont on a parlé donc je vais vérifier avec if si sur next page button on a cet attribut donc pour ça on peut utiliser la méthode GET attribute comme ceci et on va lui passer le nom de l'attribut qui dans ce cas-ci est Arya disabled si cet attribut est égal à true donc à la chaîne de caractère true et bien on va faire un break alors attention ici c'est bien la chaîne de caractère ça ne va pas être un boulé1 puisque ici l'attribut on est avec du HTML tout ça ça va nous retourner des valeurs en euh chaîne de caractère donc là on vérifie bien que c'est la chaîne de caractère true avec ici un T minuscule on pourrait mettre un lower ici pour s'assurer que on a bien cette valeur qui est récupérée en minuscule aussi mais comme on l'a vu dans le code HTML elle était déjà en minuscule donc je vais faire juste cette vérification ici donc si ce n'est pas le cas si on n' pas cet attribut Aria disable ça veut dire que le bouton est actif et qu'on peut donc cliquer dessus pour passer à la prochaine page donc je vais faire next page button.cilick pour cliquer sur le bouton et on va vérifier que tout ça fonctionne en mettant un point de débug ici sur le while et en relançant notre script alors cette fois-ci je vais enlever je vais peut-être même créer une nouvelle configuration ça va être plus simple je vais sélectionner le script debug ici et on va cliquer ici pour copier cette configuration et là je vais mettre script without Debug et on va enlever ce PW debug é= à 1 pour pouvoir lancer notre script sans le sans la vue de dbug donc je vais lancer par contre le dbug au niveau de pycharm pour qu'il s'arrête ici au niveau de ma boucle while et qu'on vérifie que tout fonctionne correctement donc je relance le script j'ai bien la vue de dbug qui cette fois-ci n'est plus affiché mais je rentre bien donc dans la boucle on a le while et le script qui s'arrête donc je vais rafficher cette page ici je vais faire un petit peu de place je vais mettre la page ici sur la droite et pycharm sur la gauche et on va vérifier que tout fonctionne correctement donc je continue je fais un stepover pour continuer sur le bouton on va vérifier que le bouton est bien récupéré donc là on a bien un locator si je fais un view ça ressemble pas mal à ce qu'on avait avec l'URL ici qui est l'URL de la page suivante on a le selector avec le bouton enfin le texte suivant et si je continue on va vérifier si on rentre ou non dans le nextpage button.get attribute donc ce n'est pas le cas puisque l'attribu n'est pas présent et on continue bien sur le clic donc je continue on va revenir au niveau de la boucle while et je vais vérifier dans le navigateur qu'on est bien passé à la page 2 et c'est bien le cas donc je vais continuer comme ça je vais pas le faire à chaque fois puisque là ce sera un petit peu long de se rendre jusqu'à la page 15 comme ça donc ce que je vais faire c'est juste changer mon point de debug pour le mettre sur le break ici et l'enlever sur la boucle while et cette fois-ci plutôt que de faire un stepover pour continuer ligne par ligne je vais faire un resume program avec ce bouton pour résumer le programme et il va normalement s'arrêter uniquement quand on sera rentré à l'intérieur de cette structure conditionnelle donc du if ici donc je fais un resume je lance on attend un petit peu et normalement voilà on est arrivé au niveau du break et si je descends ici on devrait être exactement comme on l'avait prévu à la page 15 puisque le bouton est cette fois-ci désactivé donc je continue là cette fois-ci je vais faire un step over on arrive bien au niveau du browser prank close et je vais continuer donc en faisant un resume program et on devrait voilà arriver à la fin du programme donc ça fonctionne correctement on passe bien à travers chaque page pour relancer le script sans le débug on peut mettre d'autres print ici on pourrait mettre par exemple ici une un numéro de page pour que ce soit un peu plus explicite donc je vais dire page number égal à 1 et ensuite on va incrémenter ce page number qu'on va faire plus é= 1 on va faire print et on va dire navigating to page et on va insérer le numéro de la page ici donc page number je vais même mettre ça directement ici voilà au début pour indiquer qu'on navigue vers la page qui contient page number donc on va essayer ça on va le relancer sans le debug et sans le mode debug ici donc script without debug avec la flèche de base et là voilà on ouvre la navigation on passe à travers chaque page là vous voyez que c'est assez rapide donc on pourrait pour avoir un scrapping un peu plus éthique rajouter des timer donc par exemple ici faire un page wait for timeout et mettre un timeout de 1 seconde entre chaque page on pourrait également rentrer une valeur aléatoire avec la bibliothèque random pour que ce soit encore plus similaire à ce que ferait un humain et je vais également changer le headless pour le mettre à true cette fois-ci pour vous montrer qu'on peut faire le scrapping sans avoir besoin d'ouvrir le navigateur donc je relance le script et là on devrait avoir un script qui va nous afficher voilà la navigation vers les pages avec vous le voyez à chaque fois un temps d'attente d'une seconde entre chaque page donc tout fonctionne correctement et on arrive bien à passer à travers toutes les pages de la location avec l'url de départ ici et ensuite une navigation qui se fait directement en cliquant sur le bouton qui permet de passer à la page suivante on pourrait le faire par exemple en modifiant l'URL ici on a probablement un numéro de page quelque part ici qui nous permet de passer à la page suivante mais un humain ne fonctionnerait pas comme ça on n'irait pas modifier l'URL pour changer le numéro de page en tout cas la plupart des gens ne feraient pas ça il cliquerait plutôt sur le bouton pour passer à la page suivante et c'est exactement ce qu'on peut répliquer ici grâce aux fonctionnalités de playwright jusqu'à présent on utilise un navigateur qui est directement sur notre ordinateur donc le navigateur chromium de Play right et dans cette partie on va voir comment alterner entre ce navigateur en local et le scrapping browser de Bright data qui va nous permettre de varier les proxis et de nous assurer que on ne sera jamais bloqué lorsqu'on fait des requêtes vers notre site Airbnb puisque quand on fait tout en local au bout d'un moment même si vous espacez les requêtes même si vous faites attention il peut arriver des moments où vous serez bloqué et c'est là où l'utilisation du scrapping browser va permettre automatiquement sans que vous ayez rien besoin de faire de changer de proxy donc d'utiliser en fait un autre ordinateur tout simplement pour pouvoir refaire vos requêtes tout ça va être géré automatiquement et on va voir dans cette partie comment on peut facilement intégrer un switch qui nous permet de passer de l'un à l'autre facilement dans notre script donc dans l'interface de Bright data je vais me rendre sur le scrapping browser que j'ai ici vous voyez que avec tous les tests que j'ai fait pour cette formation je n'en suis qu'à 4 dollars de dépensé si vous n'avez pas encore de scrapping browser dans la liste ici vous pouvez en ajouter un nouveau je crois que par défaut il y en a un et il n'est juste pas activé s'il n'y en a pas vous pouvez cliquer sur Add ici et ajouter un scrapping browser et tout simplement sauvegarder et continuer sur la page que je vais afficher maintenant en cliquant dans ce cas-ci sur le scrapping browser qui est disponible ici dans mon cas donc je clique dessus j'arrive sur cette page de configuration on a d'autres configurations ici un peu plus avancées notamment si vous souhaitez mettre des cookies ou des headers custom mais dans ce cas si on n en aura pas besoin on va utiliser les options par défaut et vous avez un dernier onglet statistique ici qui va vous montrer les statistiques d'utilisation de votre scrapping browser donc assurez-vous de bien l'activer en cliquant ici sur Active proxy et on va voir ici différentes informations qui vont être importantes notamment le nom d'utilisateur le host et le mot de passe qu'on va pouvoir utiliser pour se connecter avec ce scrapping browser donc je vais faire un petit peu de place ici en mettant pycharm à gauche et mon navigateur à droite et on va maintenant utiliser les informations qu'on a ici pour se connecter à ce scrapping browser vous pouvez également vérifier le code qui est disponible en cliquant ici sur checkout code and integration examples et vous allez avoir des exemples de codes préfaits pour différents langages et différentes librairies vous avez notamment le langage Python bien sûr et la librairie playwright donc exactement ce qu'on est en train d'utiliser et vous voyez ici la chaîne de caractèrees complète qui va nous permettre de nous connecter à ce scrapping browser vous avez également un exemple de code avec cette fois-ci l'API async donc asynchrone de playwright qui permet de faire à peu près la même chose que ce qu'on vient de faire jusqu'à présent donc je vais copier cette chaîne de caractère ici qui n'est autre qu'une chaîne de caractère qui contient le host le USERNAME et le password qu'on a vu sur la page précédente donc là on voit ici le nom d'utilisateur le mot de passe et ensuite le host ici avec WSS qui signifie WebSocket sécuriser ce qui va nous permettre de faire nos requêtes à travers ce webscket et accéder au scrapping browser de Bright data donc vous retrouvez ici le host le USERNAME et le password donc j'ai copié moi toutes ces informations ici alors je vais refaire un petit peu de place pour pour qu'on voit la chaîne au complet donc on a bien le WSS pour WebSocket sécurisé 2./ slash donc la même chose qu'un HTTP 2.//ash sauf que ici c'est WSS on a ensuite ici donc le nom d'utilisateur deux points le mot de passe et ensuite @as et le host qui est BRD superuperproxy.ioo 2 point et le port 9222 et donc c'est grâce à cette url qu'on va pouvoir se connecter à la place de notre chromium local au scrapping browser de Bright data donc ce que je vais faire c'est que je vais rajouter ici ici un paramètre je vais mettre bright data qui va être égal par défaut à false et ça va nous permettre quand on lance ici de spécifier si on souhaite utiliser le navigateur local ou le scrapping browser de Bright data donc là je vais mettre bright data qui va être égal à true et on va ici faire tout simplement un IF else donc on va dire if bright data on va cette fois-ci utiliser là encore chromium mais on va utiliser une autre méthode qui s'appelle Connect over CDP et on va utiliser donc cette chaîne de caractère ici qui va nous permettre de nous connecter à travers ce web socket si on souhaite ne pas utiliser bright data et bien on va tout simplement utiliser ici le chromium. launch qu'on avait dans les parties précédentes et là je vais bien m'assurer de mettre browser ici pour récupérer dans un cas comme dans l'autre le navigateur dans cette variable browser donc normalement on a tout qui est correctement configuré et on va pouvoir tester ça en lançant notre script avec bright data qui est égal à true ici on va rentrer dans cette structure conditionnelle et lancer le navigateur donc je vais mettre un point de debug ici en fait je vais plutôt le mettre ici sur le if pour vérifier qu'on rentre bien à l'intérieur de cette structure conditionnelle et je relance mon script en mode debug donc on va s'arrêter ici on continue avec le stepover et on voit qu'on rentre bien à l'intérieur de cette structure conditionnelle on va continuer et on arrive bien normalement ici à la page donc je vais continuer page on va aller jusqu'au goto et je vais m'arrêter ici sur le page.get by roll et ce qu'on va faire c'est qu'on va revenir donc si je remets le pycharm à gauche on va revenir ici et vous allez voir qu'on a un outil très pratique qui est ici avec le chrome dev tool debugger qui nous permet d'afficher le scrapping browser pour avoir un rendu visuel de ce qu'on est en train de faire avec notre code donc je vais cliquer ici et là si tout fonctionne bien vous allez avoir une URL sur laquelle vous pouvez cliquer si votre scrapping browser n'est pas actif vous n'aurez rien d'affiché ici mais là comme on a lancé notre script il est actif on est avec le point de débug arrêté à cette partie donc pour l'instant il est actif et il ne fait rien il attend nos instructions et donc on va cliquer ici ça va ouvrir un nouvel onglet et dans cet onglet et bien on va tout simplement retrouver un navigateur avec la page Airbnb qui s'affiche et à droite les outils de dbug donc les outils classiques qu'on retrouve dans n'importe quel navigateur qui nous permettent d'avoir accès au code HTML de l'inspecter comme on le ferait dans n'importe quel navigateur ici avec la petite icône qui nous permet de voir les boutons les différentes cartes HTML et cetera donc ça ça va être très pratique pour vérifier ce qui se passe quand on utilise notre scrapping browser là je vais pouvoir continuer et faire un stepover pour cliquer sur le bouton et vous allez voir que ça va bien se mettre à jour et qu'on va cliquer ici dans notre browser sur le bouton donc là vous voyez que le bouton a bien disparu puisqueque l'action a été exécutée et je peux continuer comme ça donc on va continuer jusqu'au break pour vérifier qu'on va bien naviguer à travers chaque page donc je mets un point d'arrêt ici sur le break je clique sur resume et on va pouvoir vérifier en revenant sur notre navigateur qu'on va bien passer à travers chaque page donc là vous voyez qu'on navigue à la 2è page ensuite on va passer à la 3è page et cetera jusqu'à arriver sur la page numéro 15 donc la dernière page et le script va s'arrêter à cette page puisqu'il y en aura plus après et vous voyez qu'on a un scrapping qui est un peu plus lent que ce qu'on avait en local mais c'est logique puisque briy data va constamment monitorer les performances du Site pour s'assurer que vous ne faites pas un scrapping trop agressif et que ça reste justement un scrapping éthique donc c'est un des avantages en fait de cette solution c'est que vous pouvez être assuré comme ça que vous aurez le moins de blocage possible et dans le cas où vous avez des sites assez agressifs qui bloquent très rapidement et bien le navigateur va automatiquement passer sur un autre proxy donc un autre ordinateur qui ne sera pas bloqué et comme ça vous pourrez continuer le scrapping donc cette option est très intéressante si vous voulez être assuré de ne jamais être bloqué ou en tout cas le moins possible on aura jamais quelque chose à 100 % fonctionnel mais vous pourrez passer comme ça à des taux de succès qui vont être grandement améliorés avec cette solution et donc comme vous le voyez maintenant donc on continue sur les pages je vais pas aller jusqu'au bout on va s'arrêter ici donc je vais arrêter mon script et vous allez voir comme ça en arrêtant le script que cette table devient inactive donc on n plus d'activité ici et si je reviens sur bride Atab vous voyez que cette fois-ci il ne peut plus trouver de session donc quand je clique sur Chrome death tool debugger ici on a plus de lien pour accéder à la session et c'est normal puisqu'elle n'est plus active donc vous voyez c'est très pratique ça on va pouvoir comme ça passer juste avec ce petit paramètre ici soit en local soit avec le scrapping browser de Bright data donc pour nos test pour tout ce qu'on fait en local comme ça pour tester le script pour vérifier que tout fonctionne on va rester en local et après quand on passe en produ uction pour s'assurer que tout fonctionne le mieux possible et bien on peut juste changer ce paramètre pour s'assurer de passer par le scrapping browser et c'est vraiment la seule chose que vous aurez besoin de changer tout le reste va être similaire puisque ça va être de la logique au niveau du code HTML donc ça ça ne changera pas que vous passiez par votre navigateur local ou par le scrapping browser ça sera exactement le même code HTML qui sera retourné donc vous n'aurez rien besoin de changer d'autre que cette petite variable ici qui sera à True ou à false dans cette partie on va rajouter une petite fonction qui va nous permettre d'ouvrir automatiquement la fenêtre d'inspection du débuger de Bright data puisque comme on l'a vu dans la partie précédente c'est possible de le faire directement via l'interface donc en passant ici par chrome dev tool debuggers ce qui va ouvrir ici une petite fenêtre avec un lien sur lequel on peut cliquer mais ce n'est pas très pratique à chaque fois il faudrait qu'on arrête le script qu'on aille sur l'interface ici pour ouvrir le débuger donc il y a un moyen de faire plus simple que vous allez retrouver dans la documentation de Bright data vous pouvez le faire donc comme c'est indiqué ici manuellement avec le panneau de contrôle comme on l'a fait mais vous pouvez aussi le faire via un script donc vous avez le code ici donc on va le copier et on va juste enlever les await pour les mettre dans notre script puisque nous on utilise une façon de faire qui est synchrone donc je vais revenir ici on va créer une fonction qui va nous permettre d'activer ou non l'ouverture de ce debug view donc je vais faire une fonction que je vais appeler par exemple open debug View et on va lui passer la page puisque on a besoin de ça pour créer un nouveau contexte donc je colle tout le code ici on va mettre une doc string ici pour dire open the bright data debug View et on va faire quelques modifications ici on va enlever le browser.ne page puisqu'on aura déjà une page nous ce qu'on veut c'est juste ouvrir cette page dans le debug view mais non pas en créer une et on va enlever tous les await ici donc je vais sélectionner les trois await et les enlever et le reste du code on va le laisser comme ça on va enlever le print et ce qu'on va faire à la fin c'est utiliser une bibliothèque qui s'appelle web browser qui est disponible dans la lib librairie standard donc on va importer web browser et web browser ça va permettre d'ouvrir le navigateur par défaut que vous utilisez sur votre système d'exploitation donc je vais faire webbrowser.open et on va ouvrir cette URL qui est dans inspect URL donc dans la variable qu'on défin juste au-dessus ici et ce qu'on va faire c'est donc rajouter la possibilité en passant un paramètre à notre fonction run d'ouvrir ou non le navigateur donc on a déjà le paramètre headless ici qui par défaut est tu donc on va rajouter un paramètre ici qu'on va appeler headless par défaut on va le mettre à false et je vais passer cette valeur ici à la place de True donc ça c'est dans le cas où on ne va pas utiliser bright data on veut spécifier si oui ou non on veut ouvrir le navigateur local en headless ou non et pour bright data on va le faire à un autre endroit puisque là on fait juste la connexion et la décision d'ouvrir le debug view va être avec cette fonction ici qu'on va appeler ou non donc on va aller plus loin ici et après la création de la page donc ici quand on fait un page browser new page on va décider si on souhaite oui ou non ou ouvrir la vue de debug donc les deux conditions à réunir c'est qu'on souhaite utiliser bright data donc ça c'est le paramètre qu'on a ici donc si ce paramètre est à true et que on a également le paramètre headless qui est at true donc là on va mettre and not headless puisque headless ça voudrait dire qu'on souhaiterait ne pas avoir de navigateur donc il faut inverser cette condition c'est un petit peu confus peut-être mais headless ici quand on met headless at ça veut dire qu'on souhaite ne pas ouvrir le navigateur donc nous ce qu'on veut c'est si on choisit d'utiliser bright data et de ne pas avoir le mode head l donc le mode sans navigateur alors ça veut dire qu'on souhaite utiliser cette debug view donc là on va tout simplement appeler debug view avec la page qu'on a récupéré à la ligne juste au-dessus donc voilà normalement ça devrait suffire et on va pouvoir spécifier ce paramètre ici dans l'appel de la fonction donc on va dire headless égal à false puisque on souhaite afficher dans ce cas-ci le navigateur donc je vais mettre bright data ég à true headless ég à false et là normalement ça devrait quand on lance le script ouvrir la debug view de Bright data automatiquement donc je vais tester tout ça je clique sur bouton pour lancer le script on se connecte au scrapping browser on va attendre un petit peu et là on a bien donc le navigateur par défaut sur mon ordinateur qui dans ce cas-ci et le navigateur arc qui m'ouvre une nouvelle fenêtre avec automatiquement la debug view de Bright data donc on voit ici qu'on a le CDN bright data.com et on va voir donc le script qui va se dérouler avec le code HTML à droite et le défilement des pages normalement qui va s'effectuer puisque c'est ce que fait notre script dans ce cas-ci donc on appuie bien sur le bouton Continuer et on va naviguer voilà on descend la p on navigue et cetera et cetera donc ça fonctionne parfaitement on a bien cette vue qui s'ouvre on va tester les autres scénarios on va mettre bright data égal à false on va laisser le headless AFF et là normalement on va passer sur notre navigateur voilà en local qui est beaucoup plus rapide comme vous le voyez puisque là on fait tout au niveau de notre ordinateur donc je vais arrêter le script on va mettre le headless cette fois-ci à TR pour vérifier si on peut bien faire la même chose sans bright data pour l'instant et avec le navigateur qui n'est pas affiché donc on va tester tous les cas de figure donc le deuxième cas de figure voilà là vous voyez que là dans ce cas-ci le navigateur ne s'ouvre pas mais on a bien la navigation qui se fait et dernier cas de figure on va tester avec bright data qui est égal atu et le headless atu donc là ça devrait être un petit peu plus lent on ne devrait pas voir non plus d'ouverture de quoi que ce soit et on va juste naviguer à travers les pages donc je vais attendre quelques secondes que ça se connecte et on devrait voir apparaître ici dans l'output de notre script la navigation vers les pages dans quelques instants et voilà on a donc la navigation à la première page la navigation à la deuxème page et cetera donc on a bien tous les cas de figure qui nous intéresse on peut faire le scrapping en local si on le souhaite pour nos tests ensuite passer par le scrapping browser de Bright data quand on veut passer en production on peut choisir aussi d'afficher ou non la debug view si on passe par bright data ou directement le navigateur quand on passe en local et ça nous permet ainsi d'avoir un contrôle très précis sur ce qu'on utilise à l'intérieur de notre script de scrapping dans cette partie on va terminer la logique principale de notre script en rajoutant une petite modification qui va nous permettre de ne pas charger les images notamment dans le cas de l'utilisation avec le scrapping browser de Bright data puisque forcément quand vous utilisez ce genre de service ça coûte de l'argent et ce qui va vous faire dépenser plus ou moins d'argent c'est le nombre de données qui vont être envoyées donc le problème c'est que les images notamment ça consomme pas mal de bandes passantes alors qu'on en a pas vraiment besoin bien sûr ça dépend de votre cas de figure si vous voulez récupérer les images des locations sur Airbnb ne faites pas à ça puisque vous allez les bloquer avant qu'elles arrivent vers vous dans notre cas on veut juste récupérer le prix donc des informations de texte et on n' pas besoin des images on va donc rajouter dans notre script une fonction qui va intercepter les requêtes et annuler les requêtes qui vont être de type Image donc là encore c'est une technique que vous retrouver dans la documentation de Bright data on voit ici du code avec playwght dans ce cas-ci il n'est pas en python il est en Javascript mais on va voir que c'est assez simple de le convertir dans le contexte de l'utilisation de playwright avec Python donc je vais retourner dans mon script et on va coller ce code que vous retrouverez dans les sources de la formation donc ce que va faire cette fonction c'est tout simplement vérifier pour chaque requête le type de la ressource qui est associé à la requête donc si on a une requête de type Image on va faire un rot. abort donc une annulation de cette requête et sinon on va continuer avec le chemin et on va donc apporter des modifications à notre fonction run ici pour modifier la route par défaut de nos requêtes donc pour ça on va faire page.roout comme ceci et on va dire qu'on souhaite cibler toutes les requêtes pour on met deux astérisques un slash et une autre astérisque ça ça va signifier qu'on souhaite intercepter toutes les requêtes qui vont passer à travers notre page et on va ensuite donner en deuxième argument la fonction qu'on souhaite appeler à chaque fois qu'on va effectuer une requête donc c'est-à-dire que pour toutes les requêtes de notre page on va passer par cette fonction et si on a une requête de type image avec donc le ressource type ici qui est égale à image et bien on va annuler cette requête donc on va pouvoir voir très concrètement ce que ça donne on n même pas obligé dans ce cas-ci là de passer par bright data on peut voir également avec playwright en local donc là je vais aller à la fin de mon script je vais mettre bright data à false et on va mettre le headless à false également pour qu'on puisse voir quelque chose donc je vais mettre un point de debug par exemple ici avant qu'on passe à la navigation avec les différentes pages donc je mets un point de débug ici je lance le script et là vous allez voir qu'on va ouvrir la page et que cette fois-ci on a aucune des images qui n'est chargé on a juste l'image de Google Maps ici puisque ce n'est pas une image fixe ici on a des données un peu plus complexes mais vous voyez que toutes les images sur le reste du site ou quasiment on a le logo ici qui doit être probablement autre chose peut-être du vectoriel mais toutes les images ici sont bien bloquées et donc ça va grandement limiter la bande passante et accélérer le scrapping et aussi réduire votre facture lorsque vous passerez par le scrapping browser de Bright data donc voilà pour cette dernière modification une autre chose que vous pouvez faire également que je vous conseille c'est de modifier le Time Out par défaut là encore on peut le faire directement au niveau de notre script pour ça il faut créer un nouveau contexte donc on peut faire browser.ne context et sur ce contexte on peut changer le timeout donc en faisant context.7 default alors il faut que je le récupère par contre avant dans une variable bien entendue donc contexte ici et on va faire contexte. set default timeout comme ceci par défaut si je me trompe pas le Time Out est de 30 secondes si vous êtes dans un endroit où il y a une connexion qui est assez lente et bien je vous conseille d'augmenter cette valeur vous pouvez passer par exemple à 60000 misees donc 60 secondes ça va permettre de ne pas retourner une erreur puisque au-delà de 30 secondes donc au-delà du timeout par défaut et bien playright va considérer que la requête a échoué alors que vous êtes peut-être juste dans une situation où votre réseau n'est pas très performant et c'est juste que la requête prend du temps à effectuer donc voilà une dernière chose que vous pouvez faire si vous souhaitez modifier le timeout et la dernière chose à ne pas oublier bien sûr ici c'est d'utiliser ce nouveau contexte à la place du browser pour créer notre page et ensuite ça ne change rien pour le reste on passe par notre page pour modifier les requêtes sur l'interception ici des images et et ensuite pour naviguer à l'intérieur de notre site dans cette partie on va améliorer notre script en faisant exactement les étapes que l'on ferait si on était un humain puisque pour l'instant qu'est-ce qu'on fait et bien on se rend directement sur une URL très spécifique qui est longue comme le bras et qui est d'ailleurs beaucoup trop longue pour mon IDE et ce qu'on va faire c'est vouloir partir directement depuis la page principale de Airbnb et faire exactement les mêmes étapes que celles qu'on ferait si on cherche une location pour faire ça on va utiliser le débuger de playwright que je peux avoir en revenant sur ma configuration script debug donc rappelez-vous c'est cette configuration qui contient la variable d'environnement pwdbug qui est égale à 1 puisque je vais pouvoir faire donc ces opérations directement dans le navigateur qui va être ouvert et voir ensuite le code que j'ai besoin d'utiliser pour me rendre jusqu'à la page qui m'intéresse donc pour l'URL je vais prendre tout ce qui se trouve après le slash ici et juste garder l'URL de base de Airbnb et pour ne pas également trop polluer le script de debug je vais commenter cette ligne ici puisque vous allez voir que si je le lance en fait je vais vous montrer ce que ça donne donc là on va encore être sans bright data avec le headless qui va être égal à false puisqu'on veut voir le navigateur donc je vais lancer mon script de debug et vous allez voir ce que ça donne si je laisse en fait l'interception des routes c'est que à chaque fois que je vais faire une opération ici vous voyez qu'on a tout le détail des opérations donc des requêtes qui sont effectuées qui est affiché donc ça va grandement polluer ici le l'output du script et moi ça m'intéresse N- pas et dans ce cas-ci je veux vraiment avoir les images pour voir concrètement ce que je fais donc je vais stopper mon script ici et on va commenter cette ligne donc la ligne qui intercepte la route et qui appelle cette fonction donc là si je relance le script vous allez voir que c'est beaucoup plus clair je peux continuer avec le stepover ici et là on aura juste une indication ici de qu'est-ce qu'on va faire et on pourrait y voir beaucoup plus clair donc là je vais me mettre en mode record et je vais effectuer les actions que je ferais comme si j'étais un humain donc vraiment je clique là par exemple sur continuer sans accepter là on a explorer les logements donc je peux soit choisir de cliquer sur la croix soit cliquer sur ce bouton je vais cliquer sur explorer les logement voilà et ensuite moi ce qui va m'intéresser c'est de chercher une destination alors faites bien attention quand même à chaque fois que vous cliquez sur quelque chose là vous voyez je peux cliquer sur cette boîte ici qui a un test ID QA explore header ou sinon j'ai la destination directement qui a elle aussi un test ID donc on voit que le code qui m'est proposé c'est get by test ID les test id je vous en avais déjà parlé c'est assez intéressant puisque c'est des données qui généralement ne changent pas puisque c'est des données qui sont utilisées par Airbnb eux-mêm pour tester leur script pour faire des tests d'automatisation et donc on est assez sûr que ces données ne vont pas bouger puisque sinon ça casserait tout leur script d'automatisation contrairement à des classes où là ça peut être un petit peu différent des classes ou des ID en fonction de ce qu'on utilise pour faire le front-end ça peut changer assez régulièrement donc là moi je vais cliquer ici au plus proche de ce que je souhaite donc sur le test ID ici eu structur search input field query et on va rentrer le nom de ce qu'on souhaite chercher donc je vais mettre Rio de genero de nouveau et là de la même façon vous voyez on peut cliquer un peu plus en haut donc on a le option Z0 locator div et n nth1 donc ça ça veut dire que ça va prendre le premier élément euh si je vais là on va avoir le option zéro avec le get by text donc là encore c'est peut-être un peu trop précis puisque le texte va probablement changer en fonction de la destination donc je vais essayer de voir si je peux pas avoir un truc un peu plus générique et là effectivement j'ai quelque chose qui me plaît bien le test ID qui est tout simplement option z0ro si je vais là je vais avoir option- 1 option- 2 et cetera donc ça ça me plaît bien le test ID option z0ro c'est très générique et je vais pouvoir l'utiliser peu importe la destination que j'ai donc je clique là-dessus ensuite on me demande quand est-ce que je souhaite arriver dans mon cas je vais vouloir chercher sur un mois donc je vais cliquer sur moi ici et là encore on a différentes options donc je vais pouvoir cliquer par exemple sur les petits points donc là on voit qu'on a un span avec là encore le nth qui veut dire qu'il va aller chercher un nè élément donc là si on clique là-dessus on va aller sur le mois par exemple 11 moi ce qui va m'intéresser c'est juste un mois je veux pas rester plus longtemps donc là on voit qu'on a un euh voilà on a alors pour le voilà donc là ça a changé on est sur un get by label si je clique là on est avec le 6 le 7 le 8 si je clique sur celui-là et que je reviens là alors là on a un locator avec un nom de classe qui est très spécifique qui semble être le nom de classe pour le premier mois et les autres après on va y aller avec un nth donc moi comme c'est juste un mois qui m'intéresse je clique ici et ça devrait suffire et là vous voyez que tout ce qu'on fait c'est reporté ici en passant on a donc tous les différents tests qu'on a fait donc il va falloir faire le tri un petit peu là-dedans après puisque là on voit qu'on a le clic sur le mois 11 sur le mois 6 et cetera avec le nth child 6 qui était je crois le le deuxème mois voilà donc nous après il faudra faire un petit peu le TR là-dedans et tester notre script bien entendu donc dernière étape ici je vais cliquer sur le nombre de voyageurs et je vais choisir d'ajouter ajouter un voyageur donc là j'ai cliqué sur la boîte qui est un test ID encore et là de nouveau on a un test ID qui me plaît bien donc avec un stepper adult increase button là encore c'est assez spécifique donc je dis que je suis tout seul et je finis avec là encore un autre test ID pour lancer la recherche donc ça me semble pas mal et là on a toutes les étapes qui sont affichées ici de ce qu'on vient de faire et on va pouvoir faire le tri à l'intérieur de tout ça pour faire tout ça de nouveau avec notre script donc je vais agrandir un petit peu la fenêtre ici et je vais sélectionner tout ça ici et faire un copier de ce texte je vais arrêter mon script et on va aller le copier directement à l'endroit où on avait le script qui faisait tout simplement passer d'une page à l'autre donc je vais enlever tout ça ici on a bien remis ici le bouton continuer sans accepter sur lequel on clique pour enlever le bandeau des cookies et ensuite là on a pas mal de petites choses alors on a le clic sur le search input ensuite on a le Field donc là je vais mettre Rio de Jero au complet le clique sur la première option le clique sur l'onglet avec le choix des dates donc moi dans ce cas-ci j'avais choisi une date d'un mois et si je me souviens bien on avait ici la classe spécifique très spécifique qui correspondait au premier mois donc on va enlever ici le span child celui-là et celui-là aussi et on va garder uniquement le clic pour spécifier qu'on souhaite rester uniquement un mois dans les endroits donc on prend le premier et on clique dessus et ensuite on clique donc sur le search input avec le les guest donc le nombre d'invités qu'on souhaite avoir donc là dans ce cas-ci jeais j'ai mis qu'une seule personne et ensuite le clic sur le search Button qui permet de lancer la recherche donc normalement c'est tout bon je vais mettre un point de débug à la fin sur le browser close ici et on va relancer le script mais cette fois-ci sans le debug donc on va faire script without Debug et je vais le relancer en mode debug pour m'arrêter sur le point de debug ici mais sans ouvrir le dbug de playwright donc il y a plein debug dans tous les sens désolé c'est peut-être un petit peu confus mais c'est bien donc le script sans debug de playwright que je lance en mode debug de pycharm donc on va voir ce que ça donne on a bien le clic sur les deux boutons le clic ensuite et tout semble assez bon tout est très rapide et là on voit qu'on est bien donc sur la page de Rio de Jero du 1er février au 1er mars pour un voyageur et on a la liste de tous les logements ici donc ça semble bien fonctionner je vais arrêter mon script ici et enlever le point de débug et je vais juste récupérer ici le html donc je vais faire une variable HTML content qui va être égal à page.content qui est le contenu de la page et je vais tout simplement faire un beautiful soup donc je crois que je l'avais déjà importé alors non pas dans ce script donc on va faire from BS4 pas bs5 BS4 import beautiful soup et ça c'est juste pour faire un petit pretttify pour voir ce que ça nous donne donc je vais faire un beautiful soup avec le HTML content donc HTML content comme ça on va mettre le html parser et on va faire un print de soup. pretttify ce qui va me permettre d'avoir le code HTML affiché d'une façon un peu plus sympathique avec ce pratify ici qui va garder les tabulations les retours à la ligne et cetera donc je relance tout ça on va mettre le headless en true cette fois-ci toujours sans bright data pour le moment puisque on est juste sur notre ordi pour faire des tests et je relance tout ça sans le débug donc on a la connexion et ensuite on attend un petit peu et voilà on a bien tout le code HTML ici de la page qui est affichée donc tout fonctionne correctement on a bien la navigation jusqu'à la page qui nous intéresse avec dans ce cas-ci R de genero et on va voir par la suite comment on peut améliorer un petit peu notre script pour séparer tout ce qui est ici puisque là en fait un peu tout dans la même fonction donc on verra par la suite comment on peut améliorer ce script et permettre également de chercher différents endroits là on a mis Rio de genero directement ici dans le script bien sûr on va vouloir améliorer notre script pour pouvoir passer une ville différente à chaque fois en fonction de paramètre qu'on va mettre ailleurs que directement dans le script donc par exemple qu'on pourra envoyer en ligne de commande quand on lance notre script dans le terminal dans cette partie on va aller un peu plus loin avec playwri puisque on va avoir des difficultés supplémentaires par rapport à ce qu'on a fait précédemment puisque tous les éléments sur lesquels on a cliqué jusqu'à présent avaient des éléments test ID bien identifié qui nous permettait de ne pas avoir plusieurs éléments sur la page qui soient ciblés avec notamment cette barre de recherche ici pour la destination la durée le nombre de voyageurs ou encore le bouton pour lancer la recherche là on va vouloir faire défiler les différents mois de l'année pour pouvoir comparer les prix en fonction du mois de l'année et pour ça on va donc utiliser cette barre ici avec le bouton Modifier qui là comme vous le voyez est déjà beaucoup moins spécifique puisque modifier c'est quelque chose d'assez générique et ensuite il va falloir cliquer sur des dates ici donc le 1 du calendrier le bouton appliqué qui lui contient peut-être un test ID donc ça sera peut-être plus facile sur cette partie-là mais voilà là on va rentrer dans le vif du sujet avec un peu plus de défi et une utilisation un peu plus spécifique de playwright que l'on va devoir faire sans forcément passer par le debug View qui ne va pas vous allez voir nous être d'une grande utilité dans ce cas-ci donc ce que je vais faire déjà pour mes tests c'est prendre cette url au complet et on va enlever tout ce qu'on fait ici pour se rendre sur cette page puisque là on va vouloir aller un peu plus rapidement donc je vais commenter toutes ces lignes ici et je vais juste garder le continuer sans accepter ici pour enlever le bandeau des cookies et à la place de cette url je vais mettre donc l'URL complète qui nous amène vers la page sur laquelle on va pouvoir faire nos tests je vais commenter également cette ligne même si comme je redéfin l'URL ici ça n'a pas tellement d'importance de la commenter ou non mais pour que ce soit bien clair je vais quand même le faire donc là on va mettre un point de débug ici pour arrêter le script comme je vous ai dit je ne vais pas lancer le script en débug ici je vais le faire une première fois quand même pour vous montrer ce que ça donne et voir ce qu'on peut récupérer avec la debug view mais là encore pour avoir préparé la formation je peux vous garantir que ça ne va pas donner grand-chose donc je vais continuer avec le stepover ici pour aller sur l'URL on va accepter avec le continuer sans accepter donc là on se retrouve bien à notre point de dbug et si je reviens ici sur le playwright inspector je vais pouvoir faire un record ou directement cliquer sur le bouton ici ici pour vérifier les locators et là vous voyez le problème qu'on a c'est que on a des choses beaucoup plus spécifiques là notamment on a un get by roll button mais le nom c'est arrivé/dpart 1er février-1 et cetera donc vous voyez c'est pas très pratique ici parce que ça veut dire que il faudrait vérifier à quel mois on est si on est en février prendre les quatre premières lettres du mois et cetera donc vous voyez que c'est assez pénible pareil si on regarde ici vous voyez là il y a voyageur un voyageur donc ça devient des chaînes de caractères très spécifiques que inspecteur de playwright nous spécifie ici et nous ça ne va pas nous être d'une grande aide donc nous ce qu'on va faire à la place c'est plutôt faire un inspect donc en faisant un clic droit inspect pour voir s'il y a pas des choses un peu plus spécifiques qu'on pourrait récupérer donc si je clique ici on va aller voir un peu plus par là si on n'a pas des Data test ID par exemple ici vous voyez que sur le div qui contient toute la barre de recherche on a un Data test ID little search alors je vais grossir un petit peu pour que vous puissiez voir un peu plus le code HTML donc là voilà data test ID little search ça ça me PLA PL un petit peu plus puisqu'on va pouvoir probablement cibler ces éléments et ensuite on voit qu'on a différents boutons donc ces boutons peut-être qu'ils ont également des Data test ID mais je regarde et ça ne semble pas être le cas on a des classes ici qui sont longues comme le bras encore une fois qui ne vont pas beaucoup nous aider mais on voit bien les boutons ici donc le premier bouton qui constitue la destination le deuxième bouton pour la date donc c'est celui qui va nous intéresser mais l'intérêt ici c'est que et bien on va pouvoir cibler des boutons spécifiques avec des fonctionnalités un petit peu plus avancées de playwright donc on va voir ça tout de suite je vais fermer le script je vais arrêter mon script ici et on va lancer cette fois-ci le script sans le mode Debug et à la place de faire du debug dans la petite vue de l'inspecteur playwri on va le faire directement dans piecharm donc je laisse mon point dbug ici je relance tout ça en mode debug bien entendu de pcharm pour qu'il s'arrête ici avant le browser.close et on va faire un petit peu de ménage alors là je crois que voilà j'étais en headless true donc je vais l'enlever le headless true ne change rien bien sûr quand vous êtes en mode debug de playri puisque il va quand même afficher la fenêtre même si si on le lance en headless ici donc le headless qu'on avait à l'intérieur ici de notre script avec Chromium launch quand on passe en mode debug avec la variable d'environnement et bien ça va prendre effet plutôt que le headless qu'on a spécifié quand on lance chromium donc là je m'assure de bien mettre headless à false puisque là on lance le script sans Debug et je relance avec le dbug de pcharm cette fois-ci donc on a bien notre fenêtre ici et le débuger qui s'arrête je vais faire un petit peu de place pour qu'on y voit plus clair et pour qu'on puisse utiliser donc cette partie ici evaluate expression qui va nous permettre d'évaluer des expressions notre script et de vérifier que ça fonctionne correctement donc là si on se souvient bien je vais refaire un clic droit inspect pour retrouver le Data test ID que j'avais sur cette barre donc qui si je me souviens bien est ici voilà donc c'est little search tout simplement donc je vais faire un premier essai pour vérifier si je peux cliquer sur cette barre et ce que je vais faire donc je vais agrandir un petit peu ici pour qu'on y voit bien clair sur toute une ligne je vais faire un get by test ID et on va essayer de cibler le Little search et ça nous retourne bien quelque chose et on va essayer de cliquer dessus donc je fais un point clic tout simplement et là vous voyez que ça clique correctement sur cette barre et que ça nous affiche bien l'élément qu'on souhaite ici avec l'affichage des mois donc ensuite on va vouloir cliquer sur le bouton Modifier donc cette ligne ici elle fonctionne on va la garder sous le coude et on va la mettre dans notre script pour pouvoir la réutiliser plus tard et ensuite ce que je vais faire c'est probablement un get by roll qui va me permettre de sélectionner des balises HTML en fonction de leur type donc get by roll ça va nous permettre de sélectionner par exemple tous les boutons donc si je fais ça là on va avoir plusieurs locators si j'affiche le résul vous voyez qu'on peut prendre le premier le dernier et on peut en cibler un spécifiquement aussi avec nth si on veut prendre le premier le deuxè le 3è et cetera nous ce qui va nous intéresser ici c'est de faire un filtre pour récupérer uniquement les boutons qui ont le texte modifié donc pour ça on pourrait faire un get by text si je me trompe pas ou on peut faire aussi un filtre donc avec point filter et spécifier certaines choses comme par exemple le texte avec has text qui est un paramètre de filtre donc je peux dire par exemple récupère-moi dans tous les éléments qui ont un rôle bouton donc dans tous les boutons de la page celui qui a le texte modifié donc bien sûr enchaîne de caractère ici et je vais mettre un clic à la fin pour vérifier si ça fonctionne et que ça clique bien sur le bouton modifié et c'est bien le cas ici on arrive à cliquer et à cibler ce bouton spécifique donc là encore je garde cette ligne pour plus tard et ensuite on va vérifier là dans ce cas-ci à quoi correspond le 1 donc je refais un clic droit inspect et on va aller voir dans le html si on a quelque chose d'exploitable ici donc là on est avec D TD donc un table FL TR TD on voit que pour les premiers jours du mois ici comme il n'y a pas de jours en fait pour le lundi mardi mercredi jeudi on a des cases vides et ensuite on a un TD avec un rôle bouton et le aralable est assez explicite un vendredi donc ça ça va pas être très utile euh et ensuite qu'est-ce qu'on a ici on a par contre un test ID un autre test ID qui lui est un peu plus sympathique parce que on a quelque chose d'assez générique donc calendard day avec tout simplement une date formatée donc ça ça me plaît beaucoup puisque on va pouvoir probablement l'utiliser et juste juste incrémenter le numéro du mois ici donc passer de 03 à 04 à 05 et cetera et cibler ainsi ce bouton donc je vais vérifier qu'on arrive bien à cibler ce bouton avec le Data test ID ici donc je copie le Data test ID je me refais un petit peu de place pour y voir plus clair ici et donc on va faire page.get by test ID de nouveau et on va mettre le test ID avec la date donc calendar Day 0103224 et je vais refaire un point clic pour vérifier que ça fonctionne donc là vous voyez que on n pas réussi à a récupérer le bouton donc qu'est-ce qu'il me dit là vous voyez il me dit qu'en fait il y a eu deux éléments qui ont été retournés avec ce data test ID donc là vous voyez on a le premier élément et on a le deuxième élément donc ça veut dire qu'on a deux éléments qui sont retournés alors c'est un petit peu bizarre je sais pas il doit y avoir d'autres bouton sur la page peut-être qu'ils sont deux fois pour des raisons de ux de Ui peut-être que le bouton est dupliqué donc moi ce que je vais faire c'est tout simplement récupérer le premier en espérant que ça fonctionne donc je vais faire un point first pour récupérer le premier des deux et faire un point clic sur ce premier élément pour voir si ça fonctionne et ça semble fonctionner également puisque le bouton est donc bien sélectionné et ensuite il ne reste plus que le appliquer donc lui je pense que ça va être assez facile on va faire un inspect et je pense qu'on va avoir un Data test ID dessus donc je vais cibler ce bouton Appliquer et qu'est-ce qu'on a ici donc non bizarrement on n pas de test ID donc là dans ce cas-ci on va probablement devoir juste cibler là encore un bouton avec appliqué qui est inscrit dessus donc je vais me refaire un petit peu de place pour retrouver mon debucker de P charm et ici on va tout simplement faire un page.get by roll alors il y a plein de façons de le faire on peut aussi mettre une expression directement ici en faisant has text directement à l'intérieur de ce get by roll donc on peut récupérer les boutons qui ont le texte appliqué je valide avec entrée et là ça ne fonctionne pas oui puisque là ce n'est pas un get by roll ça va être un niveau plus élevé on va utiliser en fait locator donc locator ça nous permet de donner des indications que ce soit en CSS avec un xpat ou plein d'autres choses donc ça nous donne un niveau de précision un peu plus spécifique puisque le get by rle va directement cibler des éléments comme les boutons les liens les images et cetera le test ID va cibler spécifiquement l'attribut test ID le locator c'est en fait ce qui est utilisé en arrière-plan par playriigh quand vous utilisez get by roll get by taste ID et cetera d'ailleurs on peut peut-être aller voir le code source de ces éléments et effectivement vous voyez le get by test ID ici tout ce qu'il fait c'est tout simplement retourner un locator spécifique donc là on peut nous utiliser ce locator très spécifique également comme on l'a vu précédemment on pourrait faire un get by roll et ensuite un filter moi je vais essayer directement ici avec le has text c'est juste pour vous montrer différentes façons de faire et vous montrer la flexibilité de playwright donc j'essae avec ça je valide avec entrée donc là vous voyez qu'on a de nouveaux plusieurs éléments je pense query selector all donc ça c'est du beautiful soup pour ceux qui connaissent c'est ce qui est utilisé je pense en arrière-plan aussi et là je pense que c'est le has text qui n'est pas bon donc si je me trompe pas c'est has- texte comme comme ceci on va finir par y arriver voilà j'ai bien trouvé c'est ça finalement donc has- texte je valide avec entrée et là on a bien cliqué pour appliquer donc normalement on a tout ce qu'il faut ici je vais prendre cette ligne de code également et la copier ici donc on a bien le clic sur le Little search qui va cliquer sur la barre en général le clique sur le bouton qui a le texte modifié donc là comme vous le voyez je vais faire un petit peu de place pour qu'on voit tout sur la même ligne on a ici un get by roll qui nous permet de cibler spécifiquement les boutons et ensuite un filtre avec le has text et là une autre façon de faire avec le lock en ciblant directement les boutons également qui ont le texte appliqué donc vous voyez différentes façons de faire la même chose avec playwright donc on va tester tout ça on va se rendre sur notre page là je pense que alors on a juste pas ciblé on a oublié de mettre le la ligne qui va cibler le premier élément donc ça c'était un Data test ID donc je vais refaire un inspect là-dessus je vais vérifier et là on avait voilà le calendar day donc on va tester on va prendre le lien qu'on avait qui je pense donc je me souviens plus exactement à quel mois en comm commc je vais prendre tout ça ici je vais aller hop le remettre dans la barre donc là on était je crois 1er février au 1er mars donc là ça veut dire que sur le mois ici on va être au 1ier donc 1er février nous on veut passer au 1er mars donc 0103 donc je vais tester ça ici on avait page get by test ID qui était égal donc à calendar Day et là on était sur le 1er mars donc on va faire ça et on va faire un point clic et on va vérifier si avec tout ça on arrive à modifier le mois donc là je vais revenir je pense en mode dbug puisqu'on va faire du pas à pas pour voir si tout fonctionne bien je pourrais également le faire directement depuis P charms à vous de voir là on a du contrôle sur ce qu'on souhaite faire soit on le fait directement depuis pcharm soit avec le petit debuger de playwright je vais le faire avec pcharm en fait donc je vais faire un script without debug je vais arrêter celui-là relancer tout ça on va s'arrêter ici et je vais mettre ça sur la droite et ça un petit peu plus ici pour qu'on y voit un peu plus clair donc là on continue je clique hop on clique bien sur cette barre au milieu mil ensuite on clique sur le bouton Modifier c'est parfait ça ouvre le sélectionneur de date on va récupérer le 1er mars et là on a une petite erreur je pense alors oui effectivement c'est qu'on a oublié de récupérer le premier élément puisque si vous vous souvenez bien là voilà j'ai oublié de le mettre on récupérait le premier élément puisqu'on avait deux éléments avec ce test ID sur la page donc on récupère le premier sur lequel on clique donc je vais relancer tout ça pour vérifier hop je mets ça sur le côté je mets mon pcharm ici et on relance tout ça donc je continue je clique sur la barre je clique sur le bouton Modifier je clique sur le premier élément et là on semble avoir encore un petit problème donc je vais continuer on a encore une erreur donc là qu'est-ce que c'est un Time Out alors c'est bizarre un Time Out dans ce cas-ci c'est un peu surprenant je vais essayer voir si c'est pas juste une erreur de de connexion un problème de connexion donc je vais me rendre jusqu'au locator ici jusqu'après donc je vais enlever ce point ici je vais aller jusqu'au locator je vais arrêter le script et le lancé et on va voir si ça fonctionne hop donc on clique on clique et là non ça ne semble pas fonctionner donc on n arrive pas à cliquer sur le test ID donc je retourne voir ici modifier on inspecte cet élément et là on a bien normalement donc data testad calendar et on a donc plusieurs éléments comme celui-ci donc je le sélectionne donc il est bien ici je vais vérifier en faisant un filtre donc on a bien deux sur deux voilà donc on a le premier le deuxième qui se trouve je ne sais où mais on en a bien un qui est ici voilà avec le calendar day test ID donc ça devrait être re bon on est sur un div donc qu'est-ce qui ne fonctionne pas ici on va en profiter pour faire un petit peu de débug pour voir ce qui peut ne pas fonctionner donc finalement je vais enlever mes points de debug et je vais relancer avec le debug de playright je le relance cette fois-ci donc sans le dbug de pycharm mais avec le debug de playwright et on va faire du step over pour vérifier si on peut récupérer cet élément avec le debuger de playright donc je continue là on clique bien sur cet élément on va bien cliquer sur le bouton et là donc c'est ici qu'on a un problème donc je vais utiliser mon petit sélecteur et je vais cliquer dessus et là vous voyez qu'on a donc un get by test ID qui ne me plaît pas beaucoup là on a voilà des dates là on a quelque chose de très précis donc voilà si je clique là-dessus moi ça me plaît pas beaucoup model container avec le 1 vendredi mars j'ai pas envie de devoir deviner ou calculer en fait quel est le le premier jour du mois de chaque mois plus la date ici en texte donc je vais euh je vais refaire un inspect là-dessus pour voir quand même euh je pense que je vais refaire un petit débug après donc je vais inspecter ici le 1 on est bien toujours avec notre data test ID avec le calender Day et qui doit apparaître donc deux fois si je me trompe pas alors on va vérifier s'il apparaît donc là il apparaît même trois fois alors ici on a un truc un petit peu bizarre première fois deuxième fois qu'il apparaît et troisème fois qu'il apparaît et là on a bien un div à l'inrireur d'un TD donc ça semble exactement le même dans les deux derniers cas sauf que celui-là ici je ne sais pas quoi il correspond là il ne me surligne rien et là on a bien le le 3 sur 3 qui correspond au bouton donc en fait plutôt qu'un first je pense que je vais tester avec un Last puisque là on récupère le premier élément mais vous voyez des fois il y en a deux des fois il y en a trois et finalement ça semble être le dernier plutôt qui correspond à celui qui nous intéresse donc je vais remettre un point de débug ici je le relance sans le debug de playwright juste avec le debug de pycharm pour voir si on arrive à se rendre jusque là donc là on clique on clique on clique et ça semble bon là on a réussi à cliquer sur le bouton donc je pense que c'était vraiment juste ça en fait c'est que je récupérais le premier qui semblait ne pas toujours être le bouton alors que le dernier ça semple être le bon et ensuite donc le bouton appliqué alors je vais continuer avec le script ici on continue avec le stepover là j'ai bien cliqué sur Appliquer et ensuite il ne reste plus que le bouton Rechercher qui si je me souviens bien voilà on l'a ici donc je vais le remettre et on va le mettre à la fin donc on va lancer notre script quelques fois on va faire une méthode un petit peu empirique on va relancer notre script plusieurs fois pour vérifier qu'avec le Last ici on arrive toujours à récupérer bien le bon élément sur notre page donc je relance le débug on va vérifier si ça clique bien où il faut donc on enlève le pop-up voilà on a bien appliqué et là on est bien rendu au 1er mars 1er avril donc ça semble bon je vais le lancer une dernière fois pour m'assurer que ça fonctionne de nouveau donc là voilà on clique continuer continuer ça semble bon à chaque fois on est tout bon on revient au 1er mars donc c'était ça la solution vous voyez des fois il y a un petit peu d'essais d'erreur comme ça mais j'espère que cette cette explication vous permet de voir comment on peut soit avec le debuger de pcharm donc directement avec le debuger on a la possibilité qui est assez sympa de pouvoir aller dans thread and variables ici et d'évaluer des expressions alors que notre script est ouvert avec le debuger de playwright c'est intéressant aussi mais c'est différent c'est plus pour analyser la page avec des outils de playright donc il va nous retourner du code de playright mais vous l'avez vu dans le cas des dates c'est nous retournait pas des éléments très intéressants ça nous retournait des trucs beaucoup trop spécifiques donc c'est dans ces cas-là qu'il faut revenir à la base de la p de playwright avec les locator les first last et tout ce qu'on a vu pour pouvoir cibler plus précisément des objets de façon générique mais pas trop donc pas avec des trucs comme on avait vu avec le vendredi 1er mars qui sera un petit peu dur à deviner à chaque fois ou à calculer là on est resté avec quelque chose de très simple si on retourne voir le code la seule chose qu'on aura besoin de modifier ici c'est la date et ça c'est très facile à manipuler avec Python on peut juste grâce à un objet Date time changer la date du mois et l'insérer ici dans notre script donc dans notre chaîne de caractère pour à chaque fois cliquer sur le mois donc sur le premier jour du mois différent tout le reste vous voyez c'est très générique on a le Little search le modifier le appliquer et ensuite ce test ID ici générique également pour relancer la recherche dans cette partie on va continuer notre script pour faire défiler les mois donc là pour l'instant on fait juste passer au mois suivant en mettant la date spécifique ici donc le 1er mars et nous ce qu'on va vouloir faire c'est partir de la date d'aujourd'hui rajouter un mois et puis continuer comme ça pour faire défiler les mois à chaque fois afin de pouvoir ensuite récupérer la totalité des prix pour chaque mois et faire une moyenne et voir quel mois est le moins cher pour voyager dans une location donc là on va un petit peu sortir de ce script on va tout simplement revenir dans un terminal pour lancer Python 3 et on va faire nos tests à l'intérieur d'un terminal tout simplement puisqu'on va juste faire de la manipulation de date donc on n pas besoin de se lancer dans le scrapping pour ça on veut juste déjà faire notre petite recette à côté et donc je vais le faire dans un terminal avant ça je vais installer un autre module bien pratique qui est date utile qui va me permettre de récupérer la date du prochain mois de façon un peu plus robuste que ce qu'on aurait avec les modules de date de base de Python comme DateTime qui ne sont pas très faciles à manipuler surtout quand il y a des anné bisexyle et tout ce genre de choses qui arrivent avec les dates qui généralement peuvent poser des problèmes donc on a un module qu'il faut installer en plus qui s'appelle date utille qui va nous être bien pratique pour ça pour être assuré qu'on va facilement récupérer la date du premier jour du mois suivant donc on va l'installer avec PIP donc le pack package c'est python date util tout en minuscule comme ça avec un tiret entre les deux date util on l'installe avec PIP et une fois que c'est fait et bien on va pouvoir lancer un terminal Python 3 et importer les librairies dont on va avoir besoin donc on va déjà importer le module daytime à partir de la librairie dayetime donc là il y a beaucoup de choses qui se ressemblent dans cette librairie elle n'est pas très facile à manipuler je trouve que les noms sont un peu confus donc ça c'est une bibliothèque qui est disponible de base dans la librairie standard de Python je valide avec entrée et ensuite depuis date utilerative Delta on va importer relative Delta donc comme vous le voyez dans les gens qui écrivent ce genre de bibliothèque ils aiment bien confondre les gens un petit peu en mettant des noms qui sont similaires à chaque fois pour les modules et les classes qu'on va utiliser donc je lance tout ça et je vais récupérer la date d'aujourd'hui que je vais mettre dans une variable today avec datetime. today tout simplement on pourrait utiliser également now la différence entre les deux c'est que today n'a pas les informations d'heure alors que now les a moi ce qui m'intéresse c'est juste la date donc je vais rester avec today donc là si j'affiche today vous allez voir donc pas today comme ça mais voilà juste la variable que je viens de créer on a bien la date d'aujourd'hui et en fait l'heure aussi alors je me suis planté je croyais que il y avait une différence entre les deux mais apparemment non les deux retournent que ce soit today ou now retourn exactement la même information avec la date mais aussi l'heure donc dans ce cas-ci ça ne change pas grand-chose nous ce qui va nous intéresser c'est vraiment l'année le mois et le jour et ce que je vais faire maintenant c'est récupérer le prochain mois donc en faisant une variable par exemple next month et je vais ajouter à ma date de today un relative Delta d'un mois donc je vais mettre month é=al à 1 et pour les jours je vais mettre day é= à 1 alors attention ici on a bien un s à puisque on veut en fait ajouter un nombre de mois donc ça pourrait être 1 2 3 ou plus à notre date et pour le Day en fait on veut le remplacer ici donc ce n'est pas qu'on veut ajouter un nombre de day on veut juste dire que le jour doit être le premier jour du mois donc ce qu'on fait ici c'est prendre la date d'aujourd'hui et lui ajouter un mois et remettre le jour à 1 pour qu'on ait donc la date du premier jour du prochain mois et ici si je voulais tout faire sur une ligne à la place du Today je pourrais faire un daytime. now tout simplement ou daytime. today comme on l'a vu ça ne change pas grand-chose donc si je fais ça et que j'affiche next month vous voyez que là on a bien donc la date du mois prochain donc là on est le 13 janvier au moment où j'enregistre cette vidéo et là on a bien le 1er février 2024 donc c'est ce qu'on voulait alors je vais copier cette ligne puisque c'est cette ligne que je vais utiliser dans mon script je reviens ici on va importer les librairies nécessaires donc on va les mettre en haut ici from data import time et from dateurative Delta import relative Delta donc on arrive ici dans notre script avec le run on va remettre notre URL ici donc on va pour l'instant partir directement de cette url ici avec le continuer sans accepter et juste la modification ici du mois prochain donc je vais mettre dans une variable ici next month le mois prochain et là dans ce casci dans le pour le le premier mois on va devoir ajouter de mois puisque le on va commencer en FA en fait au mois d'après donc si je fais ma recherche au mois de janvier par défaut il va m'afficher le mois de février donc de février à mars donc pour le premier on va faire un relative delta de 2 mois et je vais ensuite transformer cette information qui est un objet Date en chaîne de caractère donc je vais mettre next month string par exemple et on va faire un string from time et on va lui donner une chaîne de caractère donc dans ce cas-ci ça va être le format 0103 2024 alors si vous voulez savoir le format de string for time vous avez un site très bien fait qui s'appelle string for time.org et là vous allez voir les codes qu'il faut utiliser pour pouvoir récupérer à partir de l'objet Date un format de chaîne de caractère donc nous ce qui va nous intéresser c'est bien d'avoir à chaque fois le jour du mois avec un zero pided decimal number donc pour le jour du mois pour le mois en tant que tel donc ça va être pourcentage D et pourcentage m et pour l'année on veut bien quatre chiffres ici donc ça va être pourcentage y en grand donc je reviens dans mon script on va avoir donc sous le format pourcentage d pour le jour/ash pourcentage m pour le mois/ash pourcentage y majuscule pour l'année et là normalement on devrait avoir dans cette variable exactement ce qu'on cherche à voir ici donc le 01 03224 qui correspond à la date du premier jour du mois dans 2 mois à partir de la date à laquelle je suis dans ce cas-ci le 13 janvier donc je vais insérer ça avec un f string ici dans mon test ID je le mets ici à la place de la date qu'on avait mis qu'on avait hardcodé en fait dans le script et je vais relancer mon script pour vérifier si avec tout ça ça fonctionne donc je mets mon point de débug ici je lance le script sans debug mais avec le debug de pcharm et on va voir si on arrive bien à naviguer au prochain mois comme ceci avec une date dynamique et ça semble fonctionner je regarde ici on est bien rendu au 1er mars donc tout fonctionne on a bien une date dynamique cette fois-ci il ne reste plus qu'à mettre tout ça dans une boucle for pour pouvoir passer à travers les 12 prochains mois donc je vais arrêter mon script et enlever le point de débug ici et on va tout simplement faire une boucle for qu'on va mettre probablement à partir d'ici donc je vais dire pour I in range de 12 donc on va faire 12 pour l'instant on va mettre tout ça à l'intérieur de notre boucle on pourrait mettre quelque chose d' un peu plus explicite ici je vais voir et ce relative Delta on va devoir le bouger à l'intérieur donc on va même mettre tout ça en fait ici directement aussi dans la boucle et on va voir donc qu'est-ce qu'on a besoin de changer là on commence à deux donc on a mis deux alors peut-être qu'on va modifier notre range on va commencer à 2 et on va aller jusqu'à 14 comme ça on va pouvoir mettre directement le i ici sans rien changer normalement donc là on va voir I qui va être égal à 2 3 4 et cetera jusqu'à 13 puisque si je me souviens bien le Range est exclusif euh donc on va décaler en fait à chaque fois on va faire un relative delta de 2 mois ensuite de 3 mois de 4 mois et cetera à chaque fois avec le daytime point today alors ça je vais quand même le mettre dans une variable au début qui va être égale ici à daytime point today puisque je n'ai pas envie de le recalculer à chaque fois et ça pourrait poser des problèmes imaginez qu'on lance le script par exemple le dernier jour du mois à 23h59 et on aurait donc un changement entre le moment où on débute le script et le moment où on passe dans la boucle for donc je préfère garder cette date ici ancrée au début pour qu'elle ne bouge pas une fois qu'on est dans la boucle for donc ensuite ici à la place du 2 je vais mettre le I et normalement avec tout ça on devrait être bon je vais avoir le next month qui va être égal à today avec à chaque fois un décalage de plus en plus grand donc on va décaler de 2 mois de 3 mois de 4 mois et cetera et à chaque fois ça devrait se répercuter comme il faut ici dans la date donc je vais juste sortir le browser close ici puisque je ne veux pas fermer le navigateur à chaque fois et et bien normalement ça devrait être tout bon je vais faire un petit page point wait for time out ici pour qu'on puisse y voir un peu plus clair et que ça n'aille pas trop vite donc je vais mettre 5 secondes par exemple on peut même mettre un peu moins 2,5 secondes et on va vérifier si avec tout ça ça fonctionne donc je relance le script je vais pas le lancer en débug là avec le Time Out ça devrait être un petit peu plus lent et on devrait avoir le temps de voir ce qui se passe donc je reviens ici je modifie et là rien ne se passe donc je pense qu'on a un petit problème et comme on n pas fait de dbug et bien je ne vois pas ce qui se passe donc je vais mettre un point de débug ici on va relancer ça j'ai probablement fait une erreur quelque part avec le relative Delta donc je vais relancer pour qu'on y voit un peu plus clair je vais mettre ça de côté voilà donc on arrive ici next month est égal alors là j'ai pas exécuté cette ligne je vais continuer donc next month 0103 2024 donc ça devrait être bon normalement c'est ce qu'on voulait alors je vais séparer un petit peu mon écran pour qu'on y voit un peu plus clair donc là on continue on clique sur la barre on clique sur le bouton Modifier et normalement on va récupérer voilà le premier jour alors ça a bien marché cette fois-ci on valide on clique sur le bouton Rechercher et on a bien continué alors je vais y aller comme ça pas à pas donc on attend 2.5 secondes on continue on va voir I est égal à 3 je continue donc je pense que là c'était peut-être juste que le script est allé un peu trop vite et que il n'a pas eu le temps de de de voir tous les éléments sur la page donc je vais continuer on reclique on clique sur Modifier on passe au 1er avril on applique on continue et ça semble bien fonctionner donc je pense que c'est juste que le script est aller un peu trop vite donc pour ça si jamais vous avez ce genre de problème et bien on peut rajouter un petit timeout donc là il semble que ça se soit passé après le modifier donc ce que vous pouvez faire c'est rajouter pour être sûr un petit wait for time out ici par exemple de 500 mses euh ce qu'on peut faire aussi c'est faire un page point wait for event et là on va avoir différents events on peut faire network Idol ou dB content loaded donc le Network Idol en fait il est un petit peu dangereux puisque il va attendre jusqu'à ce qu'il n'y ait plus aucun événement du réseau donc ça ça peut être un peu dangereux parce que on peut avoir des sites qui vont continuellement aller chercher des informations de par période régulière donc toutes les secondes par exemple et dans ce cas-ci on aura jamais vraiment un réseau qui va être Idol donc Idol ça veut dire qu'il ne bouge plus euh donc ça ça peut être un petit peu risqué le DOM content loaded c'est pareil à un moment le DOM donc le Document Object Model va avoir fini de charger mais là encore ça peut il peut y avoir des rechargements qui se font aussi donc là ça va être dans la gestion d'erreur moi je vais faire juste un wait for timeout de 500 secondes et on va voir si ça règle le problème là aussi je vais mettre un petit wait for time out à la fin de 500 secondes on pourrait varier un petit peu pour être un peu plus humain là encore ça c'est le genre de chose qui avec le scrappeur de Bright data vont être grandement fluidifiés puisque il va imiter le plus possible le comportement humain pour également ne pas impacter les performances du site là pour l'instant on fait tout en local et on n pas mis vraiment de wait for time out comme vous l'avez vu dans le reste du script donc ça va le plus vite possible dès qu'il voit que les éléments sont chargés playwright gère normalement plutôt bien tout ça en fait il va s'attendre quand il clique sur quelques chose à ce que les éléments se tassent un peu donc à ce qu'il y ait moins d'activité et que tous les éléments sur lesquels on a cliqué soient visibles mais des fois ça peut valoir le cûp de mettre des timeouts comme ici pour attendre un petit peu et ne pas aller trop vite donc je vais relancer le script on va voir donc en relançant ici directement sans point de débug si ça fonctionne mieux cette fois-ci on relance et ça semble bien ici on continue on modifie on passe au mois suivant et cetera et cetera donc vous voyez avec les petits timeout ici ça semble fonctionner sans aucun problème et on récupère bien toutes les dates à chaque fois toutes les locations on arrive au 1er juillet on continue donc tout fonctionne sans problème 1er septembre 1er novembre et on va faire à la fin de l'année comme ça je pense même qu'on va se rendre à l'année prochaine et après donc il ne reste plus qu'à modifier dans la boucle for le l'étendue du Range pour voir jusqu'où on veut aller là vous voyez tout a bien fonctionné et donc là si vous voulez aller plus loin en 2025 vous pouvez modifier pour mettre par exemple 20 et ça va continuer comme ça euh à défiler les mois de la page Airbnb donc voilà pour la résolution de ce petit problème avec la boucle for avec le calcul de la date et cette bibliothèque date uti qui est bien pratique pour faire des calculs comme ça avec des dates de façon un peu plus simple que ce qu'on aurait eu à faire avec la librairie de base de on touche au but désormais avec notre script qui va pouvoir passer à travers les mois de l'année maintenant ce qu'il manque c'est de récupérer les données ça on l'avait fait dans notre script basique donc si je reviens dans le main.py ici on avait bien la fonction ici qui était get average price qu'on va pouvoir copier puisque le code HTML lui n'a pas changé c'est juste la façon de faire là on utilisait request maintenant on va utiliser playright donc là je vais mettre tout ça dans un module je vais créer un nouveau fichier Python et je vais l'appeler price.py tout simplement et je vais mettre à l'intérieur cette fameuse fonction get average price et on va réimporter les librairies nécessaires donc on va faire from BS4 import beautiful soup et le logger pour l'instant on va l'enlever on verra par la suite si on le rajoute pour l'instant je vais simplifier tout ça et je vais juste rimporter également le module re donc le module de RX ici en haut de mon script donc cette fonction va pouvoir l'utiliser normalement comme je vous dis rien n'a changé on va lui passer du HTML et on va récupérer la moyenne des prix et on va revenir donc de notre script principal pour importer cette fonction donc là encore je vais le faire tout en haut ici on va les mettre après les imports de la librairie standard et des librairies tierces comme playwri ici donc on va faire from price import get average price et on va utiliser donc cette fonction pour récupérer le prix à partir du code HTML ce qu'il me reste à faire ici c'est de décommenter toutes les lignes que j'avais ici là on va vraiment repartir depuis la page d' accil donc je vais enlever cette url qu'on avait utilisé pour nos test on va vraiment faire le test au complet en partant de la page d'accueil pour naviguer jusqu'à la page avec Rio de genero on va en profiter également pour modifier cette valeur qui est directement mise dans le script ici pour la passer à la place à notre fonction donc on va la passer en deuxième ici on va mettre City par exemple et on va indiquer ici qu'il s'agit d'une string on va également rajouter les éléments ici de typage donc le boulet 1 ici et le boulet 1 également pour le headless je fais un petit commande option l pour formater tout ça automatiquement et le City ici et bien on va le mettre à la place du Rio de janeero je vais le mettre dans le fil et on va le passer ici en bas de notre script et par la suite on va voir qu'on pourra le passer en ligne de commande comme on l'avait fait avec le module 6 si on le souhaite donc là je vais mettre City égal et pour varier on va mettre Paris on va revenir du Brésil et changer la ville pour voir si tout fonctionne également avec une autre ville ça ne fera pas de mal donc là normalement tout est bon il reste plus qu'à récupérer donc le comp contenu du code HTML pour pouvoir analyser le prix donc ça je vais le faire au début de ma boucle ici puisque là on va faire la recherche donc ici je vais faire get average price avec HTML qui va être égal à page. content et on va récupérer ça dans une variable qu'on va appeler average price et je vais faire un print pour afficher la valeur donc on va dire average price for date et là on va mettre la date alors je vais peut-être le bouger un petit peu plus loin on va le mettre juste après le calcul de la date ici pour qu'on ait accès à cette date donc for date ici is et on va insérer le average price pour l'afficher donc je refais un petit reformat pour tout remettre comme il faut et bien on va tester comme ça normalement ça devrait être tout bon on continue avec le headless qu'on va on va le mettre à TR pour voir on va juste lancer le script comme ça sans desbug directement et voir si on a bien tout ce qui nous intéresse ici alors si ça marche du premier coup je suis chanceux alors là on a un zé ça commence bien donc là ça ne semble pas fonctionner donc j'ai dû faire une erreur quelque part donc on va refaire un petit debug pour vérifier qu'on a bien tout ce qu'il faut je vais mettre le headless à false et on va remettre ici un point ah oui alors est-ce que c'est parce que non là on fait un page ok donc je vais page content euh ok non ça devrait être bon je vais mettre un point je vais mettre ça dans une variable déjà pour qu'on puisse l'isoler donc je vais faire un clic droit on peut faire un refactor ici et un extract euh introduce variable pardon et on va mettre HTML content comme ceci et automatiquement vous voyez qu'il a déplacé le contenu que j'avais sélectionné dans une variable il a tout remplacé comme il faut donc je vais mettre un petit point de débug ici pour voir si on a bien ce qu'il nous faut dans le html je relance en mode des bugs donc on continue on explore on arrive à Paris là on arrive à ce point ici et on a bien notre page qui s'affiche alors je pense que ça doit être encore une fois juste une question de de temps d'affichage puisque quand on va sur Airbnb ça prend un petit peu de temps avant d'afficher toutes les annonces donc je pense que ça doit être ça je vais continuer voir si on récupère quelque chose dans average price donc là on est toujours à zéro alors c'est peut-être un problème ici directement dans le script donc je vais peut-être devoir analyser ce script ici il y a peut-être une erreur donc on va aller voir le HTML content déjà voir à quoi ça ressemble et vérifier si on a bien les fameuses classes qu'on va chercher donc par exemple le cart container donc je vais vérifier ici avec un contrôle F et effectivement il semble qu'on n pas le card container ici alors je vais aller voir dans le sous-location si je fais un clic droit inspect et que je vaux voir directement ici est-ce qu'on a le card container alors on l'a bien data test ID donc là il doit y avoir un problème quelque part euh donc ce que je vais faire c'est tout simplement encore un petit peu de débug on va remettre un point de débug ici directement pour voir si on arrive bien à récupérer les div je l'enlève d'ici et je vais juste relancer le script avec le debug à ce niveau donc directement dans la fonction donc là on va bien récupérer les éléments voilà et je pense alors en fait oui en fait je pense je vais mettre avant je viens d'avoir le de me dire que là on récupère le HTML content directement alors ce que je vais faire c'est avant ici comme je vous disais ça va peut-être un peu vite donc on va faire un wait for P event mais for Time Out et on va mettre allez on va être générer on va mettre 5 secondes et on va voir déjà si ça résout le problème donc je vais remettre mon point de débug que j'avais pas enlevé donc je vais le laisser juste ici on relance et on va juste lui laisser un petit peu de temps après qu'il charge la page pour voir si ça peut déjà euh pas être ça le problème vous voyez qu'il y a un petit temps d'attente euh entre le moment où on fait la recherche et le moment où on a la page donc je continue et là vous voyez qu'effectivement on a quelque chose dans les div donc ça semble être bon je vais continuer avec mon point de débug que je vais mettre ici après le average price je fais cette fois-ci un resume program je ne veux pas continuer pas à pass si je clique ici sur stepover ça va faire les lignes une par une moi ce que je veux juste c'est continuer le programme et m'arrêter après le average price donc je continue et là on a bien une valeur dans le average price donc c'est bien mon intuition qui se vérifie je vais continuer comme ça hop là on va rattendre 5 secondes de nouveau puisque j'ai toujours mon wait for Time Out et normalement on devrait avoir une autre valeur donc je continue on arrive bien dans la fonction get average price et on a une autre valeur ici dans average price donc ça fonctionne bien c'était effectivement juste un problème de chargement donc là on peut faire un wait for time out si on veut être un peu plus précis on pourrait peut-être euh vérifier ici faire une boucle while qui vérifie là je sais pas combien en a de d'éléments je pense que sur cette page on en a toujours le même nombre donc on a une grille avec trois par peut-être 5 ou 6 donc ça fait 18 éléments si mes mats sont bon donc ce qu'on pourrait faire c'est une boucle pour vérifier euh pour attendre en fait tant qu'on n' pas 18 éléments avec la classe carart container par exemple ça pourit être une façon de faire pour être sûr d'attendre uniquement le temps dont on a besoin euh dans ce cas-ci je pense queon pourrait juste laisser une valeur fixe comme je vous dis on n'est pas forcément très pressé et si on veut rester éthique et faire quelque chose qui ne va pas surcharger le site c'est de toute façon une bonne idée de mettre un petit peu de temps d'attente ici donc là je vais pas mettre 5000 je vais essayer de mettre quand même un petit peu moins 2000 on va mettre ça comme ça et je vais relancer le script pour voir si euh tout fonctionne bien on va se remettre en headless at pour ne pas être importuné par l'ouverture du navigateur et on va voir si on arrive bien à récolter les données de nouveau donc voilà average price on a 487 1401 donc là ça semble un petit peu moins cher en avril qu'en mars ça commence à remonter avec l'approche de l'été j'imagine avril mais voilà on commence à remonter tout doucement donc ça semble assez logique en juin en juillet on commence à augmenter beaucoup en août j'imagine ça va être encore pire voilà et probablement qu'en septembre octobre ça va commencer à redescendre effectivement mes intuitions sont bonnes donc on a forcément c'est assez logique la saison touristique qui battent son plein donc là basé sur ces données il semble que le meilleur mois pour partir à Paris ce soit le mois de novembre ce qui là encore est assez logique je pense puisque si on regarde donc par rapport aux périodes de vacances je pense donc là on va aller jusqu'à probablement le 3 2025 ou peut-être qu'on va s'arrêter là non voilà on s'est arrêté là puisqu'on fait 12 mois donc là on a la boucle qui est bouclée on avait bien 12 mois donc 12 itérations dans notre boucle donc on on a le mois prochain donc en mars on est pas mal élevé après bien sûr avec l'été ça explose et ensuite en novembre il y a pas grand-chose qui se passe pour le 1er décembre donc le mois de décembre je pense qu'avec les fêtes de fin d'année pareil pour janvier ça remonte un petit peu par contre en octobre et en novembre vous voyez il y a pas grandchose qui se passe donc selon cette étude je pense que le mois de l'année le mieux enfin en tout cas le mieux le moins cher on va dire pas forcément le mieux mais celui qui fera le moins de mal à votre portefeuille c'est le mois de novembre et on peut répéter ça avec d'A are ville donc là on peut le modifier directement ici on pourrait mettre par exemple Porto la ville où j'habite pour vérifier ce que ça donne je vais relancer le script et je pense en tout cas j'espère que les prix seront un peu moins chers quoique là il faut savoir aussi qu'on a mis aucune option de filtre donc on a des gamme de prix qui sont je pense en fait assez similaires c'est peut-être voulu de la part de Airbnb de toujours être un petit peu dans les mêmes zones de prix probablement en fonction du pays d'origine peut-être là on voit qu'on est quand même dans des fourchettes assez proches c'est quand même un petit peu moins cher que Paris mais mais c'est quand même assez élevé et bien sûr donc là avec tout ce que vous avez vu dans les parties de cette formation vous voyez que c'est maintenant très facile de pouvoir faire la même chose pour modifier les filtres si on le souhaite pour mettre des limites de prix par exemple ou pour cibler certains type de bien et bien il suffit d'utiliser par exemple l'outil de debug de playright qu'on a vu qui va permettre d'inspecter les différents éléments de la page pour pouvoir cliquer sur les bons éléments et rajouter les options de filtrre que l'on souhaite donc voilà pour cette partie tout fonctionne bien on peut changer notre ville ici on peut changer notre ville directement ici on peut choisir de le faire avec bright data également pour terminer cette partie je vais vérifier avec bright data que ça fonctionne bien également le headless je vais le mettre en false et je vais relancer ma requête donc script without debug ça devrait ouvrir la vue de debug de Bright data et on va voir si ça fonctionne également avec le scrapping browser de Bright data mais il n'y a pas de raison que ça ne fonctionne pas puisque là encore le site n'a pas changé donc on va se rendre sur les mêmes pages HTML on va cliquer qui est sur les boutons voilà donc le bouton pour les cookies le bouton pour explorer les logements donc comme vous voyez c'est un petit peu plus long mais ça fonctionne bien on va se rendre dans la destination et on va continuer comme ça voilà avec les dates et cetera et cetera donc je vais pas aller plus loin ça semble fonctionner je vais arrêter le script et on a donc un script 100 % fonctionnel pour aller récupérer les données qui nous intéresse j'en profite pour faire une petite parenthèse de 10 secondes si tu souhaites te former à Python une seule adresse docstring fr tu peux te créer un compte c'est gratuit et tu auras beaucoup de contenu des exercices des quiz des glossaires des formations des projets des parcours cré-toi un compte tu vas pouvoir découvrir tout ça et n'hésite pas également à nous rejoindre sur le serveur discord de doc string on a des challenges toutes les semaines des vocaux des salons d'aide donc rejoins-nous tous les liens sont dans la description dans les parties qui vont suivre on va voir comment faire le Graal de tous les gens qui font du scrapping un script qui va va nous permettre de détecter une baisse de prix suffisamment importante sur un produit Amazon alors j'ai pris Amazon mais on pourrait prendre n'importe quel site d'e-commerce pourquoi j'ai pris Amazon parce que c'est un site qui est bien entendu très connu et également qui est connu pour être difficile à scrapper on va voir donc comment avec les outils de Bright data on peut mettre en place un scrapping éthique qui va nous permettre de récupérer les informations dont on a besoin sans être bloqué et on va également faire un script professionnel et robuste avec une gestion des erreurs et un logging qui vont nous permettre d'être avertis dans le cas où il y a le moindre problème avec notre script on va notamment mettre en place un service qui s'appelle centry qui va nous permettre de voir toutes les erreurs qu'on aura dans notre script et de les résoudre au fur et à mesure et d'être alerté en cas d'erreur sur notre script on verra également comment utiliser pushover une application qui permet d'envoyer des alertes sur votre téléphone vous aurez ainsi à la fin de ce projet un script qui va rouler sur un serveur privé virtuel donc qui sera disponible 24h/ 24 pour exécuter votre scrapping et vous avertir dès qu'il y a une chute de prix avec une gestion des erreurs et des alertes sur votre téléphone pour pouvoir gérer tout ça à distance pour réaliser ce projet on va utiliser beaucoup d'outils qui vont chacun avoir une fonction très précise pour réaliser le scrapping on va utiliser le web Unlocker de Bright data puisque nous n'avons pas besoin ici de faire des interactions complexes avec le site web on va juste naviguer vers une page pour récupérer les données de prix mais comme Amazon est assez agressif en terme de scrapping on va utiliser une solution comme le web Unlocker qui va nous assurer de passer à travers les capchas potentiels ou les blocages par adresse IP parce que Amazon oui peut vous bloquer même si vous ne faites pas un scrapping agressif donc même en faisant des requêtes à un rythme raisonnable par exemple une ou deux fois par minute si vous le faites régulièrement à un moment ils peuvent quand même décider de bloquer une adresse IP dans ce cas-ci la rotation d'IP du web Unlocker qui est faite automatiquement va nous aider à passer à travers ces blocages le deuxième outil qu'on va utiliser c'est l'outil qui va nous permettre de mettre en ligne notre projet et on va le faire sur un VPS d'infomaniaque si vous souhaitez soutenir la la chaîne vous trouverez en commentaire de cette vidéo un lien d'affiliation qui vous permettra de créer votre compte et votre VPS sur infomaniaque donc nous on va utiliser ce VPS pour mettre en ligne notre script et utiliser un chron job pour lancer ce script de façon régulière pour aller récupérer les informations de prix et le VPS va nous assurer d'avoir ce script qui va rouler 24 he/ 24 7 jours sur 7 sans avoir besoin de notre côté de laisser notre ordinateur allumer les deux derniers services qu'on va utiliser ça va être pushover et sentry deux services que vous pouvez utiliser grat gruitement ils ont des options payantes mais pour les besoins de ce projet on n pas besoin des options payantes les options gratuites nous suffisent avec pushover vous pourrez par exemple envoyer jusqu'à 10000 notifications par mois sur votre téléphone donc ça devrait être largement suffisant pushover va donc comme je viens de l'expliquer nous permettre d'envoyer des alertes directement sur votre téléphone donc c'est très pratique pour être averti dans le cas d'un scrapping d'une information qui nous intéresse dans notre cas l'information que le prix du produit qui nous intéresse a une chute significative etentry c'est un service qui va nous permettre d'avoir un log des erreurs on peut également lier sentry à pushover pour être averti en cas de problème sur notre script là encore avec une alerte sur notre téléphone donc sentry c'est un peu comme un loger Plus+ si vous voulez ça va nous permettre d'avoir accès à toutes les erreurs potentielles qu'on aura dans notre script et de les avoir logué à un endroit pour en avoir une trace et pouvoir indiquer si elles ont été résolues ou non pour finir on va utiliser deux bibliothèques au niveau de Python request et select AX vous allez voir que le script va être assez simple on va juste faire une seule requête avec le web er vers la page d'Amazon et avec selectolax on va récupérer le prix là encore on pourrait utiliser d'autres bibliothèques vous pouvez utiliser httpx si vous souhaitez à la place de request ou encore beautiful soup à la place de selectolax vous allez voir qu'avec les quelques lignes de code que l'on a ce sera très facile d'adapter votre code peu importe les bibliothèques que vous choisissez d'utiliser pour ce projet avant de commencer le scrapping à proprement parler on va encore une fois s'assurer qu'on fait un scrapping éthique la même chose qu'on avait fait pour le projet Airbnb la première chose à vérifier c'est donc l'existence d'une API publique qui fournit les données que je recherche donc je vais pas refaire le processus que j'avais fait pour l'application Airbnb je vous laisse aller vérifier par vous-même il n'y a pas d'API public qui permet de récupérer les données d'un produit sur Amazon donc dans notre cas on va être obligé de passer par le scrapping les données qu'on va récupérer sont également publiques et on va les récupérer à un rythme raisonnable avec le web Unlocker de Bright data qui l' encore va disposer de toutes les mesures de sécurité pour s'assurer que le scrapping n'est pas fait de façon trop agressive ainsi qu'elle pourrait porter atteinte aux performances du site et on va également respecter le contenu qu'on récupère et le droit d'auteur et ne pas utiliser ce contenu pour porter atteinte à Amazon donc dans ce cas-là on va également respecter tout ce qui est rgpd on ne va pas récolter d'adresse mail de numéro de téléphone ou quoi que ce soit qui soient des données personnelles on va juste récupérer les données de prix on ne va pas non plus récupérer ces données pour les dupliquer ou pour créer un service concurrent ou qui pourrait porter atteinte à Amazon ou au vendeurs des sites Amazon là encore les données vont être utilisées pour un besoin personnel donc juste pour avoir une information sur le prix exactement comme on pourrait le faire en rafraîchissant la page pour vérifier si le prix a descendu ou non donc ça va être un scrapping très léger et qu'on va faire un rythme raisonnable avec le web Unlocker de Bright data donc ça coche toutes les cases d'un scrapping éthique bien sûr là encore avec des sites comme Amazon assurez-vous si vous voulez faire des scripts un petit peu différents ou même avec ce genre de script que vous allez le faire dans le cadre de la loi des pays concernés dans ce cas-ci le projet est à but éducatif mais comme à chaque fois c'est quand même un important je pense de passer en revue ces choses ici notamment le cas de l'API parce que ça ne sert à rien de faire du scrapping si vous avez une API qui est fonctionnelle qui est publique et qui vous permet de récupérer les mêmes informations que celles qu'on récupère en faisant du scrapping donc on va commencer avec la création de la base de notre script et on va commencer tout naturellement par créer un projet que je vais créer directement avec pcharm je vais l'appeler ICOM notifier tout simplement et on va utiliser les outils de pycharm pour automatiquement créer un environnement virtuel à l'intérieur de ce dossier je vais également créer le fichier mine.py par défaut on va enlever tout ce qu'il y a dedans mais comme ça on aura pas besoin de créer le fichier il sera déjà là pour nous donc je vais cliquer sur Create et ça va créer le projet avec ce fameux fichier main.p donc comme je vous dis je vais enlever tout ce qu' est a à l'intérieur mais là au moins on a bien configuré notre dossier avec l'environnement virtuel et on va pouvoir ainsi installer les bibliothèque dont on va avoir besoin donc je vais ouvrir le terminal on va installer les bibliothèques request et sectolx donc PIP install request et PIP install selectolx install selectolax comme ceci tout en minuscule je valide avec entrée et j'ai les deux premières librairies dont je vais avoir besoin je vais les importer au début de mon fichier donc on va faire un import de request et on va importer depuis selectolx selectolax.parser le html parser qui va nous permettre d'analyser le html pour récupérer les informations qui nous intéressent je vais faire une fonction main qui va recevoir une URL pour l'instant je vais mettre un pass et je vais créer le fameux if nameame = main pour lancer cette fonction à l'intérieur de cette structure conditionnel et pour l'URL on va aller chercher l'URL du produit Amazon qu'on souhaite récupérer donc là je suis sur la page du produit donc c'est une carte graphique Nvidia très classique et vous voyez que là on a une URL assez longue puisqu'il y a plein de paramètres ici après le point d'interrogation plein de paramètres qui permettent de définir des tags et tout plein d'autres choses comme ceci donc vous allez bien souvent avoir tous ces paramètres quand vousz naviguer depuis la page d'accueil vers des produits nous ce qui va nous intéresser c'est juste la première partie ici et même encore plus précisément ce cette chaîne de caractère un petit peu bizarre que vous allez retrouver en fait si on descend dans les descriptions du produit donc dans product information ici on a quelque chose qui s'appelle l'assine donc qui se retrouve effectivement ici dans additional information donc c'est cette chaîne de caractère que l'on retrouve également dans l'URL à la fin avant le point d'interrogation et après le DP donc on va pouvoir prendre cette assine et juste en fait si je prends l' URL vous allez voir on peut la recréer également à partir de cette url donc si je reviens dans pcharm je vais faire une variable URL je vais faire un petit peu de place ici et là en fait ce qu'on peut faire c'est enlever cette cette description du produit enchaîne de caractère et juste garder le slash DP Slash et le assigne ici donc c'est le assine on va le mettre dans une variable même et je vais le récupérer ici comme ça on pourra si on le souhaite utiliser un autre assine d'un autre produit qu'on souhaiterait récupérer donc je vais le mettre ici assine et le concaténner avec cette URL et on va passer l'URL ici dans notre fonction main donc à l'intérieur de cette fonction qu'est-ce qu'on va faire on va faire une requête avec request on va faire une requête GET vers l'URL que l'on va passer dans cette fonction main je vais récupérer le contenu de cette requête dans une variable response et le contenu de la page dans une variable HTML content qui va être égal à response.text et ce qu'on va faire tout de suite c'est écrire ce fichier sur le disque parce que c'est toujours bien en fait pour éviter de par la suite refaire cette requête surtout avec Amazon on va être très rapidement bloqué en fait c'est toujours bien de profiter de cette première requête un peu pure je dirais pour écrire le fichier sur le disque donc là on va écrire le contenu du fichier euh donc de la variable HTML content dans un fichier amazon.html qui va être donc dans le même dossier que là où j'exécute mon script comme ça on va pouvoir faire notre analyse directement depuis le fichier donc là l'analyse est assez simple vous allez voir on va inspecter le fichier HTML il y a une seule classe à aller chercher mais voilà c'est toujours bien de déécrire en fait ce fichier lors de la première requête pour s'assurer d'avoir la base du H HTML et de pouvoir la réutiliser ensuite je vais créer un objet tree qui va être créé à partir de HTML parsur et on va lui donner le HTML content donc la variable HTML canton qu'on a défini plus haut et là je crois que j'ai une erreur alors qu'est-ce que j'ai fait comme erreur euh alors ça va oui ça va être en WR et là il est pas content alors je pense que ah oui c'est une erreur d'indentation tout simplement voilà il y avait trois espaces au lieu de quatre et euh ensuite donc on va analyser cette page html déjà et voir qu'est-ce qu'on peut faire pour ne pas être bloqué directement parce que là c'est bien important pour cette première requête de faire une modification ça va être de donner un user agent parce que actuellement avec request le user agent qui est la chaîne de caractère qui identifie quand on fait une requête avec un navigateur quel navigateur on utilise quel système d'exploitation et cetera donc par exemple de dire qu'on utilise chrome sur un ordinateur Mac ou alors qu'on utilise Safari sur un élément iOS par exemple donc un téléphone ça c'est une chaîne de caractère qui va être envoyée avec la requête et par défaut avec request on va avoir une chaîne de caractère qui va ressembler à Python request et la version de request donc par exemple 3.12 donc là on va tout de suite être identifié comme un bot par Amazon et il va nous bloquer direct donc si vous faites une première requête comme ça sans changer le user agent vous êtes assuré d'être bloqué il va bloquer votre IP en fait et la seule façon de changer ça ça va être si vous le faites à la main d'utiliser un VPN par exemple ou un réseau de proxy comme on verra par la suite comme le réseau de proxy donc de Bright data qu'on va utiliser mais voilà quand vous voulez faire vos tests faites bien attention ne faites pas une première requête sans changer le user adjin sinon vous allez être bloqué direct et vous allez dès le début devoir contourner les restrictions qui vont être faites sur votre IP donc moi ce que je vais faire c'est utiliser mon user agent donc on peut taper what is my user agent par exemple dans Google et ça va vous retourner votre user agent il y a plein d'autres sites aussi là qui peuvent vous donner votre user agent mais avec Google on l'a directement donc je peux le copier et je vais le mettre dans une chaîne de caractère dans mon script donc qui va être dans les headers donc les headers c'est les entêtes qu'on va passer avec notre requête donc on va mettre user agent ici et je vais passer la chaîne de caractère que je viens de copier dans le user agent et on va passer ces en tête à notre requête donc avec l'argument headers donc je passe cette variable ici à ma requête et comme ça on aura bien un user agent qui ne va pas être identifié comme un bot maintenant si je retourne sur la page d'Amazon on va essayer de trouver comment récupérer l'information du prix donc il a plusieurs endroits il est par exemple ici 234 ici aussi donc on va faire un clic droit inspect pour vérifier ce qu'on a là on a juste un span avec hidden on a pas grand-chose on a quelques classes ici un peu plus haut qui pourrait être utile mais vous voyez qu'il y a pas une classe directement qui va cibler le 234 ce que je peux faire c'est chercher à d'autres endroits sur la page si je ne trouve pas ce 234 et vous voyez qu'on a 25 occurrences ici donc je vais essayer d'aller trouver est-ce qu'il y a pas cette information quelque part d'autre avec une classe un peu plus un peu plus facile à récupérer donc on a le span avec un ID total cost ici qui est pas mal on va avoir d'autres choses ici donc un value je suis pas sûr que ce soit la bonne chose ça pourrait être une une autre valeur qui est aussi égale à 234 on a ici euh les choses qui sont un peu mieux découpées donc avec le price h price decimal donc ça c'est pas mal le span ici je l'aime bien parce qu'on a juste les informations avec le chiffre comparativement aux autres o on avait le symbole de pounds le la décimale et cetera moi dans ce cas-ci je veux pas les décimales je m'en fous des centimes je veux juste donc le le prix complet sans les sans les centimes et là on a une classe à Price H qui est bien sur un span je vais chercher si cette classe apparaît autre part et elle est effectivement à 22 endroits avec je vais vérifier est-ce qu'on a à chaque fois l'information ici on l'a également ici aussi donc on l'a plusieurs endroits mais à chaque fois on semble avoir la même information donc je vais essayer d'utiliser ça là vous voyez qu'on a le price symbol avec euh le pound les fractions et cetera donc je pense que ça c'est pas mal je vais utiliser le span et on va le récupérer donc dans notre script avec selectol AX donc on va faire un une variable Price et on va faire un tree. CSS first parce qu'on souhaite récupérer uniquement une indication là il y en a 20 22 sur la page mais je vais cibler le span avec cette classe et ça devrait nous retourner le premier et on va voir si à chaque fois on arrive à récupérer la valeur du prix et je vais donc faire un print pour l'instant de juste price.text et on va voir ce que ça va donner alors il est très possible que là je sois déjà bloqué par Amazon vu que j'ai fait pas mal de tests et cetera donc on va essayer si ça ne marche pas j'essaierai de changer mon adresse IP pour voir si on peut quand même récupérer cette information avec ce script et on va également voir ce que ça donne dans le fichier amazon.ht ml qu'on va écrire sur le disque donc je vais faire un clic droit je vais lancer run main ici et on va voir ce qu'on a est-ce qu'on a une valeur ou non on attend un petit peu et on a bien cette valeur 234 avec le point ici donc ça veut dire qu'on récupère le on récupère quand même le point donc on pourra l'enlever donc on peut faire par exemple une variable intermédiaire on va l'appeler price node et ensuite on va dire price on va faire un return pour l'instant de int qui va être price node donc pas print mais price node text et on va juste placer le point par une chaîne de caractère vide donc on va enlever en fait le point et on va retourner tout ça donc comme ça on aura bien le nombre ici en tant que nombre donc en tant que nombre entier sans le point donc ça semble fonctionner là vous voyez je n'ai pas été bloqué je pense que si je le fais de nouveau un petit peu trop ça ça risque de bloquer si je vais voir amazon.html ici on a bien le fichier complet si je retourne voir je crois que c'était à Price hall donc là on a des classes de CSS et là on a le fameux 234 et euh et on a effectivement le point ici donc en fait le problème ici c'est que on a un span qui contient un autre span euh avec le price decimal donc en fait c'est ça qu'on récupère comme on récupère tout le texte qui est à l'intérieur on va pas récupérer le span on va récupérer le texte qui est à l'intérieur du span puisqueon là on a un premier span qui se termine du coup ici et qui englobe le point donc euh donc voilà je pense que je vais rester là-dessus juste remplacer le point c'est pas c'est pas très problématique et ça me permet de récupérer le prix donc comme je vous dis la on va on va le réessayer une deuxième fois on va voir si ça si ça fonctionne de nouveau je vais relancer le script on va voir si on récupère bien le prix alors là j'ai pas fait de print on va faire un print et on va enlever notre notre with open là on en a plus besoin c'était juste pour avoir une première une première version sur le disque de notre fichier HTML si jamais on veut l'avoir comme référence mais là je n'en ai plus besoin donc je vais l'enlever donc j'ai refait le print ici je relance on va voir si on récupère l'information 234 ça marche de nouveau je vais le refaire une dernière fois donc pour l'instant vous voyez VO on n'est pas encore bloqué ça va mais si on fait la requête trop souvent vous allez voir qu'assez rapidement on va être bloqué et je vais vous montrer aussi si j'enlève les headers ici donc si je les enlève de ma requête je suis pas sûr que ça va marcher on va voir vous voyez directement non type donc j'essaie de faire la requête mais directement on est identifié comme un bot je vais remettre ce que j'avais en fait le with open ici donc je fais quelques contrô Z juste pour vous montrer queune fois qu'on est bloqué le le html va être différent là je le relance avec les headers et là vous allez voir que comme on l'a fait une fois sans les headers normalement amazon va bloquer notre IP et même si on met les par la suite avec le user agent on devrait être bloqué de la même façon et non ce n'est pas le cas donc on a de la chance il nous a il nous a pas encore bloqué donc je pense qu'il il autorise comme vous le voyez une certaine un certain scrapping mais si on le fait trop souvent vous allez voir qu'au bout d'un moment on va être assez rapidement bloqué donc là on va aller voir donc le fichier HTML il va toujours être être bon je vais faire une petite boucle on va faire un import the time et on va faire une petite boucle ici on va dire for H in range de 10 on va faire 10 requêtes on va laisser se passer un petit peu quand même pour pas surcharger le site même si Amazon n'a pas trop de souci à se faire là-dessus je pense mais c'est juste voilà pour quand même ne pas se faire bloquer trop violemment et rester un minimum éthique donc on va faire une petite un petit time point slip je relance et vous allez voir normalement que on va être bloqué à un certain moment et là vous voyez hop on arrive à un moment où on a une erreur non type puisque on n' pas de d'attribut texte sur Price node donc ça veut dire qu'on a pas réussi à récupérer price node et donc c'est que dans le HT on avait pas on n' pas trouvé en fait ce ce span avec cette classe et donc ça veut dire qu'en fait normalement on va être bloqué je vais aller voir le html ici on va remonter un petit peu là vous voyez qu'on a une petite centaine de lignes donc là c'est déjà une bonne indication qu'on a pas toute la page et vous voyez ici euh voilà je regarde un petit peu là on a effectivement un avertissement enfin un message qui nous dit voilà pour parler des processus automatisés écrivez-nous API service vous pouvez utiliser les Marketplace API et cetera donc donc vous voyez qu'on a on a un message ici qui nous dit que on peut pas on peut pas récupérer l'information et effectivement donc le le prix n'est plus affiché sur cette page et c'est pour ça qu'on a cette erreur donc vous voyez que là on est bloqué ce qu'on peut faire comme je vous disais c'est utiliser par exemple un VPN pour faire en sorte qu'on soit détecté comme étant ailleurs avec un autre ordinateur mais ça va pas être très pratique et c'est pour ça qu'on va par la suite utiliser un réseau de proxy résidentiel pour pouvoir faire le scrapping tout en restant éthque bien sûr donc en ne le faisant pas de façon trop agressive mais en s'assurant de ne pas être bloqué avec le blocage par adresse IP ou un blocage par un capcha aussi c'est quelque chose que j'ai vu régulièrement revenir sur Amazon dans cette partie on va rajouter un petit package qui va nous permettre de lire des informations depuis un fichier qui va être un fichier qui va contenir des variables d'environnement qu'on va pouvoir ensuite charger dans notre script puisque dans ce script on va avoir plusieurs informations qu'on ne souhaite pas mettre endure directement dans le script comme le token qui nous permettra d'utiliser pushover pour faire des alertes sur notre téléphone ou encore les informations d'utilisateur et de mot de passe et l'URL donc complète en fait pour accéder au web Unlocker de Bright data donc je vais rouvrir mon terminal et on va installer le package python-.env qui va nous permettre de facilement lire ces variables d'environnement donc je l'installe et je vais créer un fichier point en à l'intérieur de mon projet donc clic droit fichier nouveau et on va créer ce fichier donc un fichier point en qui par défaut va être caché et on verra bien entendu que c'est le genre de fichier qu'il ne faut pas ajouter dans votre dépo guide si jamais vous en créer un donc qu'est-ce que je vais faire ici je vais mettre mes variables on verra par la suite lesquelles on va créer je vais en mettre une déjà juste pour vous montrer ça va ressembler à ça donc on a ici pushover token égal à une chaîne de caractère pour l'instant on l'a pas encore mais je la mets juste pour vous montrer et ici en haut on va importer donc depuis doend la fonction load.end et on va tout simplement l'appeler au début de notre script on va également importer le module os qui va nous permettre de lire ces variables d'environnement une fois qu'on les a importé avec load.env et ici si je vais lire cette variable donc je vais mettre quelque chose à l'intérieur pour vous montrer on va mettre notre cher Patrick et je vais faire un print de os environ et on va récupérer pushover token et là normalement je vais enlever donc ce qu'on a ici pour ne pas exécuter cette fonction je vais juste faire le print de cette variable je lance le script et là on a bien récupéré Patrick qui est la valeur qu'on a mis dans cette variable d'environnement à l'intérieur de ce fichier donc ça fonctionne bien on va pouvoir utiliser cette technique pour mettre les variables d'environnement dont on va avoir besoin et ensuite les lire et qu'ell ne soi pas donc directement dans notre fichier pour ne pas euh dévoiler en fait tous les secrets dans le script principal qui serait lui hébergé par exemple sur un dépôt git euh qui euh pourrait être plus facilement accessible que le fichier point R qui va lui être stocké directement sur notre serveur dans un endroit beaucoup plus sécurisé donc dans cette partie on va voir comment utiliser le web Unlocker de Bright data qui va nous permettre d'avoir un réseau de proxy résidentiel et également des fonctionnalités pour résoudre les Captur chat puisque là on va avoir les deux cas de figure des fois amazon va bloquer notre IP dans ce cas-ci il faudra passer sur un autre IP donc un autre proxy et des fois ça va être des capchas à résoudre et le web Unlocker va faire tout ça pour nous et vous voyez que le coût est très limité on est à 3 dollars par 1000 requêes 1000 requêes qui ont été réussies donc ça veut dire que si on a une requête qui échoue parce qu'on est bloqué ou parce qu'il y a un capcha qui n'a pas été réussi ça ne va pas compter dans ce nombre de requêes donc 1000 requettes réussies ça fait beaucoup vous voyez que par exemple si on lance notre script une fois par jour ou même 10 fois par jour on peut avoir notre script qui va tourner pendant à peu près 1 an là si on fait trois requêtes par jour ça ferait tro fois 365 donc on arrive à plus de 1000 et ça nous coûterait donc 3 3 dollars sur l'année pour lancer notre script trois fois par jour donc c'est vraiment des coût assez faible pour ce qu'on a besoin de faire il suffit d'économiser 10 € sur le prix de l'objet qu'on va acheter et on est déjà rentré dans nos frais avec ce ce coût de 3 par 1000 requêtes réussies donc on va voir les access paramet ici vous pouvez pouvez également changer la géolocation si vous voulez accéder à une version d'Amazon plus spécifique c'est possible également moi là je vais laisser ça comme ça et je vais aller dans Access parameters et on va retrouver les informations dont on va avoir besoin notamment le host le USERNAME et le password vous avez également la chaîne de caractère complète que vous pouvez copier directement depuis ici vous pouvez également la retrouver dans les exemples de code donc si je clique ici sur le bouton on va avoir des exemples avec l'API ici et avec Python et en fait ce qui nous intéresse nous c'est cette chaîne de caractère ici qui est constitué tout simplement du host du username et du password donc je sais plus exactement dans quel dans quel ordre là je crois que c'est le host ici c'est le mot de passe et ici c'est le USERNAME si je me trompe pas donc on peut copier directement tout ça ici et retourner dans notre script pour l'utiliser donc cette chaîne de caractère que j'ai copié je vais la mettre dans mon fichier d'environnement ici alors pas dans le pushover token on va la mettre dans une variable qu'on va appeler proxy et je vais la mettre ici et on va pouvoir l'utiliser en tant que proxy très facilement dans notre requête ici qu'on effectue on va enlever le user agent on en a plus besoin puisque tout ça va être géré directement par le proxy qui va s'assurer d'avoir quelque chose qui est logique et qui n'est pas détecté comme un script et je vais créer une variable ici qui va contenir mes proxy donc je vais l'appeler tout simplement proxies et ça va être un dictionnaire qui va contenir deux clés une clé pour le HTTP et une clé pour le https même si vous allez voir qu'on va mettre la même valeur dans les deux donc c'est juste pour gérer les deux cas de figure soit les connexions avec HTTP soit avec HTTPS donc il faut mettre re les deux clés pour que ça fonctionne sinon on va avoir une erreur avec request mais à l'heure où j'enregistre cette vidéo en 2024 on est quasiment assurer surtout sur des gros sites comme ça d'être toujours avec des requêtes HTTPS donc ici on va mettre tout simplement notre proxy qu'on va chercher à partir de os environ et qui est dans la variable d'environnement proxy et on va la mettre également ici pour le HTTP donc je la mets là et ne vous inquiétez pas si on retourne voir notre variable d'environnement là vous voyez que ça commence par HTTP et on n pas HTTP ou HTTPS c'est normal parce qu'en fait c'est ici juste la connexion vers le proxy donc la connexion vers le proxy doit être faite en http mais la connexion derrière effectuée par le proxy elle va être faite en https dans le cas d'Amazon puisqu'on va accéder au script en https si on revient ici on est bien avec le https pour accéder à l'URL d'Amazon et donc cette variable proxy je vais pouvoir la passer à ma requête dans un argument qui s'appelle proxy également et on va rajouter un verify é= false sinon on va avoir des problèmes avec le SSL donc le certificat là encore je vais pas trop rentrer dans les détails ça pourrait devenir assez technique mais si vous ne faites pas ça vous aurez une erreur de certificat SSL et ça ne fonctionnera pas dans ce cas-ci on va avoir juste un petit avertissement et on verra par la suite comment on peut enlever cet avertissement s'il vous énerve mais pour l'instant on va laisser ça comme ça donc là je vais retester mon script pour voir si tout fonctionne de nouveau là comme on a vu dans la dernière partie on était bloqué par Amazon donc je vais relancer on va voir si on est plus bloqué normalement ça devrait être le cas donc je relance avec main ici et on va voir donc là on a l'avertissement comme je vous disais qui nous dit que on a mis le verify qui est égal à false donc là c'est un petit peu plus long et on a bien réussi à récupérer le prix c'est un peu plus long parce que forcément on passe par un proxy on a aussi toute la logistique de Bright data qui va s'assurer que on ne fait pas du scrapping trop agressif qui va également s'il y a des capchas ou quoi que ce soit d'autres par exemple donc encore une fois un blocage par adresse IP qui va changer automatiquement tout ça qui va changer de proxy qui va résoudre le capcha donc c'est pour ça que c'est un peu plus long mais avec ça au moins on est assuré de ne pas être bloqué euh et il suffit juste de rester éthique et de ne pas bombarder le site de requê donc vous voyez là ici on a le insecure request warning et on verra par la suite si vous voulez l'enlever comment faire donc voilà pour cette partie vous voyez que c'est très très simple il suffit de récupérer cette variable que l'on a dans bright data donc cette valeur avec le nombre d'utilisateurs le mot de passe et cetera de la mettre dans ce proxy et de l'envoyer avec request dans cet argument proxy pour passer par le web Unlocker de Bright data et s'assurer de ne pas être bloqué pour pouvoir comparer les différentes valeurs du prix au fur et à mesure qu'on exécute notre script il va falloir garder les informations de prix quelque part dans mon cas je vais pas me compliquer la vie on pourrait passer par des bases de données des trucs un peu plus complexes mais c'est beaucoup plus pénible à mettre en place et dans ce cas-ci on a juste une valeur de prix à stocker je vais garder également la date pour savoir à quel moment on a récupéré cette valeur mais c'est vraiment juste deux informations donc je vais pas me compliquer la vie et je vais tout simplement stocker ça dans un fichier Jason qui sera dans le même dossier que le dossier du script donc c'est ce qu'on va faire dans cette partie on va créer une fonction qui va nous permettre d'écrire cette valeur dans un fichier Jason donc ce que je vais commencer par faire c'est utiliser deux bibliothèques la bibliothèque date time qui va me permettre de récupérer la date et l'heure au moment où j'écris la valeur et la bibliothèque patlib qui va me permettre de récupérer le chemin vers le fichier Jason en fonction du chemin du script donc si vous avez déjà vu des formations que j'ai faites vous devez être habitués on va faire une constante ici qui va être être égal au chemin du fichier du script qui est dans la variable file on va créer un objet Pat avec cette variable ici donc qui va être tout simplement en fait le chemin absolu vers le fichier qu'on exécute donc le fichier main.py on va récupérer le dossier parent avec parent donc point parent et on va concaténer tout ça avec le nom du fichier dans lequel on va écrire qui est price.jason donc on a cette variable ici et on peut ensuite créer une fonction qui va écrire ses données à l'intérieur de ce fichier Jason donc je vais faire la fonction je vais l'appeler tout simplement write price to file et on va lui donner une valeur en nombre entier donc un paramètre price ici je mets une annotation de type pour spécifier qu'on veut récupérer un nombre entier un integer et on va déjà vérifier si le fichier existe parce que siil existe on veut modifier on veut ajouter cette valeur au fichier donc je vais tout simplement faire un IF price filepath.exist donc si le fichier existe déjà on va lire les données qu'il contient pour ajouter à ces données donc on va faire le fameux with open et on va ouvrir le price file path en mode read en tant que F et on va également avoir besoin du module Jason donc je crois que je l'ai pas importé voilà on va l'importer ici donc import Jason puisque avec ce module on va lire les données donc je vais récupérer ça dans une variable data et on va faire un json. load du fichier donc F que j'ai récupéré dans cette variable ici si ce n'est pas le cas si le fichier n'existe pas et bien on va tout simplement créer une valeur par défaut donc une liste vide sur cette variable data pour pouvoir ajouter euh la première valeur de prix dans cette liste donc on va faire un data. happened et on va ajouter un dictionnaire qui va contenir deux valeurs donc la première valeur ça va être le prix qui va être égale à la valeur qu'on envoie en argument à Price ici et la deuxième valeur ça va être tout simplement un timeestamp que je vais récupérer à partir de DateTime point now et on va faire isoormat donc c'est un format spécifique qui vous allez le voir contient toutes les informations dont on a besoin donc la date l'heure et cetera et euh et voilà on a besoin juste de ça donc le prix le timeestamp qui va être créé automatiquement à partir de cette variable now au moment où on écrit le fichier et ce qu'il ne reste plus qu'à faire maintenant c'est réécrire ces nouvelles informations à l'intérieur du fichier donc pour ça on va refaire un with open donc on va ouvrir le fichier cette fois-ci en mode write dans une variable F et on va faire cette fois-ci un jason.dump pour écrire les datas dans le fichier avec un ind de 4 pour que ce soit bien formaté et voilà donc je suis aller un petit peu vite mais c'est des choses assez classiques ici je vais pouvoir ensuite tester cette fonction pour m'assurer que ça fonctionne donc je vais comme mon cette ligne là et je vais appeler ma fonction write donc write price to file et on va donner un prix de 200 par exemple je lance le script et on va aller voir si le fichier est bien là donc il est bien ici et on a bien le premier price avec 200 avec le timeestamp donc comme je vous disais on a bien la date 2024 01 20 et ensuite l'heure à laquelle j'enregistre et il est effectivement midi pile à l'heure où je lance ce script on va le relancer une deuxième fois avec une autre valeur pour voir si ça fonctionne bien si on arrive à l'ajouter et là on a bien 150 avec l'heure qui a été mis à à jour donc là on avait 28 secondes là on est à 47 secondes et on a bien mis à jour tout ça se met à la suite et avec le indon de 4 on a bien qui est tout indentter correctement pour que ce soit facilement visible donc voilà pour cette fonction qui nous permet d'écrire les données de se faire une genre de petite base de données pour écrire et garder ses valeurs et par la suite ce qu'il va falloir faire et bien c'est tout simplement récupérer la dernière valeur dans le fichier et la comparer avec la nouvelle valeur qu'on va récupérer depuis Amazon pour vérifier s'il y a eu une différence de prix entre les deux et si c'est le cas et bien tout simplement avertir l'utilisateur qu'il y a eu une baisse de prix sur l'item qui nous intéresse dans cette partie on va faire la fonction qui va nous permettre de récupérer la différence de prix entre le prix actuel et le dernier prix qu'on a récupéré sur le disque donc je vais créer une fonction que je vais appeler tout simplement get price difference et on va lui passer le prix actuel donc je vais faire un paramètre current price qui va être un nombre entier et on va retourner également à un nombre entier qui va être tout simplement la différence de prix entre les deux on va pas retourner un flot parce que s'il y a une différence de 0,53 % ça nous intéresse pas trop on va considérer que on va faire un arrondi et uniquement avertir l'utilisateur s'il y a une différence de prix d'au moins peut-être 5 ou 10 % donc après c'est à vous de voir bien sûr si vous voulez traquer des différences de prix très très faible de l'ordre du moins de 1 % et bien vous pouvez tout simplement éviter cet arrondissement à la valeur supérieure et juste retourner un flot donc ici on va vérifier déjà si le fichier existe parce que s'il n'existe pas et bien on peut pas comparer la valeur actuelle à la valeur précédente donc on va refaire un IF price filepath.existe donc sil existe on va ouvrir ce fichier pour récupérer la dernière valeur et ensuite la comparer donc on va refaire un with open de Price fileepat en tant que F en mode lecture et on va récupérer les données avec jason.load depuis le fichier F et une fois qu'on a récupéré ces données et bien on va créer une variable tout simplement qu'on va appeler previous price qu'on va pouvoir comparer par la suite à current price et ça va être égal à la dernière valeur dans notre liste puisque si je reviens dans mon fichier Jason ici on a bien une liste de dictionnairees donc on récupère la dernière valeur ici et ensuite on va récupérer la valeur associée à la clé price donc je viens ici je récupère le dernier élément et je fais ici un autre crochet pour récupérer la valeur de Price et si le fichier n'existe pas donc on va faire un else et on va tout simplement dire que previous Price est égal à current price tout simplement donc on va juste avoir une comparaison qui va être nul puisque forcément le les deux valeurs seront similaires mais comme ça au moins on aura quelque chose dans previousw price peu importe que le fichier existe ou non et ensuite qu'est-ce qu'on va faire bien on va retourner cette valeur donc là il y a une petite formule mathématique pour récupérer le pourcentage de différence entre les deux donc ça va être le prix donc l'ancien prix moins le prix actuel donc moins current price qui va être divisé par le prix précédent et on va multiplier tout ça par 100 donc là j'ai mis des parenthèses pour bien effectuer cette soustraction en premier donc on va soustraire le prix actuel de l'ancien prix on va diviser tout ça par l'ancien prix et ensuite on va multiplier par 100 et comme je vous l'avais dit on va arrondir tout ça donc je vais faire un round pour arrondir au nombre supérieur cette cette valeur donc si si on se retrouve à 0,9 on va aller à 1 si on est à 9,9 on va aller à 10 et cetera puisque comme je vous l'ai dit on veut avoir une précision sans les décimales donc on va retourner ici un nombre entier et et voilà c'est tout il y a pas besoin de faire quoi que ce soit de plus normalement on a tout géré ici si le fichier existe on récupère les données on fait un -1 price là on pourrait gérer les erreurs pour s'assurer que on a bien un un élément donc normalement si le fichier existe on devrait avoir une valeur dedans on pourrait faire plus de de précision ici mais normalement à moins que j'aille modifier le fichier pour le pour le briser un petit peu euh là on va bien écrire à chaque fois price timeestamp on pourrait protéger aussi ce fichier pour ne pas pouvoir écrire dedans nous manuellement comme ça ça éviterait d'avoir des de potentielles erreurs mais là voilà je considère que les données vont être correctement inscrites à l'in inérieur du fichier puisqu'on va à chaque fois passer par un script et je ne vais pas donc faire plus de vérification à ce point-là ici sur cette ligne de code dans cette partie on va ajouter notre fonction d'alerte qui va permettre d'envoyer une Notification grâce au service pushover sur mon téléphone pour être averti dans le cas où il y a une baisse de prix significative donc je vais coller tout le code de la fonction puisque il y a pas grandchose d'intéressant ici je vais vous montrer ensuite comment aller récupérer les informations nécessaires depuis pushover donc qu'est-ce qu'on a ici tout simplement une fonction send alert qui va envoyer un message qu'on va définir par la suite qui sera probablement quelque chose qui va nous dire tout simplement qu'il y a eu une baisse de prix et nous indiquer le pourcentage de la baisse de prix comme ça après on peut choisir si le pourcentage est suffisamment important ou non pour aller acheter l'item donc là on a une requête POST vers l'API de pushover donc HTTPS api.pushover.net/1 et c'est le pointmessage.jason ici et on va envoyer en data plusieurs informations le token l'utilisateur et le message qu'on veut envoyer donc on va voir tout de suite comment récupérer ces informations depuis pushover donc on a déjà notre clé d'utilisateur qui est disponible ici donc je vais la copier et je vais la mettre dans le fichier d'environnement donc je retourne ici dans mon fichieren et on va créer une autre variable qui va être pushover user et je vais mettre la valeur que je viens de copier et ensuite on va créer une application vous voyez que j'ai déjà pas mal d'applications j'ai des alertes pour docsting j'ai des alertes pour le covid aussi qui était une une ancienne vidéo que j'avais faite sur Youtube pour recevoir des alertes en cas de vaccin disponible si je me souviens bien et on a notre alerte Amazon ici donc si vous n'avez pas encore créé d'application vous pouvez cliquer ICI sur create an application/api token il va vous demander tout simplement un nom la description l'URL c'est optionnel l'icône aussi il faut juste accepter ici pour créer l'application et vous allez arriver sur une page avec les informations dont vous avez besoin et notamment le token ici donc vous pouvez tout simplement le copier et on va le mettre également de la même façon dans notre fichier d'environnement avec la variable pushover token donc je le mets ici j'ai bien toutes les informations dont j'ai besoin pushover token et pushover user et si je reviens dans mon script j'ai ces deux variables que je récupère à partir de os donc le module os que j'ai importé tout au début du script et les variables d'environnement que je récupère grâce au module doenv donc on va tester tout ça je vais vérifier je vais euh hop commenter cette ligne ici et je vais faire un send alert et on va dire bonjour tout le monde tout simplement je vais euh activer le son sur mon téléphone peut-être que vous allez entendre l'alerte et on va de toute façon normalement la voir ici apparaître là on a cinq messages qui ont été envoyés déjà vous voyez que vous en avez 10000 de disponible gratuitement par mois donc là encore on a de quoi voir venir donc je vais lancer le script et on va voir si on reçoit bien l'alerte et voilà donc vous venez peut-être d'entendre le petit bruit de mon téléphone on a bien reçu l'alerte je l'ai relancé une deuxième fois parce que j'étais en mode avion pour enregistrer et euh donc vous voyez que là on est bien passé de de 2 à 4 on était de 5 aussi là on est passé à 7 donc ça correspond bien aux deux tests que j'ai fait donc le premier avec le mode avion que je n'ai pas entendu et le deuxième que vous avez probablement entendu puisque j'avais le téléphone collé au micro donc ça fonctionne on arrive bien à envoyer l'alerte via l'API de pushover sur mon téléphone on arrive bientôt à la fin dans cette partie ce qu'on va faire c'est tout simplement rajouter le loger puisque c'est bien important de toujours avoir un logger surtout quand on va être sur un VP s donc un ordinateur externe auquel on aura pas accès on va pas avir le script se dérouler donc c'est bien important d'avoir ces informations stocker quelque part et pour ça donc on va pas utiliser un fichier Jason comme on l'avait fait pour le prix on va utiliser quelque chose d'un peu plus robuste et donc un logger je vais utiliser le package loguru donc je vais ouvrir mon terminal et je vais l'installer avec PIP install loguru ça va être plus simple que le module de base mais vous pouveiez aussi passer par le module logging les lignes de code vont être assez similaires donc je vais un importer ce loguru ici donc on va dire from loguru import logger et on va créer quelques variables ici on va déjà enlever avec logger. remove le loger qui est ajouté de base pour avoir un petit peu plus de contrôle sur le niveau du loger qui va afficher dans le terminal je vais devoir aussi importer le module 6 parce qu'on va rediriger donc vers le 6 le standard output d'erreur du module 6 avec notre logger donc on va faire loger.ad et on va rediriger vers le STD r comme ceci donc E2R qui signifie erreur et on va mettre le niveau qu'on souhaite avoir donc on va mettre un niveau alors le level il est en minuscule et le niveau il est en majuscule donc level é= Debug et on va ajouter un autre logger qu'on va mettre sur le disque qui va être dans un dossier logs et on va l'appeler tout simplement dbug. log je vais mettre un level cette fois-ci de warning on n pas besoin d'avoir forcément toutes les informations après c'est à vous de voir on peut mettre info aussi à vous de voir le niveau que vous souhaitez avoir de granularité au niveau du loger et on va faire une rotation à part partir de 1 Mbit donc ça veut dire que dès que le fichier atteint ce poids en fait on va faire une rotation et créer un nouveau fichier pour ne pas avoir des fichiers de log trop important donc maintenant qu'on a créé notre loger on va pouvoir l'utiliser à l'intérieur de nos différentes fonctions pour expliquer ce qu'il se passe donc on va faire un loger pointino au début de chaque fonction pour expliquer qu'on passe dans la fonction et qu'est-ce qu'on y fait donc là pour l'instant je vais mettre avec une F string on va dire writing Price et on va insérer le prix ici avec Live string to file là normalement donc on n pas de d'erreur potentielle on n' pas fait de gestion d'erreur ici mais normalement il y a pas de raison qu'il se passe quoi que ce soit on va ensuite aller dans le price difference on va dire donc logger.info de nouveau getting price difference ensuite ici qu'est-ce qu'on a là aussi pas grand-chose si le fichier existe on récupère sinon on donne une valeur par défaut il faudrait peut-être là dans ce casci gérer le cas de figure où on aurait previous Price qui est égal à zé parce qu'on pourrait avoir une Z0 division error donc donc là je pourrais faire un try hop essayer de retourner ça et on va faire un except Z0 division error et là on va le récupérer on va faire un logger pointerror et on va dire tout simplement euh alors on na pas besoin de faire une F string on va juste mettre une chaîne de caractère et on va dire euh la variable previous price contient la valeur 0 division impossible et on va faire un raise de e donc on va relancer cette erreur en fait tout simplement on pourrait faire également raise zero division from E pour avoir un lien entre les deux là dans ce cas-ci je veux juste loguer l'erreur et re relancer cette erreur donc on va refaire un raise là c'est juste pour avoir en fait la possibilité d'insérer ce loger ici en cas de division par zéro euh ensuite qu'est-ce qu'on a d'autre donc le send alert je vais mettre aussi un logger ici info et on va dire sending alert with message et on va insérer le message ici et euh et on peut faire également un try accept ici en cas de problème avec la requête donc je vais faire un try je vais mettre tout ça à l'intérieur on va récupérer la réponse dans une variable et on va faire un responseraise for status et ici on peut faire un except vers l'exception request exception et j'ai remarqué également que cette exception est directement disponible dans le module request donc on n'est pas obligé d'aller chercher dans le sous-module exception on peut faire juste ici on peut le le mettre en fait et mettre directement request request exception comme ceci et là encore on va faire un loggererror en disant que on n pas réussi à faire euh l'alerte donc je vais récupérer l'erreur ici et on va dire euh avec un f string couldn't send alert due to et on va insérer l'erreur ici hop due to cette erreur et on va refaire un race de e également ici et voilà on va remettre un petit peu tout ça en forme avec mon petit raccourci clavier que vous retrouvez ici dans code reformat euh reformat code qui va tout remettre en place notamment ici vous voyez il y avait un petit décalage je l'ai remis automatiquement en place avec ce raccourci et euh bah ça me semble pas mal là on arrive à la fin on a notre fonction main de base euh là on va voir on va probablement encore modifier un petit peu tout ça ici peut-être faire une autre fonction intermédiaire donc là je vais pas mettre de loger pour l'instant ici euh et on va voir ce qu'on fait par la suite si on modifie cette fonction ou non mais pour l'instant je vais rester à ça avec les loggers que j'ai ajouté dans les trois autres fonctions ici pour vérifier que ça marche je peux relancer le print ici de ma fonction main pour vérifier si on arrive toujours à récupérer le prix et qu'on a bien le loger point info qui se fait et je relance donc là on devrait avoir le loger qui nous affiche les informations on va attendre un petit peu et et et et donc est-ce qu'on arrive bien déjà à récupérer le prix normalement oui et on a aucune info alors pourquoi oui parce que en fait tout simplement je crois oui bah voilà c'est parce que j'ai pas mis de loger dans cette fonction main et pour l'instant on on nécrit pas les données sur le disque ici si je vais voir voilà on a toujours nos anciens prix puisque effectivement il faut qu'on modifie donc cette fonction qu'on en fasse une autre comme je vous disais pour pouvoir récupérer le prix et cetera donc je va juste faire un loger Point Info ici pour vérifier que ça fonctionne bien on va faire un test hop voilà on a bien le loger qui s'affiche ici là si on va voir on a bien donc le fichier de log qui est créé mais avec rien pour l'instant je vais faire un error pour voir si ça fonctionne et là voilà on a bien l'erreur qui s'affiche donc ça fonctionne je vais l'enlever de ce fichier je vais enlever ce code ici on a bien notre loger qui fonctionne à la fois dans le terminal et dans notre fichier de log et on va pouvoir passer à la dernière fonction normalement pour que ce script fonctionne correctement pour qu'il aille rechercher le et qu'il l'écriv également et qu'il puisse faire la comparaison pour nous avertir en cas de différence de prix dans cette partie on va terminer notre script je vais déplacer je pense tout ça dans une autre fonction en fait je vais renommer tout simplement cette fonction puisque cette fonction qu'est-ce qu'elle fait elle va récupérer le prix donc je vais l'appeler tout simplement get current price et on va lui passer plutôt que de passer une URL on va rendre notre script un peu plus un peu plus robuste en passant juste le assine comme ça par par la suite on pourrait imaginer que cet assine on le passe directement dans le terminal via le module 6 qu'on pourrait donc récupérer avec 6. arc V on pourrait récupérer le dernier argument qui est passé après le script et comme ça ça nous permettrait de faire quelque chose du genre Python 3 main et de donner l'assine ici dans le terminal si jamais on voulait avoir plusieurs scripts avec différents assin ça serait voilà ça serait plus pratique comme ça pour l'instant je vais pas je vaux pas faire tout ça mais je vais quand même prévoir mon script pour que ce soit possible donc là on va faire get cur Price et à la place de URL du coup je vais mettre ici assine qui va être une chaîne de caractère et là dans l'URL je vais reprendre tout ça en fait ici et je vais le mettre directement comme ceci et on va juste insérer le hasine qui va être passé à la fonction directement comme ça donc cette fonction d'ailleurs on a encore des petits trucs à modifier on a plus besoin d'écrire sur le disque on va également gérer les erreurs donc là on va faire un try except avec la requette en cas de problème donc un try avec cette réponse on va faire un response. race for status s'il y a un problème donc on va faire un request point request exception as e et on va faire un loger en disant qu'il y a eu une erreur donc par exemple on va mettre un message qui dit couldn't fetch content from et là on va mettre l'URL alors l'URL je l'ai mise comme ça ici je vais faire une variable intermédiaire donc je refactor option commande V sur Mac sinon vous faites un clic droit et vous allez dans refactor pour introduire une variable donc c'est un petit raccourci que j'utilise très souvent et là il ne semble pas être très coopératif alors je sais pas pourquoi introduce variable ok il veut pas normalement il va il fait la chose pour moi automatiquement donc je vais mettre ici URL on va mettre la chaîne de caractère ici normalement il fait cette opération automatiquement euh là je sais pas pourquoi ça n'a pas marché et donc cette url ici on va la mettre à l'intérieur de notre F string donc on va dire qu'on a pas réussi à récupérer le contenu à partir de cette URL à cause de l'erreur qu'on va mettre ici donc dans notre chaîne de caractère également l'erreur qu'on a récupéré ici et on va lever de nouveau cette erreur à partir de l'erreur qu'on a récupéré dans cette variable e donc ça c'est pour la gestion de cette requête qui est potentiellement problématique on sait jamais on peut avoir des erreurs 404 si jamais la S n'est pas trouvé ou euh ou quelque chose d'autre ensuite qu'est-ce qu'on va avoir comme erreur potentielle on avait dit ici àoir donc on peut avoir le price note qui n'est pas trouvé là je fais un price note point text donc on pourrait avoir potentiellement un attribute error je vais plutôt passer par un IF ici je vais regarder si on a le price node donc si on a price node on va retourner ça ici et si ce n'est pas le cas ça veut dire que on n pas réussi à trouver l'information sur la page donc là encore je vais faire un loger.error et on va faire un string en disant couldn't find price in et on va remettre l'URL ici et on va faire un raise value error donc là on va lever une erreur puisque value error comme ceci là on va lever une erreur parce que on fait juste une vérification ici on fait pas un try accept donc si jamais on a un problème on veut là dans ce cas-ci faire planter le script pour indiquer qu'on a eu un problème et on verra par la suite comment vérifier et récupérer ses erreurs s'il y a une erreur comme celle-ci pour être avertie et aller vérifier pourquoi ça a planté donc là on va dire on va faire la même chose on va faire error message message on va le mettre ici error message on va dire à quoi c'est égal et on va le remettre ici aussi error message message comme ceci donc je fais une variable je la logue et je fais un raise de cette value error ici en cas de problème on pourrait aller encore plus loin comme je vous dis ici si euh là on pourrait avoir une un problème également avec le le price node imaginez que le texte retourne autre chose qu'on arrive pas à le convertir en int on aurait dans ce cas-ci une erreur type error si je me trompe pas donc on pourrait tester ça aussi bon après de toute façon on va voir avec les outils qu'on va mettre en place par la suite si on arrive pas à récupérer le prix ici euh ça sert à rien d'envoyer une alerte parce que si on arrive pas à récupérer le prix ici ça sert à rien d'aller plus loin euh on aura pas la valeur et ça sert à rien de la comparer on peut pas comparer quelque chose qu'on n' pas donc ici si ça plan sa plante on va avoir une alerte avec les outils qu'on va mettre en place pour indiquer que notre script n'a pas bien fonctionné donc après on peut décider d'aller voir est-ce que c'est Amazon qui a changé le html est-ce que il y a eu un autre problème non identifié ou quoi que ce soit mais ici voilà ça sert à rien d'aller plus loin donc je vais pas faire un try accept pour gérer cette erreur potentielle on va juste laisser cette erreur arriver si c'est le cas donc maintenant qu'on a refait un petit peu cette fonction on va faire une nouvelle fonction main qui là va avoir la logique principale de notre script donc je vais enlever ça je vais enlever ça aussi et on va appeler main ici et qu'est-ce qu'on va avoir ici comme logique et bien la logique principale qui va consistait à déjà récupérer le prix actuel donc je vais faire une variable current price qui va être égale à get current price le Hine on l'a ici donc je vais le je vais le passer je vais le passer à main en fait aussi donc on va faire un paramètre ici qui va être une string et là on va le passer et comme ça hop on va le passer directement à notre fonction get current price ensuite qu'est-ce qu'on va faire on va écrire cette valeur sur le disque mais avant ça on va récupérer la différence de prix parce que si on écrit déjà la valeur sur le disque on va comparer la valeur actuelle avec elle-même parce qu'on aura déjà écrit sur le disque et on va récupérer la dernière valeur qui va être celle-ci donc bien important ici l'ordre on va déjà récupérer la différence de prix donc get price difference avec le current price é=al current price et si jamais on n pas de prix si on n pas le fichier qui existe ça on avait déjà prévu voilà get price different si on lance le script pour la première fois le fichier n'existera pas et on va juste avoir le previous Price qui va être égal au current price donc on aura une variation de zéro et on ne va tout simplement pas envoyer d'alerte donc ce n'est pas un problème et ce qu'on va faire c'est écrire donc ce prix sur le disque donc en mettant price égal à current price et il reste plus qu'à vérifier s'il y a une différence de prix donc on va faire if price difference là on peut vérifier on peut dire est-ce qu'elle est plus grande que 10 que 5 donc là c'est à vous de mettre la barre où vous le souhaitez on pourra mettre tout simplement zéro euh donc s'il y a une différence de prix on va faire send alert et et on va envoyer un message qui va dire price has decreased byy et on va mettre le pourcentage hop buy price difference et on va mettre un symbole pour pour que ce soit bien clair on pourrait même mettre hop moins bon après on dit decreased ici donc c'est déjà assez assez clair que ça a descendu de par exemple 10 20 ou 30 %. donc normalement c'est bon on va pouvoir tester ça on va tester avec des valeurs fictif parce que là euh pour l'instant si je lance le script on aura peut-être pas de différence donc là qu'est-ce qu'on a une valeur de 150 si je me souviens bien on avait une valeur de 234 sur le site donc bah je vais je vais lancer le script en l'état normalement on devrait avoir ici une alerte parce qu'on va avoir la dernière valeur qui est de 150 la valeur qu'on va récupérer va être 234 si mes souvenirs sont bons donc on a une quand même une grosse différence de prix ici qui va assurément être plus grande que zéro donc ça devrait fonctionner je vais enlever de nouveau mon mode avion et vous faire écouter pour voir si on a bien l'alerte donc on croise les doigts normalement on a bien tout fait je lance le script et on va vérifier si on a bien tout qui est fonctionnel on va vérifier le loger également donc on a bien ça et 4 price difference right price 234 et là il semble qu'on a un problème sur le la différence de prix parce qu'on n pas détecté de différence donc là je regarde ici on a 234 ok donc il y a eu un petit souci je pense sur la différence de prix on va vérifier ce que ça donne ici donc je vais commenter cette ligne on va mettre une valeur fictif ici pour ne pas faire trop de requête on va dire donc que le col Price est égal on va mettre 500 euh ah oui c'est parce qu'en fait je pense que c'est une différence oui c'est une augmentation ici en fait c'est tout ça c'est simplement pour ça donc on va mettre je pense si ma si mon intuition est bonne on va directement tester ça on va dire que le prix était à 500 donc la dernière valeur à 500 là on va récupérer de nouveau 234 et donc je pense que cette fois-ci on va bien avoir l'alerte donc je reteste pour voir si mon intuition est bonne je relance et là effectivement j'ai bien l'alerte donc ça me dit alerte Amazon price has decreased by 53% donc on va voir si c'est bien ça effectivement 53 % donc c'est cohérent et c'est c'est bien donc le comportement attendu puisque la price difference ici c'est une c'est une différence donc qui se fait que dans le sens négatif si je puis dire puisque si on a une augmentation du prix on ne va pas rentrer dans cette condition nous ce qu'on regarde ici c'est juste une diminution du prix euh on pourrait aussi tester une augmentation du prix si ça vous intéresse d'acheter des choses plus chères que que prévu mais ici ça va bien être une diminution donc quand on est passer de 150 à 234 ça n'a pas lancé l'alerte c'est logique et quand on passe de 500 à 234 là on a bien une diminution de 53 % ce qui est assez logique 50 % on serait à 250 donc là un peu plus que 50 % ça semble être la valeur attendue donc voilà pour notre script normalement tout est bon on a la gestion des erreurs on a notre fonction principale on peut envoyer laassne ici directement donc c'est bien optimisé on a nos gestions d'erreurs ici avec le loger on va aller voir les fichiers de log ici là on a rien de nouveau parce que c'est normal on a mis le fichier de log avec un niveau à warning donc warning error critical que des messages problématiques on pourra le mettre à info si on voulait vraiment tout loguer donc là si je relance avec ce niveau vous allez voir qu'on va récupérer tout dans le fichier de dbug donc que ce soit les infos mais aussi les erreurs et là on voit bien qu'on a les infos également moi je vais le laisser à warning là je souhaite juste avoir les informations en cas de problème et ne pas surcharger le fichier de log avec les les valeurs d'info à savoir que généralement ce qu'on fait c'est d'avoir plusieurs fichiers on peut avoir un fichier juste pour les erreurs un fichier pour le dbug avec les infos un peu plus précises donc là c'est à vous de voir c'est quelque chose qu'on voit assez régulièrement vous allez avoir un fichier par exemple er RR comme ça point log qui va contenir les erreurs en cas de problème comme ça vous pouvez directement voir s'il y a eu des problèmes ou non lors de l'exécution du script dans cette partie et les prochaines parties on va s'attaquer à la mise en ligne de notre script sur un serveur privé virtuel pour que notre script tourne en continu et qu'on ne soit pas obligé de l'héberger sur notre propre machine pour ça je vais utiliser un VPS de infomaniaque vous pourrez retrouver dans la description un lien d'affiliation qui vous permet également de créer un VPS sur ce service si vous voulez savoir comment créer le VPS et comment y accéder je vous redirige vers cette autre vidéo que j'avais faite sur YouTube dans laquelle je montre comment commander le VPS comment le créer et comment ensuite se connecter à ce VPS avec une clé SSH dans mon cas ce VPS existe donc déjà et je peux me connecter en SSH en entrant le nom d'utilisateur et l'adresse IP une fois connecté sur ce VPS on peut voir en faisant un ls que j'ai seulement un dossier qui correspond à l'autre projet que j'avais déjà fait pour créer une application avec flask et je vais pouvoir ainsi envoyer grâce à ma connexion SSH des fichiers vers ce VPS on pourrait créer un dépôt git dans ce casci je n'ai qu'un ou deux fichiers envoyés on va envoyer le fichier main.py et on va également envoyer un fichier pour installer les dépendances les librairies donc le fichier requirements.text qu'on va créer et envoyer pour l'instant ce que je vais faire c'est juste envoyer le fichier principal donc le main.py et le fichier d'environnement donc pour ça je vais ouvrir un terminal sur mon ordinateur je vais me rendre dans le dossier du projet donc dans document eCom notifier et je vais utiliser un autre utilitaire qui est SCP qui va me permettre d'envoyer des fichiers grâce à ma connexion SSH depuis mon ordinateur jusqu'à un serveur distant donc dans ce cas-ci je vais envoyer le fichier main.p et on voit ici la ligne que j'avais déjà faite qui s'affiche donc on a bien ici le nom d'utilisateur @as l'adresse IP deux points et l'endroit vers lequel on souhaite envoyer cet élément donc je vais valider avec entré et je n'ai pas encore créé le dossier donc il va falloir le créer avant je vais créer le dossier avec mkadir ICOM notifier et on va refaire la procédure donc je relance et voilà vous voyez que c'est très rapide puisque ce n'est qu'un petit fichier donc si je me rend rend dans eCom notifier maintenant j'ai bien le fichier main.py qui est ici et je vais faire la même chose avec le fichier point en dans le même dossier à la même adresse donc je relance en changeant juste le nom du fichier et là je me retrouve bien avec le fichier en si je fais un ls- a donc pour bien avoir les fichiers cachés puisque le LS simple ne va pas afficher les fichiers cachés et là je retrouve bien mon point ENF qui est caché puisque le fichier commence par un point donc voilà pour les deux éléments principaux qu'on avait besoin d'envoyer et on va tout de suite également créer le fichier euh requirements.txt donc je vais sourcer mon environnement là je suis dans un terminal en dehors de pycharm si je le fais à l'intérieur de pcharm mon environnement sera déjà sourcé on le voit ici donc ce que je vais faire ici c'est sourcer à partir de ven/bin/activate mon environnement et je vais faire un PIP freeze de requirements.txt dans ce même dossier si je fais un CAT de requirements. txt on voit que j'ai bien les différentes bibliothèques dont j'ai besoin donc on avait selectolx python den loguru et cetera donc je vais envoyer également ce fichier vers le VPS donc je vais faire scpquirements.txt et je remets la ligne au complet donc voilà pour tous les fichiers dont on avait besoin il ne me reste plus sur le serveur qu'à recréer cet environnement donc je vais utiliser Python 3 et on va faire TMV en et on va créer un dossier enve à l'intérieur de ce dossier eCom notifier et on va ensuite pouvoir sourcer cette environnement donc en/bin/activate et ensuite on fait PIP install- r require .txt pour installer les bibliothèques à partir du fichier qu'on vient d'envoyer donc tout a été bien installé et je vais pouvoir tester mon script sur ce serveur en faisant Python 3 main.py assurez-vous de bien avoir sourcé votre environnement donc pour avoir accès à toutes les bibliothèques qu'on a installé je valide avec entrée normalement je n'ai rien besoin de mettre de plus donc là on a le petit avertissement qu'on verra comment enlever et on devrait avoir le loger avec voilà l'info getting price on a le price à 234 si je fais un LS on devrait avoir notre fichier price.jason qui apparaît donc je vais faire un CAT de price.jason on voit bien le prix avec le timestamp et dans les log on a le fichier de log qui ne doit rien contenir parce que si je ne me trompe pas voilà on a rien dedans effectivement parce que il n'affiche que les messages d'erreur et là on en a pas eu donc voilà pour l'envoi des fichiers comme je vous dis on pourrait le faire avec un dépo guide si on souhaitait avoir une synchronisation plus facile là dans ce cas-ci j'ai deux ou trois fichiers je pense que ça suffit de le faire comme ça avec un transfert je ne compte pas modifier ce script très réguliè donc ça peut suffire avec ceci et c'est beaucoup plus simple dans cette partie on va créer une tâche récurrente qui est sur Linux un cron job donc cron job comme ceci qui va en fait exécuter notre script à intervalle régulier alors il existe beaucoup de sites qui vous permettent de voir comment créer ces expressions il y a chront top Guru chronitor qui sont bien connu donc chron Tab goru par exemple vous allez avoir ici toutes les valeurs que vous pouvez utiliser on va tester nous dans notre cas avec des astérisques ici ce qui signifie qu'on va le faire toutes les minutes par la suite on pourra mettre par exemple slash 30 ici ce qui veut dire qu'on va exécuter le script toutes les 30 minutes on pourrait faire toutes les 15 minutes et cetera on pourrait le faire également tous les jours donc je vous laisse explorer tout ça pour la syntaxe des chron job nous dans ce cas-ci on va voir comment créer cette tâche chron pour l'exécuter sur notre VPS donc le chron Tab on va pouvoir l'ouvrir en faisant chron Tab T e donc T e pour edit vous pouvez faire t l également pour afficher ce qu'il contient moi vous voyez que j'ai déjà la ligne qui est inscrite ici donc la première fois que vous le faites il est possible que ça vous demande de choisir un éditeur donc si vous faites chrome tab- e et que vous avez un message comme celui-ci vous pouvez choisir entre nano ou vim moi je vous conseille d'utiliser celui que vous préférez nano est un peu plus simple comme c'est indiquer vim il y a plus de gens qui le plus de gens avancés qui l'utilisent généralement donc à vous de voir vous allez voir que les deux sont assez faciles d'utilisation donc moi dans ce cas-ci j'ai choisi nano pour vous montrer puisque c'est celui qui est le plus simple et probablement celui que vous allez donc choisir d'utiliser si vous n'êtes pas familier avec ces outils donc on va aller tout en bas là il y a plein d'indications si je descends ici on voit que j'ai déjà donc le chrome Tab qui est fait il suffit que j'enlève le le petit diz ici pour l'activer donc je vais vous montrer comment on peut faire pour récupérer les information dont on a besoin on va avoir besoin du chemin complet vers l'exécutable de Python et du chemin complet vers notre script donc je valide je reviens donc dans mon dossier ici et je peux faire un Real path de main.px qui va m'afficher le chemin complet vers mon fichier Py et on peut faire un witch de Python 3 en ayant bien activé notre environnement là on voit qu'on a ENF devant ce qui signifie qu'il est bien activé sinon on peut l'activer avec source en/bin/activate et ensuite si on je fait witch Python 3 on va bien avoir le chemin complet vers Python 3 donc la commande complète dont on a besoin c'est celle-ci le nom de l'exécutable le chemin vers l'exécutable et ensuite le chemin ici vers mon script main.py donc ça c'est la commande au complet qu'on a besoin de lancer et je vais revenir donc sur mon chrome Tab t e pour éditer si je descends tout en bas euh vous pouvez donc créer une nouvelle ligne on va mettre dans ce cas-ci toutes les minutes donc je mets C astérisques comme ceci et je mets ensuite le chemin complet vers l'exécutable et le chemin complet vers mon script je sauvegarde en faisant contrôle X et je vais sauvegarder en appuyant sur la touche Y pour valider il me demande si je souhaite euh écraser je j'appuie sur Entrer pour valider et c'est bon si on refait un chrome tab- l on voit qu'on a bien notre ligne qui a été correctement ajouté ici et donc qu'est-ce qui se passe ici bien normalement maintenant c'est automatique notre script va s'exécuter toutes les minutes donc ce qu'on peut faire ici c'est aller vérifier le fichier price.jason donc si je fais un CAT de price.jason vous voyez qu'on a deux valeurs donc on a la première valeur qui a été exécutée à 14h17 quand j'ai lancé le script tout à l'heure et là on a une nouvelle valeur à 14h20 ce qu'on peut faire c'est un watch de tail euh et on peut mettre le nombre de lignes on va mettre 100 pour être large euh price point Jason donc tail ça va afficher la fin du fichier donc les 100 dernière ligne du fichier ça devrait être suffisant et watch ça va répéter l'opération toutes les 2 secondes par défaut si ma mémoire est bonne donc je valide et là on voit qu'on a déjà une nouvelle entrée ici donc price 234 timetimestamp avec 14h23 euh donc il a été exécuté 14h23 et 6 secondes là on est à 14h23 et 23 secondes donc on va attendre une nouvelle rotation à partir de 14h24 on va avoir une nouvelle entrée puisque quand on fait toutes les minutes ça va être à la minute pile donc à 14h24 le script va être exécuté probablement que le temps que le script roule il y a quelques secondes qui vont se passer pour pouvoir se connecter sur le proxy de Bright data récupérer les informations et les écrire dans le fichier donc on va attendre encore quelques secondes pour que on arrive à 14h24 et là on a normalement tout qui est déjà fonctionnel c'est-à-dire que si jamais on avait la chance d'avoir une chute de prix à ce moment-là entre les deux logs et bien je recevrai déjà une alerte sur mon téléphone je pense pas qu'on va avoir cette chance là mais saiton jamais donc là on devrait arriver à la nouvelle Lig qui va s'écrire vous allez voir c'est assez magique ça devrait arriver à moins qu'il y ait un problème il se peut qu'il y ait des problèmes si notre IP est bloqué du côté de Bright data on va voir comment enlever ça mais là non ça a bien marché donc on voit qu'on a cette ligne qui est apparue et qui a été rajoutée 14h24 donc là ça a été un peu plus long mais ça fonctionne bien donc je vais sortir de cette commande avec contrôle C pour arrêter on va éditer notre Crown Tab pour ne pas faire de requêtes inutiles pour le moment donc je vais remettre un diè ici je valide avec contrô X je save avec y je valide avec entrée alors si ça ne marche pas je vous ai dit que ça peut être bright data qui va bloquer l'IP de votre VPS donc pour ça il faut aller indiquer que il ne va pas être dans la liste des IP bloqués donc je vais aller dans mon tableau de bord sur proxy et scrapping infrastructure on va aller sur notre web Unlocker et vous allez voir si je me trompe pas c'est dans Access parameter là vous voyez qu'on va avoir les blocked IPS et le allowed IPS donc blocked IP ça se peut que vous voyez votre IP ici qui est l'IP en fait de votre serveur info maniaac donc cette IP ici alors si jamais vous voyez cet IP qui est dans la liste des IP bloqués euh je vais l'ajouter pour vous montrer ce que ça donne donc si vous avez votre IP comme ça il faut l'enlever de la liste des IP bloquées et l'ajouter dans la liste des IP autorisées donc ça c'est des mesures de précaution qui sont mises en place vous pouvez choisir d'accepter ou de bloquer certains IP vous pouvez aussi choisir les hostn qui vont être disponibles donc si vous voulez cibler ou bloquer certains site avec votre web Unlocker c'est possible et donc le fait de rajouter votre IP ici ça vous assure que euh vous n'aurez pas de problème et que votre VPS ne sera pas bloqué si jamais attention vous faites des tests de nouveau en local il faudra bien ajouter votre IP donc l'IP de votre ordinateur local vous pouvez le trouver sur Google en tapant quel est mon IP vous allez avoir plor de site de nouveau pour vous donner cette information et une fois que vous récupérez cette adresse IP vous pouvez ajouter votre IP locale dans les allowed IPS sinon il ne va pas être accepté lorsque vous allez tester votre code en local donc normalement c'est tout bon je vais revenir ici vous pouvez enlever le Diaz et vérifier que tout fonctionne et on va faire un test plus tard aussi pour vérifier queon a bien une alerte toujours en utilisant une autre URL et en modifiant l'information pour voir si tout fonctionne avec une des données factices si vous voulez enlever le petit avertissement pénible qu'on a quand on lance notre script qui nous indique ici unverified HTTPS request on peut l'enlever donc je vais utiliser vim directement ici pour aller modifier mon script donc on va faire vim main.py j'appuie avec Entrée pour valider je me retrouve dans le script et là je vais juste ajouter les lignes directement ici pour ne pas avoir besoin de refaire un envoi vers mon serveur donc ici j'appuie sur I pour rentrer en mode d'insertion on va importer une bibliothèque on va la mettre en haut puisque c'est une bibliothèque de la librairie standard qui est URL lib 3 et ensuite quelque part ici on va utiliser la ligne qui va permettre d'enlever cet avertissement qui va être URL lib 3.dable- warnings et là on va mettre URL lib 3.exception insecure request warning donc j'ai j'essaie de m'assurer de ne pas avoir faire de faute parce que là je n'ai pas d'autocomplé avec vim donc normalement c'est bon URL 3 warnings avec un S je pense que c'est bon donc on va essayer on appuie sur échappe pour sortir du du mode d'insertion et on fait deux points WQ pour sortir en mode ride donc pour écrire les changements dans le fichier je vais relancer le script pour vérifier et là on attend un petit peu et ça semble fonctionner effectivement on a plus le message d'erreur qui s'affiche et on a juste les infos donc c'est parfait ça m'évite d'avoir ce long log à chaque fois que je lance le script et d'avoir uniquement les informations ici qui m'intéressent dans cette partie on va boucler notre script en rajoutant un utilitaire qui est bien pratique il y en a plusieurs qui utilisent là il n'y a aucun sponsor ou lien d'affiliation dans cette partie c'est centry que j'utilise que j'aime beaucoup que j'utilise sur doc string vous pouvez voir que j'ai le projet ici avec un bon taux de ce qu'on appelle les crash free sessions donc des sessions sans aucun problème donc on est presque à 100 % ici ça me permet ici dans le cadre de docsting de récupérer toutes les tous les problèmes toutes les erreurs qu'il y a sur le site donc dès qu'on a une erreur qui est levée sur le projet de Django j'ai un historique ici des erreurs je peux les marquer comme résolu en attente et cetera ça me permet d'avoir un historique et un suivi des erreurs à régler donc sur l'interface je vous laisse créer un compte vous allez avoir pas mal de latitude avec la version gratuite déjà qui vous permet de reporter un bon nombre d'erreur moi pour docstring pour vous donner une idée je suis encore sur le plan gratuit je n'ai pas eu besoin de payer quoi que ce soit depuis les les nombreuses années que je l'utilise donc ce qu'on va faire c'est dans les projets créer un nouveau projet et ensuite on va installer les bibliothèques nécessaires dans notre projet et ce que ça va faire c'est que ça va nous permettre d'être averti quand il y a des erreurs vous allez voir qu'on peut également lier pushover donc le fameux pushover qu'on utilise pour recevoir les alerte de prix on peut également le lier ici pour avoir une alerte sur notre téléphone quand il y a une erreur c'est là encore quelque chose que que j'utilise sur docsting donc quand il y a une erreur critique sur le site je reçois une alerte directement sur mon téléphone qui est qui va bypasser tous les mode de non dérangement donc le mode à part le mode avion bien sûr qu'on peut pas on peut pas aller on peut pas aller au-dessus du mode avion mais quand je suis en ne pas déranger ça va quand même passer par-dessus et parce que j'ai mis une une alerte spécifique sur pushover qui va passer à travers ces notification donc ici quand on va créer notre projet on va choisir ce qu'on veut vous voyez que vous avez des configurations directement pour des services bien connus comme Django fast API flask même du react ou d'autres choses hors de de l'écosystème python nous c'est juste un script Python donc on va sélectionner python ici on va dire de m'alerter sur chaque nouvelle issue et je vais l'appeler ici donc je vais donner un nom on va dire euh ICOM notifier dans la team doc string donc je crée le projet est-ce qu'on utilise un framework non c'est du python pur euh on utilise request mais ce n'est pas un framework c'est juste une bibliothèque donc je fais skip et là on va avoir le code à utiliser donc notamment le l'installation en fait du SDK donc je vais copier le code ici et je vais retourner dans mon pycharm en pour l'installer donc dans le terminal ici je vais coller cette ligne pour installer le centry SDK et on va aller copier les lignes qu'on a ici donc de nouveau je copie et je vais mettre ça tout en haut de mon script pour avoir le loger de sentry donc je le mets ici import sentry SDK là je vais enlever les commentaires pour enlever les lignes inutiles et là on a une longue adresse que vous pouvez également rajouter si vous le souhaitez à l'intérieur de votre fichier d'environnement donc on peut faire ici os environ et mettre par exemple century DNS et puis mettre cette valeur dans le fichier d'environnement si vous voulez la protéger également même si ce n'est pas des choses très critiques ici mais bon c'est quand même mieux je pense parce que quelqu'un pourrait utiliser cette cette url pour la mettre dans son propre projet et et vous causer du trouble en envoyant des des logs qui n'ont rien à faire ici donc moi je vais le laisser comme ça ici et on va faire un test donc le test qui nous conseille de faire d'ailleurs je crois voilà c'est de faire une division par 0 donc ici à la place de faire le main on va tout simplement faire 1 divis par 0 et on va lancer le script pour vérifier que on a bien l'erreur qui est loguée donc je vais aller ici dans take me to issues on va cliquer ici pour avoir les updates en real time donc je vais mettre ça à droite de mon écran je vais mettre ça à gauche je lance le script et là normalement voilà on a la Z0 division error centry attempting to S to send pardon de pending events donc on va revenir ici et ça devrait apparaître dans peu de temps pour nous avertir qu'il y a eu un problème dans notre script et voilà vous voyez que c'est assez rapide il nous dit donc ilil y a 16 secondes donc c'est précis ça fait à peu près effectivement 15 secondes que j'ai lancé le script et on voit ici toutes les informations qu'on a besoin on a le bot de code qui pose problème on a plein d'autres informations comme la variable file qui nous permet de voir quel est le fichier qui a déclenché l'erreur le module et cetera donc plein d'informations importantes ici on voit le nom de l'erreur on voit les variables d'environnement aussi quelle version de Python est utilisé donc centry c'est vraiment très très bien pour ça vous pouvez analyser très finement ce qui se passe et une fois que le problème est résolu on peut le sélectionner et cliquer sur resolve pour dire que le problème n'est plus un problème actif et si je rafraîchis la page ici vous allez voir que le problème aura disparu puisque là on filtre seulement les éléments qui ont été unresolved donc c'est parfait ça marche bien et je vais pouvoir du coup enlever ce cette division par zéro remettre mon main ici et envoyer de nouveau mon script sur mon serveur donc je vais ouvrir un nouveau terminal je vais me redéplacer dans Documents eCom notifier et on va refaire un SCP on va refaire en fait déjà le PIP freeze donc je vais sourcer mon environnement hop source van ensuite on va faire un PIP freeze dans le requirements.txt pour ajouter le les bibliothèques de entry et ensuite on va faire un SCP de requirements et on va faire un SCP de notre main.p qu'on a changé également donc si je reviens là après dans le ICOM on va faire un PIP install de air requirements en ayant en bien activé notre environnement virtuel donc c'était déjà le cas donc c'est bon il a bien détecté sonentry il l'a installé et si je vais voir mon main.py on devrait bien avoir si je reviens a-dessus le centry SDK donc ça fonctionne parfaitement et je peux désormais réactiver mon script dans lescon Tab et avoir cette gestion donc des erreurs avec centry qui me permet d'être averti s'il y a un problème vous pouvez aussi aller voir donc dans les settings ici vous allez avoir des intégrations donc si je vais dans intégration vous allez voir que moi j'ai pushover qui est déjà activé et qui est euh qui est ajouté à mon projet doc strring donc là vous pouvez cliquer sur Add to project pour l'ajouter à un autre projet comme ICOM notifier qu'on vient de créer et il suffira ici d'ajouter donc comme on l'a fait pour envoyer des alertes le user key le API key donc une autre application que vous pouvez faire pour envoyer des alertes vous pouvez utiliser la même que vous avez utilisé pour faire le l'envoi d'alerte de notre application mais vous pouvez aussi en faire une autre et là comme ça vous aurez automatiquement des alertes envoyées via pushover quand il il y a un problème sur votre site donc voilà on arrive à la fin il ne me reste plus qu'une chose à tester c'est quand même que le script continue de fonctionner bien donc ce que je vais faire en fait c'est modifier le prix ici donc là encore je vais utiliser vim pour modifier la dernière valeur qu'on a donc je descends un petit peu tout en bas et là on va mettre une valeur un petit peu plus un petit peu plus haute donc on va on va tricher on va mettre un prix de 500 je sors et je sauvegarde et je vais réactiver mon Crown Tab donc je fais Crown tab- e et je vais réactiver mon Tab qui se lance toutes les minutes et donc là normalement on va avoir une baisse de prix puisque on va passer de 500 à 234 donc c'est suffisant pour déclencher l'alerte donc je veux juste vérifier avec tous les changements qu'on a fait depuis que ça fonctionne toujours bien et que j'ai bien l'alerte qui arrive sur mon téléphone donc je vais essayer de pas trop parler et on va voir si on entend de nouveau la notification toute façon moi je vais la voir je vais je vais pas vous mentir hein si ça n'arrive pas je vous le dirai et on va voir quel est le problème là j'attends un petit peu on va faire on peut faire un watch comme on l'avait fait du tail de donc on va faire on va refaire un N 200 sur notre price.jason pour voir voilà quand est-ce qu'on aura des nouvelles informations et voilà vous voyez que j'ai à peine ouvert le fichier et on a bien donc j'ai bien l'alerte price has decreased by 53 %. donc ça fonctionne si je sors de ça et que je fais un tail de price point Jason tout simplement on voit qu'on est bien passé de 500 à 234 donc ça fonctionne et la prochaine itération dans une minutes je ne devrais pas recevoir d'alerte parce que là on va comparer 234 avec 234 donc il n'y aura pas de de baisse de prix mais vous voyez que ça fonctionne bien on a bien les erreurs qui sont loguées je vais faire un tout dernier test je vais aller dans vim euh avec mon main.py et on va faire une petite une petite erreur on va changer par exemple l'adresse ici donc je vais aller ici je vais mettre n'importe quoi dans le https et ça devrait provoquer cette erreur request exception donc je sauvegarde je lance on va attendre que le chrome Tab relance euh le script et on devrait avoir cette erreur donc je vais aller voir dans sentry je vais retourner dans les issues de ICOM notifier et là on va encore attendre un petit peu que le script se lance et voilà vous voyez que j'ai même pas eu besoin d'attendre là encore très longtemps on a directement l'erreur qui arrê qui arrive ici avec le invalide schemma donc je vais tout de suite aller euh remodifier le script pour le remettre comme il faut comme ça voilà avec les deux thttps je valide et je vais désactiver mon chrome Tab également puisque je n'ai pas envie de scrapper cette information pour l'instant donc je ne veux pas surcharger le site et dépenser des crédits bright data mais voilà vous voyez que ça fonctionne bien on a là encore notre erreur on voit le problème on voit la ligne de code qui pose problème invalide schema donc le problème voilà l'adapteur n'est pas bon on a encore ici toutes les valeurs importantes pour nous on a la valeur de laassine la valeur des proxy la valeur de l'URL et toutes les informations qui pourraient nous être utiles pour résoudre ce problème donc j'espère que ce projet vous permet de voir à quel point on peut avoir un script fonctionnel qui tourne dans ce cas-ci tout toutes les minutes mais après vous pouvez changer le chrome Tab pour le pour modifier le temps de rafraîchissement de votre script et vous avez ainsi les alertes directement sur votre téléphone en cas de baisse de prix et les alertes sur centry en cas d'erreur dans le script qui nécessite votre attention et voilà on est arrivé à la fin de cette vidéo monumentale qui j'espère vous a plu et vous a permis de découvrir le scrapping avec Python je vous le redis encore une fois si vous ne l'avez pas encore fait mettez un pouce bleu partagez la vidéo vraiment c'est important mettez-la sur tous vos réseau c'est ça vraiment qui nous permet de continuer à faire du contenu gratuit et j'espère que je vais pouvoir en faire encore longtemps donc merci de votre soutien dites-moi en commentaire tout ce qui vous passe par la tête si vous avez des questions si vous voulez voir d'autres vidéos de ce genre ça m'intéresse je les lis tous donc n'hésitez pas et si jamais vous souhaitez vous former à Python vous le savez une seule adresse docstring.fr créez-vous un compte c'est gratuit vous pouvez également nous rejoindre sur le serveur discord on a des challenges des forum d'ID on a sur le site des quiz des exercices des formations plein de contenu gratuit donc n'hésitez rejoignez-nous et j'espère qu'on se retrouve là-bas très [Musique] vite