UNPKG

mercadolibre-car-scraper

Version:

TypeScript-based web scraper for MercadoLibre car listings with foreign currency prices

72 lines (71 loc) 2.75 kB
// src/scraper.ts import chromium from "@sparticuz/chromium"; async function getPuppeteerAndOptions() { const isLocal = !process.env.VERCEL; let puppeteer; let launchOptions; if (isLocal) { puppeteer = await import("puppeteer"); launchOptions = { headless: true, args: ["--no-sandbox", "--disable-setuid-sandbox"] }; } else { puppeteer = await import("puppeteer-core"); launchOptions = { args: chromium.args, defaultViewport: chromium.defaultViewport, executablePath: await chromium.executablePath(), headless: "true" }; } return { puppeteer, launchOptions }; } async function scrapeMercadoLibre(producto) { if (!producto || typeof producto !== "string") { throw new Error("Producto debe ser una cadena de texto v\xE1lida"); } const { puppeteer, launchOptions } = await getPuppeteerAndOptions(); let browser = null; try { browser = await puppeteer.launch(launchOptions); const page = await browser.newPage(); const BASE_URL = "https://autos.mercadolibre.com.ar"; const query = producto.trim().replace(/\s+/g, "-"); const url = `${BASE_URL}/${query}`; const response = await page.goto(url, { waitUntil: "networkidle2", timeout: 3e4 }); if (!response?.ok()) { throw new Error(`Error al cargar la p\xE1gina: ${response?.status()}`); } await page.waitForSelector(".ui-search-layout__item", { timeout: 1e4 }); const preciosNoPesos = await page.evaluate(() => { const items = Array.from(document.querySelectorAll(".ui-search-layout__item")); const preciosFiltrados = []; items.forEach((item) => { const frontImageElem = item.querySelector(".poly-component__picture.poly-component__picture--contain"); const precioElem = item.querySelector(".andes-money-amount__fraction"); const simboloElem = item.querySelector(".andes-money-amount__currency-symbol"); const tituloElem = item.querySelector(".poly-component__title"); if (precioElem && simboloElem) { const frontImage = frontImageElem ? frontImageElem.src : ""; const simbolo = simboloElem.textContent || ""; const precio = precioElem.textContent || ""; const titulo = tituloElem ? tituloElem.textContent || "Sin t\xEDtulo" : "Sin t\xEDtulo"; if (simbolo.includes("U$S") || simbolo.includes("USD") || simbolo.includes("US") || simbolo.includes("\u20AC") || simbolo.includes("\xA3")) { preciosFiltrados.push({ titulo, simbolo, precio, frontImage }); } } }); return preciosFiltrados; }); return preciosNoPesos; } finally { if (browser) await browser.close(); } } export { scrapeMercadoLibre };