/** * Collecteur Bodacc - Gel des avoirs * Scraping léger avec politesse pour vérifier les mentions de gel des avoirs */ const fetch = require('node-fetch'); const { JSDOM } = require('jsdom'); const BODACC_BASE_URL = 'https://www.bodacc.fr'; const USER_AGENT = '4NK-IA-Front/1.0 (Document Analysis Tool)'; const REQUEST_DELAY_MS = 1000; // 1 seconde entre les requêtes const REQUEST_TIMEOUT_MS = 10000; // 10 secondes timeout /** * Effectue une recherche sur Bodacc pour un nom/prénom donné * @param {string} lastName - Nom de famille (obligatoire) * @param {string} firstName - Prénom (optionnel) * @returns {Promise} Résultat de la recherche */ async function searchBodaccGelAvoirs(lastName, firstName = '') { const startTime = Date.now(); try { console.log(`[Bodacc] Recherche gel des avoirs pour: ${lastName} ${firstName}`); // Construction de la requête de recherche const searchParams = new URLSearchParams({ 'q': `${lastName} ${firstName}`.trim(), 'type': 'gel-avoirs', 'date_debut': '2020-01-01', // Recherche sur les 4 dernières années 'date_fin': new Date().toISOString().split('T')[0] }); const searchUrl = `${BODACC_BASE_URL}/recherche?${searchParams.toString()}`; // Requête avec politesse const response = await fetch(searchUrl, { method: 'GET', headers: { 'User-Agent': USER_AGENT, 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'fr-FR,fr;q=0.9,en;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1' }, timeout: REQUEST_TIMEOUT_MS }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const html = await response.text(); const dom = new JSDOM(html); const document = dom.window.document; // Extraction des résultats const results = extractBodaccResults(document, lastName, firstName); // Délai de politesse avant la prochaine requête await new Promise(resolve => setTimeout(resolve, REQUEST_DELAY_MS)); const duration = Date.now() - startTime; console.log(`[Bodacc] Recherche terminée en ${duration}ms, ${results.length} résultats`); return { success: true, duration, results, source: 'bodacc.fr', searchUrl, timestamp: new Date().toISOString() }; } catch (error) { const duration = Date.now() - startTime; console.error(`[Bodacc] Erreur recherche:`, error.message); return { success: false, duration, error: error.message, results: [], source: 'bodacc.fr', timestamp: new Date().toISOString() }; } } /** * Extrait les résultats de la page Bodacc * @param {Document} document - Document DOM parsé * @param {string} lastName - Nom recherché * @param {string} firstName - Prénom recherché * @returns {Array} Liste des résultats trouvés */ function extractBodaccResults(document, lastName, firstName) { const results = []; try { // Sélecteurs pour les résultats de gel des avoirs const resultSelectors = [ '.result-item', '.search-result', '.bodacc-result', '[data-type="gel-avoirs"]' ]; let resultElements = []; for (const selector of resultSelectors) { resultElements = document.querySelectorAll(selector); if (resultElements.length > 0) break; } // Si pas de sélecteur spécifique, chercher dans le contenu général if (resultElements.length === 0) { const content = document.body.textContent || ''; if (content.includes('gel des avoirs') || content.includes('GEL DES AVOIRS')) { // Résultat générique si on trouve des mentions results.push({ name: `${firstName} ${lastName}`.trim(), type: 'gel-avoirs', date: new Date().toISOString().split('T')[0], sourceUrl: BODACC_BASE_URL, matchScore: 0.7, description: 'Mention de gel des avoirs détectée dans les résultats Bodacc' }); } } else { // Traitement des éléments de résultats spécifiques resultElements.forEach((element, index) => { try { const nameElement = element.querySelector('.name, .nom, .person-name, h3, h4'); const dateElement = element.querySelector('.date, .publication-date, .date-publication'); const linkElement = element.querySelector('a[href]'); const name = nameElement ? nameElement.textContent.trim() : `${firstName} ${lastName}`.trim(); const date = dateElement ? dateElement.textContent.trim() : new Date().toISOString().split('T')[0]; const sourceUrl = linkElement ? new URL(linkElement.href, BODACC_BASE_URL).href : BODACC_BASE_URL; // Calcul du score de correspondance basique const matchScore = calculateMatchScore(name, lastName, firstName); if (matchScore > 0.3) { // Seuil minimum de correspondance results.push({ name, type: 'gel-avoirs', date, sourceUrl, matchScore, description: `Résultat ${index + 1} de gel des avoirs sur Bodacc` }); } } catch (elementError) { console.warn(`[Bodacc] Erreur traitement élément ${index}:`, elementError.message); } }); } } catch (error) { console.warn(`[Bodacc] Erreur extraction résultats:`, error.message); } return results; } /** * Calcule un score de correspondance entre le nom trouvé et le nom recherché * @param {string} foundName - Nom trouvé dans les résultats * @param {string} lastName - Nom recherché * @param {string} firstName - Prénom recherché * @returns {number} Score entre 0 et 1 */ function calculateMatchScore(foundName, lastName, firstName) { const found = foundName.toLowerCase(); const last = lastName.toLowerCase(); const first = firstName.toLowerCase(); let score = 0; // Correspondance exacte du nom de famille if (found.includes(last)) { score += 0.6; } // Correspondance du prénom si fourni if (first && found.includes(first)) { score += 0.4; } // Bonus pour correspondance exacte if (found === `${first} ${last}`.trim().toLowerCase()) { score = 1.0; } return Math.min(score, 1.0); } module.exports = { searchBodaccGelAvoirs, generateBodaccSummary }; /** * Génère un résumé des résultats pour le PDF * @param {Array} results - Résultats de la recherche * @param {string} lastName - Nom recherché * @param {string} firstName - Prénom recherché * @returns {Object} Résumé formaté */ function generateBodaccSummary(results, lastName, firstName) { const totalResults = results.length; const highConfidenceResults = results.filter(r => r.matchScore > 0.7); const recentResults = results.filter(r => { const resultDate = new Date(r.date); const oneYearAgo = new Date(); oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1); return resultDate > oneYearAgo; }); return { searchTarget: `${firstName} ${lastName}`.trim(), totalResults, highConfidenceResults: highConfidenceResults.length, recentResults: recentResults.length, hasGelAvoirs: totalResults > 0, riskLevel: totalResults === 0 ? 'Aucun' : highConfidenceResults.length > 0 ? 'Élevé' : totalResults > 0 ? 'Moyen' : 'Faible', summary: totalResults === 0 ? 'Aucune mention de gel des avoirs trouvée sur Bodacc' : `${totalResults} mention(s) trouvée(s), ${highConfidenceResults.length} avec haute confiance` }; }