Files
bpi-stock-price-scraper/index.mjs
T
Lino Silva be8ff08f94
Build and publish / build (push) Successful in 37s
updated symbols
2026-03-20 15:41:47 +00:00

104 lines
2.8 KiB
JavaScript

import puppeteer from "puppeteer";
import process from "node:process";
import axios from "axios";
import "dotenv/config";
const contas = {
bpi2040: {
url: "https://www.bancobpi.pt/particulares/poupar-investir/ppr/bpi-destino-ppr-2040",
ghostfolioName: "GF_BPI_Destino_PPR_2040",
},
bpi2050: {
url: "https://www.bancobpi.pt/particulares/poupar-investir/ppr/bpi-destino-ppr-2050",
ghostfolioName: "GF_BPI_Destino_PPR_2050",
},
};
async function parseLogRocketBlogHome(conta) {
// Launch the browser
const browser = await puppeteer.launch({
args: ["--no-sandbox"],
timeout: 10000,
});
// Open a new tab
const page = await browser.newPage();
// Visit the page and wait until network connections are completed
await page.goto(conta.url, { waitUntil: "networkidle2" });
// Interact with the DOM to retrieve the titles
const [price, date] = await page.evaluate(() => {
const spanTags = document.getElementsByTagName("span");
const priceSearchText = "ÚLTIMA COTAÇÃO:";
const dateSearchText = "DATA COTAÇÃO:";
let priceElementFound;
let dateElementFound;
for (let i = 0; i < spanTags.length; i++) {
if (spanTags[i].textContent.trim() == priceSearchText) {
priceElementFound = spanTags[i];
console.log(`Found ${priceSearchText}.`);
if (priceElementFound && dateElementFound) break;
}
if (spanTags[i].textContent.trim() == dateSearchText) {
dateElementFound = spanTags[i];
console.log(`Found ${dateSearchText}.`);
if (priceElementFound && dateElementFound) break;
}
}
return [
priceElementFound.nextSibling.innerHTML,
dateElementFound.nextSibling.innerHTML,
];
});
// Don't forget to close the browser instance to clean up the memory
await browser.close();
const marketPrice = parseFloat(
price.replace("€", "").trim().replace(",", "."),
);
// Print the results
console.log(decodeURIComponent(conta.ghostfolioName));
console.log(`Current price: € ${marketPrice}`);
console.log(`Date: ${date}`);
const bearerTokenResponse = await axios.post(
`${process.env.GHOSTFOLIO_HOST}/api/v1/auth/anonymous`,
{
accessToken: process.env.GHOSTFOLIO_SECURITY_TOKEN,
},
);
const response = await axios
.post(
`${process.env.GHOSTFOLIO_HOST}/api/v1/market-data/MANUAL/${conta.ghostfolioName}`,
{
marketData: [
{
date,
marketPrice,
},
],
},
{
headers: {
Authorization: `Bearer ${bearerTokenResponse.data.authToken}`,
},
},
)
.catch(console.error);
console.log(response.status);
}
await Promise.all([
parseLogRocketBlogHome(contas.bpi2040),
parseLogRocketBlogHome(contas.bpi2050),
]);
process.exit(0);