Spaces:
Paused
Paused
| import tempfile | |
| import os | |
| import shutil # Nécessaire pour supprimer le dossier temporaire | |
| from selenium import webdriver | |
| from selenium.webdriver.chrome.service import Service | |
| from selenium.webdriver.chrome.options import Options | |
| from bs4 import BeautifulSoup | |
| import traceback # Pour afficher les erreurs détaillées | |
| def scrape_website(website): | |
| """ | |
| Scrape le contenu HTML d'un site web en utilisant Selenium et ChromeDriver. | |
| Args: | |
| website (str): L'URL du site web à scraper. | |
| Returns: | |
| str or None: Le contenu HTML brut de la page, ou None en cas d'erreur. | |
| """ | |
| print(f"Préparation du scraping pour : {website}") | |
| chrome_driver_path = "/usr/bin/chromedriver" # Assurez-vous que ce chemin est correct sur HF Spaces | |
| # Ou essayez sans si chromedriver est dans le PATH | |
| options = Options() | |
| options.add_argument("--headless") # Exécuter sans interface graphique (essentiel pour les serveurs) | |
| options.add_argument("--no-sandbox") # Requis pour les environnements type Docker/HF Spaces | |
| options.add_argument("--disable-dev-shm-usage") # Évite les problèmes de mémoire partagée limitée | |
| options.add_argument("--disable-gpu") # Désactiver l'accélération GPU, souvent inutile en headless | |
| options.add_argument("window-size=1920x1080") # Définir une taille de fenêtre virtuelle | |
| # --- Gestion du répertoire de données utilisateur --- | |
| # Crée un répertoire temporaire unique pour cette session Chrome | |
| user_data_dir = tempfile.mkdtemp() | |
| print(f"Utilisation du répertoire de données utilisateur temporaire : {user_data_dir}") | |
| options.add_argument(f"--user-data-dir={user_data_dir}") | |
| # Note : Si vous n'avez absolument pas besoin de persistance (cookies, etc.), | |
| # vous pouvez commenter les deux lignes ci-dessus et celle du nettoyage dans finally. | |
| # Ne pas spécifier de user-data-dir du tout est souvent plus simple si possible. | |
| driver = None # Initialiser à None pour le bloc finally | |
| html_content = None # Initialiser le résultat | |
| try: | |
| # --- Initialisation du WebDriver --- | |
| # L'objet options est passé directement à webdriver.Chrome, pas à Service | |
| service = Service(executable_path=chrome_driver_path) | |
| print("Lancement du navigateur Chrome headless...") | |
| driver = webdriver.Chrome(service=service, options=options) | |
| print("Navigateur lancé.") | |
| print(f"Accès à l'URL : {website}") | |
| driver.get(website) | |
| print("Page chargée.") | |
| # Attendre un peu si nécessaire pour le contenu dynamique (optionnel) | |
| # import time | |
| # time.sleep(2) # Attendre 2 secondes par exemple | |
| html_content = driver.page_source | |
| print("Code source HTML récupéré.") | |
| except Exception as e: | |
| print(f"ERREUR lors du scraping de {website}: {e}") | |
| print("Traceback complet :") | |
| traceback.print_exc() # Affiche la trace complète pour un meilleur débogage | |
| finally: | |
| # --- Nettoyage --- | |
| if driver: | |
| print("Fermeture du WebDriver.") | |
| driver.quit() # Ferme le navigateur et le processus chromedriver | |
| # Supprimer le répertoire de données utilisateur temporaire | |
| if os.path.exists(user_data_dir): | |
| try: | |
| print(f"Suppression du répertoire temporaire : {user_data_dir}") | |
| shutil.rmtree(user_data_dir) | |
| except OSError as e: | |
| print(f"Erreur lors de la suppression de {user_data_dir}: {e}") | |
| return html_content | |
| def extract_body_content(html_content): | |
| """ | |
| Extrait le contenu de la balise <body> d'un contenu HTML. | |
| Args: | |
| html_content (str): Le contenu HTML brut. | |
| Returns: | |
| str: Le contenu de la balise <body>, ou une chaîne vide si non trouvé. | |
| """ | |
| if not html_content: | |
| return "" | |
| soup = BeautifulSoup(html_content, "html.parser") | |
| body = soup.body | |
| if body: | |
| return str(body) | |
| print("Balise <body> non trouvée dans le HTML.") | |
| return "" | |
| def clean_body_content(body_content): | |
| """ | |
| Nettoie le contenu HTML en retirant les scripts, styles et les espaces superflus. | |
| Args: | |
| body_content (str): Le contenu HTML (généralement de la balise <body>). | |
| Returns: | |
| str: Le texte nettoyé. | |
| """ | |
| if not body_content: | |
| return "" | |
| soup = BeautifulSoup(body_content, "html.parser") | |
| # Supprimer les balises <script> et <style> | |
| for script_or_style in soup(["script", "style"]): | |
| script_or_style.extract() | |
| # Obtenir le texte, en mettant une nouvelle ligne comme séparateur | |
| cleaned_text = soup.get_text(separator="\n", strip=True) | |
| # Optionnel : Nettoyer les lignes vides multiples si get_text ne suffit pas | |
| # lines = [line.strip() for line in cleaned_text.splitlines() if line.strip()] | |
| # cleaned_text = "\n".join(lines) | |
| return cleaned_text | |
| def split_dom_content(dom_content, max_length=60000): | |
| """ | |
| Divise une longue chaîne de caractères en morceaux de taille maximale spécifiée. | |
| Args: | |
| dom_content (str): La chaîne de caractères à diviser. | |
| max_length (int): La longueur maximale de chaque morceau. | |
| Returns: | |
| list[str]: Une liste de chaînes de caractères. | |
| """ | |
| if not dom_content: | |
| return [] | |
| return [ | |
| dom_content[i:i + max_length] for i in range(0, len(dom_content), max_length) | |
| ] |