# Tool Web Scraping pour OpenWebUI ## Configuration Dans OpenWebUI (http://192.168.1.27:3000) : 1. **Aller dans** : Admin → Tools → Create Tool 2. **Nom** : Web Scraper 3. **ID** : web_scraper 4. **Description** : Extrait le contenu texte de n'importe quelle URL web ## Code du Tool ```python from typing import Optional import requests from urllib.parse import urlparse import re class Tools: def __init__(self): """Initialize Web Scraper Tool""" self.timeout = 15 self.headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.0' } def scrape_url(self, url: str, max_chars: int = 5000) -> str: """ Scrape le contenu texte d'une URL web Args: url: L'URL à scraper (doit commencer par http:// ou https://) max_chars: Nombre maximum de caractères à retourner (défaut: 5000) Returns: Le contenu texte extrait de la page """ try: # Validation URL if not url.startswith(('http://', 'https://')): return "Erreur: L'URL doit commencer par http:// ou https://" parsed = urlparse(url) if not parsed.netloc: return "Erreur: URL invalide" # Télécharger la page response = requests.get(url, headers=self.headers, timeout=self.timeout) response.raise_for_status() # Détecter l'encodage if response.encoding == 'ISO-8859-1': response.encoding = response.apparent_encoding html = response.text # Extraction simple du texte (sans BeautifulSoup pour garder le Tool léger) # Supprimer les scripts et styles text = re.sub(r'', '', html, flags=re.IGNORECASE | re.DOTALL) text = re.sub(r'', '', text, flags=re.IGNORECASE | re.DOTALL) # Supprimer les balises HTML text = re.sub(r'<[^>]+>', ' ', text) # Nettoyer le texte text = re.sub(r'\s+', ' ', text) # Espaces multiples text = text.strip() # Décoder les entités HTML text = text.replace('&', '&') text = text.replace('<', '<') text = text.replace('>', '>') text = text.replace('"', '"') text = text.replace(''', "'") text = text.replace(' ', ' ') # Tronquer si nécessaire if len(text) > max_chars: text = text[:max_chars] + f"\n\n[...] {len(text) - max_chars} caractères supplémentaires" return f"Contenu extrait de {url}:\n\n{text}" except requests.exceptions.Timeout: return f"Erreur: Timeout après {self.timeout}s pour {url}" except requests.exceptions.ConnectionError: return f"Erreur: Impossible de se connecter à {url}" except requests.exceptions.HTTPError as e: return f"Erreur HTTP {e.response.status_code}: {url}" except Exception as e: return f"Erreur lors du scraping: {str(e)}" def scrape_article(self, url: str) -> str: """ Scrape un article en essayant d'extraire le contenu principal uniquement Args: url: L'URL de l'article Returns: Le contenu principal de l'article (titre + texte) """ try: if not url.startswith(('http://', 'https://')): return "Erreur: L'URL doit commencer par http:// ou https://" response = requests.get(url, headers=self.headers, timeout=self.timeout) response.raise_for_status() if response.encoding == 'ISO-8859-1': response.encoding = response.apparent_encoding html = response.text # Extraire le titre title_match = re.search(r'