From 6f47a668c0d3820e4e36cbf0b209316a6d971baa Mon Sep 17 00:00:00 2001 From: marsalva Date: Fri, 13 Feb 2026 18:38:41 +0000 Subject: [PATCH] Actualizar robot.js --- robot.js | 101 +++++++++++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 52 deletions(-) diff --git a/robot.js b/robot.js index 38a79a3..da9af22 100644 --- a/robot.js +++ b/robot.js @@ -42,7 +42,7 @@ async function main() { } // ========================================== -// 🏥 MULTIASISTENCIA V3 (CIRUJANO) +// 🏥 MULTIASISTENCIA V4 (BÚSQUEDA POR ANCLAS) // ========================================== async function runMultiasistencia(ownerId, user, pass) { const browser = await chromium.launch({ headless: HEADLESS, args: ['--no-sandbox'] }); @@ -68,78 +68,75 @@ async function runMultiasistencia(ownerId, user, pass) { return Array.from(new Set(links.map(a => a.href.match(/reparacion=(\d+)/)?.[1]).filter(Boolean))); }); - console.log(`🔍 [Multi] ${expedientes.length} expedientes a analizar.`); + console.log(`🔍 [Multi] ${expedientes.length} expedientes encontrados.`); for (const ref of expedientes) { await page.goto(`https://web.multiasistencia.com/w3multi/repasos1.php?reparacion=${ref}`, { waitUntil: 'domcontentloaded' }); const fullData = await page.evaluate(() => { const data = {}; - const bodyText = document.body.innerText; - - // --- 1. CIRUJANO (Extracción manual de lo importante) --- - // Intentamos sacar la dirección de la cabecera típica de Multi - const boldElements = Array.from(document.querySelectorAll('b, strong, .titulo')); - // Buscamos nombre: Suele estar cerca de "Asegurado" o es un texto en mayúsculas aislado - let clientNameCandidate = ""; - // Buscamos dirección: Suele contener "CL", "AV", "PZ" - let addressCandidate = ""; + // 1. EXTRAER TODOS LOS ELEMENTOS CON TEXTO + const allElements = Array.from(document.querySelectorAll('td, b, span, div')); + + // 2. DICCIONARIO DE ETIQUETAS "ANCLA" + const keywords = [ + { key: 'expediente', search: 'Número Reparación' }, + { key: 'poliza', search: 'Número de Póliza' }, + { key: 'clientName', search: 'Nombre Cliente' }, + { key: 'address', search: 'Dirección' }, + { key: 'poblacion_cp', search: 'Distrito Postal' }, + { key: 'procedencia', search: 'Procedencia' }, + { key: 'descripcion', search: 'Descripción de la Reparación' }, + { key: 'tramitador', search: 'Tramitador' }, + { key: 'urgente', search: 'Urgente' }, + { key: 'fecha_realizacion', search: 'Fecha realización' }, + { key: 'forma_pago', search: 'Forma de pago' } + ]; - // Estrategia por palabras clave vecinas (más seguro) - const findNeighbor = (keywords) => { - const cells = Array.from(document.querySelectorAll('td')); - for (let i = 0; i < cells.length; i++) { - const txt = cells[i].innerText.toUpperCase(); - if (keywords.some(k => txt.includes(k))) { - // Devolvemos el texto de la siguiente celda que no esté vacía - for(let j=1; j<=3; j++) { - if(cells[i+j] && cells[i+j].innerText.trim().length > 2) return cells[i+j].innerText.trim(); - } + keywords.forEach(item => { + // Buscamos el elemento que contenga el texto exacto del campo + const found = allElements.find(el => el.innerText.trim() === item.search); + if (found) { + // El valor suele estar en el siguiente elemento hermano + let val = ""; + if (found.nextElementSibling) { + val = found.nextElementSibling.innerText.trim(); + } else if (found.parentElement && found.parentElement.nextElementSibling) { + // O en la celda de al lado + val = found.parentElement.nextElementSibling.innerText.trim(); + } + + // Si lo que encontramos no es el mismo nombre de la etiqueta, lo guardamos + if (val && val !== item.search) { + data[item.search] = val; } } - return ""; - }; + }); - data.clientName_fixed = findNeighbor(['ASEGURADO', 'NOMBRE CLIENTE', 'CONTACTO']); - data.address_fixed = findNeighbor(['DIRECCIÓN', 'DOMICILIO', 'RIESGO', 'UBICACIÓN']); - data.phone_fixed = (bodyText.match(/[6789]\d{8}/) || [])[0] || ""; - data.description_fixed = findNeighbor(['DESCRIPCIÓN', 'DAÑOS', 'AVERÍA']); - - // ... dentro del evaluate de Multiasistencia ... -const rows = document.querySelectorAll('tr'); -rows.forEach(row => { - const cells = Array.from(row.querySelectorAll('td')); - for (let i = 0; i < cells.length - 1; i++) { - let key = cells[i].innerText.trim().replace(':', ''); - let val = cells[i+1]?.innerText.trim(); - - // ❌ FILTRO ANTIBASURA: - // Si la "clave" es muy larga (más de 30 caracteres), - // probablemente es una dirección o un nombre, NO una etiqueta. - if (key.length > 30 || key.length < 2) continue; - - // Si la clave contiene números y espacios, probablemente es una dirección - if (/\d/.test(key) && key.includes(' ')) continue; - - if (val && val.length > 0) { - data[key] = val; - } - } -}); + // 3. CAPTURA ESPECIAL DE TELÉFONOS (CIRUJANO) + const bodyText = document.body.innerText; + const phones = bodyText.match(/[6789]\d{8}/g); + if (phones) { + data['phone_fixed'] = [...new Set(phones)].join(' / '); + } return data; }); - if (fullData) { + if (fullData && Object.keys(fullData).length > 0) { await saveServiceToDB(ownerId, 'multiasistencia', ref, fullData); } } - } catch (e) { console.error("❌ [Multi]", e.message); } finally { await browser.close(); } + } catch (e) { + console.error("❌ [Multi]", e.message); + } finally { + await browser.close(); + } } // ========================================== -// 🧹 HOMESERVE (SE MANTIENE IGUAL, FUNCIONABA BIEN) +// 🧹 HOMESERVE (MANTENIDO) // ========================================== async function runHomeserve(ownerId, user, pass) { const browser = await chromium.launch({ headless: HEADLESS, args: ['--no-sandbox'] });