34849-vm/includes/shalom_scraper.js
2026-07-18 00:36:25 +00:00

167 lines
4.8 KiB
JavaScript

#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const puppeteer = require('puppeteer');
function detectChromeExecutable() {
const candidates = [];
const cacheRoot = '/home/ubuntu/.cache/puppeteer/chrome';
try {
if (fs.existsSync(cacheRoot)) {
const versions = fs.readdirSync(cacheRoot).sort().reverse();
for (const version of versions) {
candidates.push(path.join(cacheRoot, version, 'chrome-linux64', 'chrome'));
}
}
} catch (error) {
// Ignoramos y seguimos con rutas fijas.
}
if (process.env.PUPPETEER_EXECUTABLE_PATH) {
candidates.unshift(process.env.PUPPETEER_EXECUTABLE_PATH);
}
candidates.push(
'/usr/bin/google-chrome-stable',
'/usr/bin/google-chrome',
'/usr/bin/chromium',
'/usr/bin/chromium-browser'
);
return candidates.find((candidate) => candidate && fs.existsSync(candidate)) || null;
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function main() {
const orderNumber = (process.argv[2] || '').trim();
const orderCode = (process.argv[3] || '').trim();
if (!orderNumber || !orderCode) {
console.log(JSON.stringify({
success: false,
error: 'Número de orden y código de orden son requeridos.'
}));
process.exit(1);
}
const trackingUrl = `https://shalom.com.pe/rastrea/${encodeURIComponent(orderNumber)}/${encodeURIComponent(orderCode)}`;
let browser = null;
try {
const executablePath = detectChromeExecutable();
browser = await puppeteer.launch({
headless: 'new',
executablePath: executablePath || undefined,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage'
]
});
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 900 });
await page.setUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36');
await page.goto(trackingUrl, {
waitUntil: 'networkidle2',
timeout: 60000,
});
await sleep(4000);
const payload = await page.evaluate(() => {
const textOf = (selectorList) => {
for (const selector of selectorList) {
const el = document.querySelector(selector);
const text = el && el.textContent ? el.textContent.trim() : '';
if (text) return text;
}
return '';
};
const allParagraphs = Array.from(document.querySelectorAll('p'))
.map((p) => (p.textContent || '').trim())
.filter(Boolean);
const status = textOf([
'.text-4xl.font-bold.text-red-color-sidebar',
'.text-3xl.font-bold.text-red-color-sidebar'
]);
let description = textOf([
'p.text-md.font-normal.text-silver-title',
'p.text-sm.font-normal.text-silver-title'
]);
if (!description) {
description = allParagraphs.find((text) => {
return !/^N° DE ORDEN:/i.test(text)
&& !/^Desde el/i.test(text)
&& /destino|recojo|entregado|origen|procesado|tránsito|transito/i.test(text);
}) || '';
}
const orderLabel = allParagraphs.find((text) => /^N° DE ORDEN:/i.test(text)) || '';
const dateLabel = allParagraphs.find((text) => /^Desde el/i.test(text)) || '';
const internalOrderNumber = orderLabel.replace(/^N° DE ORDEN:\s*/i, '').trim();
const bodyText = document.body && document.body.innerText ? document.body.innerText.trim() : '';
return {
status,
description,
orderLabel,
dateLabel,
internalOrderNumber,
requiresLogin: /Inicia sesión para acceder/i.test(bodyText),
currentUrl: location.href,
currentPath: location.pathname,
};
});
if (!payload.status || payload.currentPath === '/rastrea') {
console.log(JSON.stringify({
success: false,
error: 'No se pudo encontrar la guía en el rastreo público de Shalom.',
tracking_url: trackingUrl,
}));
process.exit(2);
}
console.log(JSON.stringify({
success: true,
source: 'shalom_web',
status: payload.status,
description: payload.description,
internal_order_number: payload.internalOrderNumber || null,
external_order_number: orderNumber,
order_code: orderCode,
date_text: payload.dateLabel || null,
tracking_url: trackingUrl,
requires_login: !!payload.requiresLogin,
}));
} catch (error) {
console.log(JSON.stringify({
success: false,
error: error && error.message ? error.message : 'Error al consultar Shalom.',
tracking_url: trackingUrl,
}));
process.exit(3);
} finally {
if (browser) {
try {
await browser.close();
} catch (error) {
// Ignoramos errores al cerrar el navegador.
}
}
}
}
main();