Spaces:
Running
Running
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) | |
] |