mercadolibre-car-scraper
Version:
TypeScript-based web scraper for MercadoLibre car listings with foreign currency prices
72 lines (71 loc) • 2.75 kB
JavaScript
// 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
};