diff --git a/index.js b/index.js index 13d3a0f..37f32ca 100644 --- a/index.js +++ b/index.js @@ -1,22 +1,13 @@ const cheerio = require("cheerio"); const cron = require("node-cron"); const axios = require("axios"); -const { chromium } = require("playwright"); const fs = require("fs"); const discordWebhook = "https://discord.com/api/webhooks/1439286509390921749/t2Hb8XloF6zhDRYD1yh_QlkHHa9eHUyXvd9TxZRHwqR_b_OxxbnwDgsm4em8TwA9NQIa"; -const priceSelectors = { - miodowamydlarnia: ".projector_prices__price", - greentouch: ".main-price", - amazon: "#corePrice_feature_div .a-price .a-offscreen", - soxo: "#projector_price_value span", - empik: '[data-ta-section="priceMainContainer"] [data-ta="price"]', - notino: "#pd-price", -}; - -const excludePage = ["allegro", "homla.com.pl", "home-you.com"]; +// new version works with ceneo.pl only +const productsIds = ["182928416", "95706396", "90180325"]; function sendMessage(message) { axios.post(discordWebhook, { @@ -36,7 +27,7 @@ async function compareAndSave(productsPrice) { for (const product of productsPrice) { const oldProduct = oldProductsPrice.find( - (oldProduct) => oldProduct.link === product.link + (oldProduct) => oldProduct.name === product.name ); if (oldProduct && oldProduct.price !== product.price) { @@ -45,6 +36,7 @@ async function compareAndSave(productsPrice) { newPrice: product.price, oldPrice: oldProduct.price, link: product.link, + shop: product.shop, }); } } @@ -65,88 +57,40 @@ async function compareAndSave(productsPrice) { ); } -async function getProducts() { - const products = await axios - .get( - "https://db.maciaszek.ovh/api/collections/gifts_items/records?fields=title,link" - ) - .then((response) => response.data.items); - - return products - .filter((product) => product.link !== "") - .filter( - (product) => !excludePage.some((page) => product.link.includes(page)) - ); -} - async function init() { - const productsWithLinks = await getProducts(); - const productsWithBrowser = []; - const productsPrice = []; - const selectors = Object.keys(priceSelectors); + const products = []; - console.log("Zaczynam sprawdzać ceny"); - for (const product of productsWithLinks) { - if (product.link === "") continue; + for (const productId of productsIds) { + const response = await axios.get(`https://www.ceneo.pl/${productId}`); + const $ = cheerio.load(response.data); - try { - const { data } = await axios.get(product.link, { - headers: { - "User-Agent": - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36", - }, - }); + const items = $(".product-offer__container").first(); + for (const item of items) { + let name = $(item).data("productname"); + let price = $(item).data("price"); + let link = `https://www.ceneo.pl/${$(item).data("click-url")}`; + const shop = $(item).data("shopurl") || "ceneo.pl"; - const $ = cheerio.load(data); - const selector = selectors.find((selector) => - product.link.includes(selector) - ); - const price = $(priceSelectors[selector]).text(); - productsPrice.push({ - name: product.title, - price: price, - link: product.link, - }); - } catch { - productsWithBrowser.push(product); + if (!name || !price) { + name = $(item).find(".short-name__txt").text(); + price = $(item).find(".price").text(); + link = `https://www.ceneo.pl/${productId}`; + } + + if (!name || !price || !link) { + continue; + } + + products.push({ name, price, link, shop }); } } - if (productsWithBrowser.length > 0) { - const browser = await chromium.launch(); - const context = await browser.newContext({ - userAgent: - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36", - }); - const page = await context.newPage(); - - for (const product of productsWithBrowser) { - await page.goto(product.link); - const selector = selectors.find((selector) => - product.link.includes(selector) - ); - const element = await page.$(priceSelectors[selector]); - - if (!element) continue; - - const price = await element.textContent(); - productsPrice.push({ - name: product.title, - price: price, - link: product.link, - }); - } - - await browser.close(); - } - - await compareAndSave(productsPrice); - + await compareAndSave(products); console.log("Sprawdzone! Aktualne ceny zapisane w productsPrice.json"); } sendMessage("Zaczynam monitoring cen"); -const task = cron.schedule("0 */3 * * *", init, { +const task = cron.schedule("0 6,9,12,14,16,18,21 * * *", init, { timezone: "Europe/Warsaw", }); diff --git a/index.js.old b/index.js.old new file mode 100644 index 0000000..a8a93a2 --- /dev/null +++ b/index.js.old @@ -0,0 +1,153 @@ +const cheerio = require("cheerio"); +const cron = require("node-cron"); +const axios = require("axios"); +const { chromium } = require("playwright"); +const fs = require("fs"); + +const discordWebhook = + "https://discord.com/api/webhooks/1439286509390921749/t2Hb8XloF6zhDRYD1yh_QlkHHa9eHUyXvd9TxZRHwqR_b_OxxbnwDgsm4em8TwA9NQIa"; + +const priceSelectors = { + miodowamydlarnia: ".projector_prices__price", + greentouch: ".main-price", + amazon: "#corePrice_feature_div .a-price .a-offscreen", + soxo: "#projector_price_value span", + empik: '[data-ta-section="priceMainContainer"] [data-ta="price"]', + notino: "#pd-price", +}; + +const excludePage = ["allegro", "homla.com.pl", "home-you.com"]; + +function sendMessage(message) { + axios.post(discordWebhook, { + content: message, + }); +} + +async function compareAndSave(productsPrice) { + if (!fs.existsSync("productsPrice.json")) { + fs.writeFileSync("productsPrice.json", "[]"); + } + + const productsPriceJson = fs.readFileSync("productsPrice.json", "utf8"); + const oldProductsPrice = JSON.parse(productsPriceJson); + + const diffProducts = []; + + for (const product of productsPrice) { + const oldProduct = oldProductsPrice.find( + (oldProduct) => oldProduct.link === product.link + ); + + if (oldProduct && oldProduct.price !== product.price) { + diffProducts.push({ + name: product.name, + newPrice: product.price, + oldPrice: oldProduct.price, + link: product.link, + }); + } + } + + for (const product of diffProducts) { + sendMessage( + `Zmiana ceny **${product.name}**:\nCena: ${product.oldPrice} -> ${product.newPrice}\nLink: ${product.link}` + ); + } + + if (diffProducts.length === 0) { + sendMessage("Brak zmian w cenach"); + } + + fs.writeFileSync( + "productsPrice.json", + JSON.stringify(productsPrice, null, 2) + ); +} + +async function getProducts() { + const products = await axios + .get( + "https://db.maciaszek.ovh/api/collections/gifts_items/records?fields=title,link" + ) + .then((response) => response.data.items); + + return products + .filter((product) => product.link !== "") + .filter( + (product) => !excludePage.some((page) => product.link.includes(page)) + ); +} + +async function init() { + const productsWithLinks = await getProducts(); + const productsWithBrowser = []; + const productsPrice = []; + const selectors = Object.keys(priceSelectors); + + console.log("Zaczynam sprawdzać ceny"); + for (const product of productsWithLinks) { + if (product.link === "") continue; + + try { + const { data } = await axios.get(product.link, { + headers: { + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36", + }, + }); + + const $ = cheerio.load(data); + const selector = selectors.find((selector) => + product.link.includes(selector) + ); + const price = $(priceSelectors[selector]).text(); + productsPrice.push({ + name: product.title, + price: price, + link: product.link, + }); + } catch { + productsWithBrowser.push(product); + } + } + + if (productsWithBrowser.length > 0) { + const browser = await chromium.launch(); + const context = await browser.newContext({ + userAgent: + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36", + }); + const page = await context.newPage(); + + for (const product of productsWithBrowser) { + await page.goto(product.link); + const selector = selectors.find((selector) => + product.link.includes(selector) + ); + const element = await page.$(priceSelectors[selector]); + + if (!element) continue; + + const price = await element.textContent(); + productsPrice.push({ + name: product.title, + price: price, + link: product.link, + }); + } + + await browser.close(); + } + + await compareAndSave(productsPrice); + + console.log("Sprawdzone! Aktualne ceny zapisane w productsPrice.json"); +} + +sendMessage("Zaczynam monitoring cen"); +const task = cron.schedule("0 6,9,12,15,18,21 * * *", init, { + timezone: "Europe/Warsaw", +}); + +task.execute();