You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

webscrap_mushroom_v1.1.ipynb 6.8 KiB

5 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. {
  2. "cells": [
  3. {
  4. "cell_type": "code",
  5. "execution_count": 1,
  6. "metadata": {},
  7. "outputs": [
  8. {
  9. "name": "stdout",
  10. "output_type": "stream",
  11. "text": [
  12. " URL Name \\\n",
  13. "0 https://mushroomobserver.org/1 Xylaria polymorpha \n",
  14. "1 https://mushroomobserver.org/2 Xylaria magnoliae \n",
  15. "2 https://mushroomobserver.org/3 Xylaria hypoxylon \n",
  16. "\n",
  17. " image_1 \n",
  18. "0 1_Xylaria_polymorpha_1.jpg \n",
  19. "1 2_Xylaria_magnoliae_1.jpg \n",
  20. "2 3_Xylaria_hypoxylon_1.jpg \n",
  21. "Données sauvegardées à D:/Images_champignons/mushroom_data.xlsx\n"
  22. ]
  23. }
  24. ],
  25. "source": [
  26. "# J'importe les modules nécessaires pour le script.\n",
  27. "import requests # Pour effectuer des requêtes HTTP.\n",
  28. "from bs4 import BeautifulSoup # Pour parser le contenu HTML.\n",
  29. "import pandas as pd # Pour manipuler et stocker les données sous forme de tableaux.\n",
  30. "import os # Pour interagir avec le système de fichiers de l'ordinateur.\n",
  31. "import time # Pour introduire des délais dans l'exécution du script.\n",
  32. "import random # Pour générer des nombres aléatoires.\n",
  33. "\n",
  34. "# Je définis les en-têtes HTTP pour simuler une requête d'un navigateur web moderne.\n",
  35. "headers = {\n",
  36. " 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'\n",
  37. "}\n",
  38. "\n",
  39. "# Je spécifie le chemin du dossier où les images téléchargées seront enregistrées.\n",
  40. "img_folder_path = 'D:/Images_champignons'\n",
  41. "# Je vérifie si le dossier spécifié existe et sinon, je le crée.\n",
  42. "if not os.path.exists(img_folder_path):\n",
  43. " os.makedirs(img_folder_path)\n",
  44. "\n",
  45. "# J'initialise une session de requêtes HTTP pour maintenir les cookies et autres en-têtes à travers les requêtes.\n",
  46. "session = requests.Session()\n",
  47. "session.headers.update(headers) # J'ajoute les en-têtes définis à la session.\n",
  48. "\n",
  49. "# Je fixe l'URL de base du site que je souhaite scraper.\n",
  50. "base_url = 'https://mushroomobserver.org/'\n",
  51. "\n",
  52. "# Je prépare une liste pour stocker les données extraites.\n",
  53. "data = []\n",
  54. "\n",
  55. "# Je boucle sur les premières trois pages du site pour l'exemple.\n",
  56. "for i in range(1, 4):\n",
  57. " # Je construis l'URL de chaque page en combinant l'URL de base avec le numéro de la page.\n",
  58. " page_url = f'{base_url}{i}'\n",
  59. " # Je récupère un identifiant unique pour chaque page, ici simplement le numéro de la page.\n",
  60. " url_reference = str(i)\n",
  61. " # Je crée une liste pour stocker les noms des images trouvées sur la page.\n",
  62. " img_names = []\n",
  63. " \n",
  64. " # J'introduis un délai aléatoire entre 1 et 5 secondes avant de faire la requête pour simuler un comportement humain.\n",
  65. " sleep_time = random.randint(1, 5)\n",
  66. " time.sleep(sleep_time)\n",
  67. " \n",
  68. " # J'essaie d'effectuer une requête HTTP pour obtenir le contenu de la page.\n",
  69. " try:\n",
  70. " response = session.get(page_url)\n",
  71. " response.raise_for_status() # Je vérifie que la requête a réussi.\n",
  72. " soup = BeautifulSoup(response.content, 'html.parser') # Je parse le contenu HTML obtenu.\n",
  73. " \n",
  74. " # Je cherche le nom du champignon dans la balise <h1> avec l'ID 'title'.\n",
  75. " name_tag = soup.find('h1', id='title').find('i')\n",
  76. " name = name_tag.get_text(strip=True) if name_tag else f'Unknown_{i}' # Si la balise <i> n'existe pas, j'utilise un nom par défaut.\n",
  77. " \n",
  78. " # Je parcours toutes les balises <img> avec la classe 'carousel-image' pour extraire les URLs des images.\n",
  79. " img_tags = soup.find_all('img', class_='carousel-image')\n",
  80. " img_counter = 1\n",
  81. " for img_tag in img_tags:\n",
  82. " img_url = img_tag.get('data-src') # J'extrais l'URL de l'image.\n",
  83. " if img_url:\n",
  84. " img_data = session.get(img_url).content # Je télécharge l'image.\n",
  85. " # Je crée un nom de fichier unique pour chaque image.\n",
  86. " img_name = f\"{url_reference}_{name.replace(' ', '_')}_{img_counter}.jpg\"\n",
  87. " img_path = os.path.join(img_folder_path, img_name) # Je construis le chemin du fichier.\n",
  88. " \n",
  89. " # J'ouvre un fichier pour écrire les données de l'image.\n",
  90. " with open(img_path, 'wb') as f:\n",
  91. " f.write(img_data)\n",
  92. " \n",
  93. " img_names.append(img_name) # J'ajoute le nom de l'image à la liste.\n",
  94. " img_counter += 1 # J'incrémente le compteur d'image.\n",
  95. " \n",
  96. " # Je crée un dictionnaire pour stocker les données de cette page, y compris l'URL, le nom, et les noms d'images.\n",
  97. " page_data = {'URL': page_url, 'Name': name}\n",
  98. " for j, img_name in enumerate(img_names, start=1):\n",
  99. " page_data[f'image_{j}'] = img_name\n",
  100. " \n",
  101. " data.append(page_data) # J'ajoute les données de la page à la liste principale.\n",
  102. " \n",
  103. " except requests.exceptions.RequestException as e:\n",
  104. " print(f\"Erreur lors de la requête {page_url} : {e}\") # J'affiche les erreurs rencontrées pendant la requête.\n",
  105. " continue\n",
  106. "\n",
  107. "# Je convertis la liste des données collectées en un DataFrame pour une manipulation facile.\n",
  108. "df = pd.DataFrame(data)\n",
  109. "# Je redéfinis les colonnes du DataFrame pour inclure toutes les images trouvées.\n",
  110. "max_images = max(len(d) for d in data) - 2\n",
  111. "df = df.reindex(columns=['URL', 'Name'] + [f'image_{j}' for j in range(1, max_images + 1)])\n",
  112. "\n",
  113. "# J'affiche le DataFrame pour vérifier les données extraites.\n",
  114. "print(df)\n",
  115. "\n",
  116. "# Je sauvegarde le DataFrame au format Excel pour une utilisation ultérieure.\n",
  117. "output_path = 'D:/Images_champignons/mushroom_data.xlsx'\n",
  118. "df.to_excel(output_path, index=False)\n",
  119. "\n",
  120. "# Je confirme que les données ont été sauvegardées avec succès.\n",
  121. "print(f'Données sauvegardées à {output_path}')\n"
  122. ]
  123. }
  124. ],
  125. "metadata": {
  126. "kernelspec": {
  127. "display_name": "base",
  128. "language": "python",
  129. "name": "python3"
  130. },
  131. "language_info": {
  132. "codemirror_mode": {
  133. "name": "ipython",
  134. "version": 3
  135. },
  136. "file_extension": ".py",
  137. "mimetype": "text/x-python",
  138. "name": "python",
  139. "nbconvert_exporter": "python",
  140. "pygments_lexer": "ipython3",
  141. "version": "3.12.3"
  142. }
  143. },
  144. "nbformat": 4,
  145. "nbformat_minor": 2
  146. }