4NK_IA_front/backend/collectors/bodaccCollector.js

236 lines
7.6 KiB
JavaScript

/**
* 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<Object>} 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`
};
}