Files
disney-cruise-prices/index.ts

202 lines
8.1 KiB
TypeScript

import puppeteer, {Page} from 'puppeteer';
import * as fs from "fs";
import {createCsvFromJson, createCsvFromJsonArray} from "./flatten-data";
(async () => {
const browser = await puppeteer.launch({headless: false, devtools: true});
const page = await browser.newPage();
await page.goto('https://disneycruise.disney.go.com/cruises-destinations/list/#september-2023,october-2023,january-2024,february-2024,march-2024,april-2024,may-2024,alaska-cruises,bahamas-cruises,bermuda-cruises,canada-cruises,caribbean-cruises,mexico-cruises,pacific-coast-cruises,5-to-6');
// Set screen size
await page.setViewport({width: 1519, height: 1024});
// Type into search box
// await page.type('.search-box__input', 'automate beyond recorder');
// Wait and click on first result
const showDatesButtonSelector = '.product-card-footer-wrapper__btn';
await page.waitForSelector(showDatesButtonSelector);
// await page.click(showDatesButtonSelector);
// Scroll down
// should scroll down until the button count stops going up
let buttonCountChanged = true;
let buttonCount = 0;
let buttonElements = await page.$$(showDatesButtonSelector);
buttonCount = buttonElements.length;
// while (buttonCountChanged) {
// await page.evaluate(() => {
// window.scrollBy(0, window.innerHeight)
// return Promise.resolve();
// });
// buttonElements = await page.$$(showDatesButtonSelector);
// if (buttonElements.length > buttonCount) {
// buttonCount = buttonElements.length;
// } else {
// buttonCountChanged = false;
// }
// }
//
// for (let i = 0; i < buttonElements.length; i++) {
// console.log(buttonElements[i]);
// await buttonElements[i].click();
// // await page.waitForSelector('wdpr-price');
// // const price = await page.$eval('wdpr-price', (el) => el.textContent);
// // console.log('price', price);
// }
const data = await getAvailableProducts(page);
// console.log('data');
// console.log(JSON.stringify(data, null, ' '));
fs.writeFileSync('products.json', JSON.stringify(data, null, ' '));
createCsvFromJsonArray(data.products, 'products.csv');
let availableSailings = await Promise.all(data.products.map(async (product: { productId: string; itineraries: { itineraryId: string; }[]; }) => {
return getAvailableSailings(page, product.productId, product.itineraries[0].itineraryId).then(({sailings}): any[] => {
return sailings;
});
})).then((results) => {
let sailings: any[] = [];
results.forEach((result) => {
sailings = sailings.concat(result);
});
return sailings;
});
console.log('availableSailings');
console.log(JSON.stringify(availableSailings, null, ' '));
fs.writeFileSync('sailings.json', JSON.stringify(availableSailings, null, ' '));
createCsvFromJsonArray(availableSailings, 'sailings.csv');
console.log('buttonCount', buttonCount);
// // Locate the full title with a unique string
// const textSelector = await page.waitForSelector(
// 'text/Customize and automate'
// );
// // @ts-ignore
// const fullTitle = await textSelector.evaluate(el => el.textContent);
//
// // Print the full title
// console.log('The title of this blog post is "%s".', fullTitle);
await browser.close();
})();
// function getButtonCount(page: Page) {
// return page.$$('.product-card-footer-wrapper__btn').then((buttonElements) => {
// return buttonElements.length;
// });
// }
function getAvailableProducts(page: Page): Promise<any> {
return page.evaluate(() => {
return getProductsPage(1).then((data) => {
let pageCount = data.totalPages;
let promises = [];
for (let i = 2; i <= pageCount; i++) {
promises.push(getProductsPage(i));
}
return Promise.all(promises).then((results) => {
results.forEach((result) => {
data.products = data.products.concat(result.products);
});
return data;
});
});
function getProductsPage(pageCount = 1): Promise<any> {
return fetch('/dcl-apps-productavail-vas/available-products/', {
body: JSON.stringify({
"currency": "USD",
"filters": ["2023-09;filterType=date", "2023-10;filterType=date", "2024-01;filterType=date", "2024-02;filterType=date", "2024-03;filterType=date", "2024-04;filterType=date", "2024-05;filterType=date", "ALASKA;filterType=destination", "BAHAMAS;filterType=destination", "BERMUDA;filterType=destination", "CANADA;filterType=destination", "CARIBBEAN;filterType=destination", "MEXICAN RIVIERA;filterType=destination", "CALIFORNIA COAST;filterType=destination", "5-6;filterType=night"],
"partyMix": [{
"accessible": false,
"adultCount": 2,
"childCount": 2,
"nonAdultAges": [{"age": 7, "ageUnit": "YEAR"}, {"age": 9, "ageUnit": "YEAR"}],
"partyMixId": "0"
}],
"region": "INTL",
"storeId": "DCL",
"affiliations": [],
"page": pageCount,
"pageHistory": false,
"includeAdvancedBookingPrices": true,
"exploreMorePage": 1,
"exploreMorePageHistory": false
}),
headers: {
'Content-Type': 'application/json'
},
method: 'POST'
}).then((response) => {
return response.json();
}).then((data) => {
return data;
});
}
});
}
async function getAvailableSailings(page: Page, productID: string, itineraryId: string): Promise<any> {
return await page.evaluate((productID, itineraryId) => {
return fetch('/dcl-apps-productavail-vas/available-sailings/', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
"currency": "USD",
"filters": [
"2023-09;filterType=date",
"2023-10;filterType=date",
"2024-01;filterType=date",
"2024-02;filterType=date",
"2024-03;filterType=date",
"2024-04;filterType=date",
"2024-05;filterType=date",
"ALASKA;filterType=destination",
"BAHAMAS;filterType=destination",
"BERMUDA;filterType=destination",
"CANADA;filterType=destination",
"CARIBBEAN;filterType=destination",
"MEXICAN RIVIERA;filterType=destination",
"CALIFORNIA COAST;filterType=destination",
"5-6;filterType=night"
],
"partyMix": [
{
"accessible": false,
"adultCount": 2,
"childCount": 2,
"nonAdultAges": [
{
"age": 7,
"ageUnit": "YEAR"
},
{
"age": 9,
"ageUnit": "YEAR"
}
],
"partyMixId": "0"
}
],
"region": "INTL",
"storeId": "DCL",
"affiliations": [],
"itineraryId": itineraryId,
"productId": productID,
"includeAdvancedBookingPrices": true
})
}).then((response) => {
return response.json();
}).then((data) => {
return data;
});
}, productID, itineraryId);
}