Actualizar robot.js

This commit is contained in:
2026-02-13 18:38:41 +00:00
parent 1a040caa8f
commit 6f47a668c0

View File

@@ -42,7 +42,7 @@ async function main() {
} }
// ========================================== // ==========================================
// 🏥 MULTIASISTENCIA V3 (CIRUJANO) // 🏥 MULTIASISTENCIA V4 (BÚSQUEDA POR ANCLAS)
// ========================================== // ==========================================
async function runMultiasistencia(ownerId, user, pass) { async function runMultiasistencia(ownerId, user, pass) {
const browser = await chromium.launch({ headless: HEADLESS, args: ['--no-sandbox'] }); 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))); 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) { for (const ref of expedientes) {
await page.goto(`https://web.multiasistencia.com/w3multi/repasos1.php?reparacion=${ref}`, { waitUntil: 'domcontentloaded' }); await page.goto(`https://web.multiasistencia.com/w3multi/repasos1.php?reparacion=${ref}`, { waitUntil: 'domcontentloaded' });
const fullData = await page.evaluate(() => { const fullData = await page.evaluate(() => {
const data = {}; const data = {};
const bodyText = document.body.innerText;
// --- 1. CIRUJANO (Extracción manual de lo importante) --- // 1. EXTRAER TODOS LOS ELEMENTOS CON TEXTO
// Intentamos sacar la dirección de la cabecera típica de Multi const allElements = Array.from(document.querySelectorAll('td, b, span, div'));
const boldElements = Array.from(document.querySelectorAll('b, strong, .titulo'));
// Buscamos nombre: Suele estar cerca de "Asegurado" o es un texto en mayúsculas aislado // 2. DICCIONARIO DE ETIQUETAS "ANCLA"
let clientNameCandidate = ""; const keywords = [
// Buscamos dirección: Suele contener "CL", "AV", "PZ" { key: 'expediente', search: 'Número Reparación' },
let addressCandidate = ""; { 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) keywords.forEach(item => {
const findNeighbor = (keywords) => { // Buscamos el elemento que contenga el texto exacto del campo
const cells = Array.from(document.querySelectorAll('td')); const found = allElements.find(el => el.innerText.trim() === item.search);
for (let i = 0; i < cells.length; i++) { if (found) {
const txt = cells[i].innerText.toUpperCase(); // El valor suele estar en el siguiente elemento hermano
if (keywords.some(k => txt.includes(k))) { let val = "";
// Devolvemos el texto de la siguiente celda que no esté vacía if (found.nextElementSibling) {
for(let j=1; j<=3; j++) { val = found.nextElementSibling.innerText.trim();
if(cells[i+j] && cells[i+j].innerText.trim().length > 2) return cells[i+j].innerText.trim(); } else if (found.parentElement && found.parentElement.nextElementSibling) {
// O en la celda de al lado
val = found.parentElement.nextElementSibling.innerText.trim();
} }
}
}
return "";
};
data.clientName_fixed = findNeighbor(['ASEGURADO', 'NOMBRE CLIENTE', 'CONTACTO']); // Si lo que encontramos no es el mismo nombre de la etiqueta, lo guardamos
data.address_fixed = findNeighbor(['DIRECCIÓN', 'DOMICILIO', 'RIESGO', 'UBICACIÓN']); if (val && val !== item.search) {
data.phone_fixed = (bodyText.match(/[6789]\d{8}/) || [])[0] || ""; data[item.search] = val;
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; return data;
}); });
if (fullData) { if (fullData && Object.keys(fullData).length > 0) {
await saveServiceToDB(ownerId, 'multiasistencia', ref, fullData); 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) { async function runHomeserve(ownerId, user, pass) {
const browser = await chromium.launch({ headless: HEADLESS, args: ['--no-sandbox'] }); const browser = await chromium.launch({ headless: HEADLESS, args: ['--no-sandbox'] });