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.
 
 
 

193 lines
9.3 KiB

  1. {
  2. "cells": [
  3. {
  4. "cell_type": "code",
  5. "execution_count": 3,
  6. "metadata": {},
  7. "outputs": [
  8. {
  9. "name": "stdout",
  10. "output_type": "stream",
  11. "text": [
  12. " URL Name \\\n",
  13. "0 https://mushroomobserver.org/5 Xeromphalina \n",
  14. "1 https://mushroomobserver.org/6 Xeromphalina campanella \n",
  15. "2 https://mushroomobserver.org/7 Xerocomus zelleri \n",
  16. "3 https://mushroomobserver.org/8 Xerocomus zelleri \n",
  17. "4 https://mushroomobserver.org/9 Xerocomus subtomentosus \n",
  18. ".. ... ... \n",
  19. "110 https://mushroomobserver.org/115 Ramaria \n",
  20. "111 https://mushroomobserver.org/116 Ramaria \n",
  21. "112 https://mushroomobserver.org/117 Ramaria rubribrunnescens \n",
  22. "113 https://mushroomobserver.org/118 Ramaria largentii \n",
  23. "114 https://mushroomobserver.org/119 Ramaria gelatinosa \n",
  24. "\n",
  25. " image_1 image_2 \\\n",
  26. "0 5_Xeromphalina_1.jpg NaN \n",
  27. "1 6_Xeromphalina_campanella_1.jpg NaN \n",
  28. "2 7_Xerocomus_zelleri_1.jpg NaN \n",
  29. "3 8_Xerocomus_zelleri_1.jpg NaN \n",
  30. "4 9_Xerocomus_subtomentosus_1.jpg 9_Xerocomus_subtomentosus_2.jpg \n",
  31. ".. ... ... \n",
  32. "110 115_Ramaria_1.jpg 115_Ramaria_2.jpg \n",
  33. "111 116_Ramaria_1.jpg NaN \n",
  34. "112 117_Ramaria_rubribrunnescens_1.jpg NaN \n",
  35. "113 118_Ramaria_largentii_1.jpg NaN \n",
  36. "114 119_Ramaria_gelatinosa_1.jpg NaN \n",
  37. "\n",
  38. " image_3 image_4 \n",
  39. "0 NaN NaN \n",
  40. "1 NaN NaN \n",
  41. "2 NaN NaN \n",
  42. "3 NaN NaN \n",
  43. "4 NaN NaN \n",
  44. ".. ... ... \n",
  45. "110 NaN NaN \n",
  46. "111 NaN NaN \n",
  47. "112 NaN NaN \n",
  48. "113 NaN NaN \n",
  49. "114 NaN NaN \n",
  50. "\n",
  51. "[115 rows x 6 columns]\n",
  52. "Données sauvegardées à D:/Images_champignons/mushroom_data.xlsx\n"
  53. ]
  54. }
  55. ],
  56. "source": [
  57. "# J'importe les bibliothèques nécessaires : requests pour réaliser des requêtes HTTP,\n",
  58. "# BeautifulSoup pour analyser le HTML, pandas pour manipuler les données, et os pour gérer les opérations liées au système de fichiers.\n",
  59. "import requests\n",
  60. "from bs4 import BeautifulSoup\n",
  61. "import pandas as pd\n",
  62. "import os\n",
  63. "\n",
  64. "# Je configure les en-têtes HTTP pour simuler une requête provenant d'un navigateur web moderne.\n",
  65. "# Ceci est utile pour éviter d'être bloqué par les mécanismes de protection anti-scraping des sites web.\n",
  66. "headers = {\n",
  67. " '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",
  68. "}\n",
  69. "\n",
  70. "# Je spécifie le chemin du dossier local où je souhaite enregistrer les images téléchargées.\n",
  71. "img_folder_path = 'D:/Images_champignons'\n",
  72. "# Si le dossier spécifié n'existe pas, je le crée pour éviter des erreurs lors de la sauvegarde des fichiers.\n",
  73. "if not os.path.exists(img_folder_path):\n",
  74. " os.makedirs(img_folder_path)\n",
  75. "\n",
  76. "# J'initialise une session de requêtes HTTP, ce qui me permet de conserver des cookies entre les requêtes\n",
  77. "# et d'améliorer la gestion des connexions HTTP.\n",
  78. "session = requests.Session()\n",
  79. "session.headers.update(headers) # J'ajoute l'en-tête User-Agent à la session pour toutes les requêtes.\n",
  80. "\n",
  81. "# Je définis l'URL de base du site web que je veux scraper.\n",
  82. "base_url = 'https://mushroomobserver.org/'\n",
  83. "\n",
  84. "# J'initialise une liste vide pour collecter les données que je vais extraire.\n",
  85. "data = []\n",
  86. "\n",
  87. "# Je démarre une boucle pour parcourir les pages du site. Ici, je limite l'exemple aux trois premières pages.\n",
  88. "for i in range(5, 120):\n",
  89. " # Je construis l'URL de chaque page en ajoutant le numéro de page à l'URL de base.\n",
  90. " page_url = f'{base_url}{i}'\n",
  91. " # Je récupère un identifiant unique de la page à partir de son numéro.\n",
  92. " url_reference = str(i)\n",
  93. " # J'initialise une liste pour stocker les noms des images trouvées sur chaque page.\n",
  94. " img_names = []\n",
  95. " \n",
  96. " # J'essaie d'effectuer une requête GET pour récupérer le contenu de la page.\n",
  97. " try:\n",
  98. " response = session.get(page_url)\n",
  99. " response.raise_for_status() # Je vérifie que la requête a réussi sans retourner d'erreur HTTP.\n",
  100. " except requests.exceptions.HTTPError as err:\n",
  101. " print(f\"Erreur HTTP : {err}\") # En cas d'erreur, je l'affiche et passe à la page suivante.\n",
  102. " continue\n",
  103. " \n",
  104. " # J'utilise BeautifulSoup pour analyser le contenu HTML de la page.\n",
  105. " soup = BeautifulSoup(response.content, 'html.parser')\n",
  106. " \n",
  107. " # Je cherche dans le document HTML la balise <h1> avec l'ID 'title' pour extraire le nom du champignon.\n",
  108. " name_tag = soup.find('h1', id='title').find('i')\n",
  109. " # Si le nom est trouvé, je l'extrait, sinon j'utilise un nom par défaut.\n",
  110. " name = name_tag.get_text(strip=True) if name_tag else f'Unknown_{i}'\n",
  111. " \n",
  112. " # Je recherche toutes les balises <img> qui contiennent les images des champignons.\n",
  113. " img_tags = soup.find_all('img', class_='carousel-image')\n",
  114. " img_counter = 1\n",
  115. " for img_tag in img_tags:\n",
  116. " # Pour chaque image, j'extrait son URL.\n",
  117. " img_url = img_tag.get('data-src')\n",
  118. " if not img_url:\n",
  119. " continue # Si aucune URL n'est trouvée, je passe à l'image suivante.\n",
  120. " \n",
  121. " try:\n",
  122. " # Je télécharge l'image en utilisant l'URL trouvée.\n",
  123. " img_data = session.get(img_url).content\n",
  124. " # Je génère un nom de fichier unique pour l'image.\n",
  125. " img_name = f\"{url_reference}_{name.replace(' ', '_')}_{img_counter}.jpg\"\n",
  126. " img_path = os.path.join(img_folder_path, img_name) # Je construis le chemin complet du fichier image.\n",
  127. " \n",
  128. " # J'ouvre le fichier en mode écriture binaire et j'enregistre les données de l'image.\n",
  129. " with open(img_path, 'wb') as f:\n",
  130. " f.write(img_data)\n",
  131. " \n",
  132. " # J'ajoute le nom du fichier à la liste des noms d'images.\n",
  133. " img_names.append(img_name)\n",
  134. " img_counter += 1 # J'incrémente le compteur d'images.\n",
  135. " except Exception as e:\n",
  136. " print(f\"Erreur lors de la sauvegarde de l'image : {e}\") # J'affiche les erreurs rencontrées lors de la sauvegarde des images.\n",
  137. " \n",
  138. " # Je crée un dictionnaire pour cette page contenant l'URL, le nom du champignon, et les noms des images.\n",
  139. " page_data = {'URL': page_url, 'Name': name}\n",
  140. " for j, img_name in enumerate(img_names, start=1):\n",
  141. " page_data[f'image_{j}'] = img_name\n",
  142. " \n",
  143. " # J'ajoute les données de la page à ma liste de données.\n",
  144. " data.append(page_data)\n",
  145. "\n",
  146. "# Je convertis la liste de données en DataFrame pour une manipulation et une analyse plus facile.\n",
  147. "df = pd.DataFrame(data)\n",
  148. "# Je redéfinis les colonnes du DataFrame pour inclure toutes les images collectées.\n",
  149. "max_images = max(len(d) for d in data) - 2\n",
  150. "df = df.reindex(columns=['URL', 'Name'] + [f'image_{j}' for j in range(1, max_images + 1)])\n",
  151. "\n",
  152. "# J'affiche le DataFrame pour vérifier les données extraites.\n",
  153. "print(df)\n",
  154. "\n",
  155. "# Je sauvegarde le DataFrame au format Excel pour une utilisation ultérieure.\n",
  156. "output_path = 'D:/Images_champignons/mushroom_data.xlsx'\n",
  157. "df.to_excel(output_path, index=False)\n",
  158. "\n",
  159. "# Je confirme que les données ont été sauvegardées avec succès.\n",
  160. "print(f'Données sauvegardées à {output_path}')\n"
  161. ]
  162. },
  163. {
  164. "cell_type": "code",
  165. "execution_count": null,
  166. "metadata": {},
  167. "outputs": [],
  168. "source": []
  169. }
  170. ],
  171. "metadata": {
  172. "kernelspec": {
  173. "display_name": "base",
  174. "language": "python",
  175. "name": "python3"
  176. },
  177. "language_info": {
  178. "codemirror_mode": {
  179. "name": "ipython",
  180. "version": 3
  181. },
  182. "file_extension": ".py",
  183. "mimetype": "text/x-python",
  184. "name": "python",
  185. "nbconvert_exporter": "python",
  186. "pygments_lexer": "ipython3",
  187. "version": "3.11.5"
  188. }
  189. },
  190. "nbformat": 4,
  191. "nbformat_minor": 2
  192. }