What Changed: - Added VERIFIED-PRICES.md with honest assessment - Added BUDGET-REALITY.md explaining challenges - Added disclaimers to all option files - Clearly marked estimates vs verified data Key Findings: - Could NOT get live quotes due to cookie popups - £2,000 budget is VERY TIGHT for July/Aug peak - Realistic Eurocamp: £1,500-2,500 for 14 nights - Brittany Ferries: £850-1,100 return with cabin Verified Data: - Siblu Kerlann: €250/week (June OFF-PEAK) - Eurotunnel: £250-400 return avg - Budgeting Mum: £600/10 nights OFF-PEAK User action needed: - Manually check Eurocamp.co.uk - Consider shorter duration - Consider gîte instead of mobile home
150 lines
5.3 KiB
JavaScript
150 lines
5.3 KiB
JavaScript
const { chromium } = require('playwright');
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
async function searchSiblu() {
|
||
const browser = await chromium.launch({ headless: true });
|
||
const context = await browser.newContext({
|
||
viewport: { width: 1920, height: 1080 },
|
||
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
|
||
});
|
||
const page = await context.newPage();
|
||
|
||
const screenshotDir = path.join(process.env.HOME, 'holiday-planning', 'price-evidence');
|
||
const results = {
|
||
searchDate: new Date().toISOString(),
|
||
park: 'Domaine de Kerlann',
|
||
dates: {
|
||
checkIn: '2026-07-18',
|
||
checkOut: '2026-08-02',
|
||
nights: 14
|
||
},
|
||
guests: {
|
||
adults: 2,
|
||
children: 1,
|
||
childAge: 6
|
||
},
|
||
screenshots: [],
|
||
status: 'in_progress'
|
||
};
|
||
|
||
try {
|
||
console.log('🔍 Navigating to Siblu website...');
|
||
await page.goto('https://www.siblu.co.uk', { waitUntil: 'networkidle', timeout: 60000 });
|
||
await page.screenshot({ path: path.join(screenshotDir, '01-homepage.png'), fullPage: false });
|
||
results.screenshots.push('01-homepage.png');
|
||
console.log('✅ Homepage loaded');
|
||
|
||
// Handle cookie consent
|
||
try {
|
||
console.log('🍪 Looking for cookie consent...');
|
||
const cookieBtn = await page.waitForSelector('#onetrust-accept-btn-handler, button:has-text("Accept"), button:has-text("accept"), [data-cookie-accept]', { timeout: 5000 });
|
||
if (cookieBtn) {
|
||
await cookieBtn.click();
|
||
await page.waitForTimeout(1000);
|
||
console.log('✅ Cookies accepted');
|
||
}
|
||
} catch (e) {
|
||
console.log('ℹ️ No cookie banner found or already accepted');
|
||
}
|
||
|
||
// Look for the park - try direct URL first
|
||
console.log('🔍 Navigating to Domaine de Kerlann park page...');
|
||
await page.goto('https://www.siblu.co.uk/holiday-parcs/brittany/domaine-de-kerlann', { waitUntil: 'networkidle', timeout: 60000 });
|
||
await page.screenshot({ path: path.join(screenshotDir, '02-park-page.png'), fullPage: false });
|
||
results.screenshots.push('02-park-page.png');
|
||
console.log('✅ Park page loaded');
|
||
|
||
// Wait for booking widget/form to load
|
||
await page.waitForTimeout(2000);
|
||
|
||
// Try to find and interact with booking form
|
||
console.log('📅 Looking for booking form...');
|
||
|
||
// Look for check-in date field
|
||
const dateSelectors = [
|
||
'input[name="checkIn"]',
|
||
'input[name="arrival-date"]',
|
||
'input[placeholder*="Check in"]',
|
||
'input[placeholder*="Arrival"]',
|
||
'[data-testid="checkin-input"]',
|
||
'.booking-form input[type="date"]',
|
||
'#checkin',
|
||
'#arrival-date'
|
||
];
|
||
|
||
let dateField = null;
|
||
for (const selector of dateSelectors) {
|
||
try {
|
||
dateField = await page.$(selector);
|
||
if (dateField) {
|
||
console.log(`Found date field: ${selector}`);
|
||
break;
|
||
}
|
||
} catch (e) {}
|
||
}
|
||
|
||
// Try to find a "Book now" or search button that might open booking
|
||
const bookButtons = await page.$$('button:has-text("Book"), a:has-text("Book"), button:has-text("Check availability"), a:has-text("Check availability")');
|
||
if (bookButtons.length > 0) {
|
||
console.log('🖱️ Clicking book/availability button...');
|
||
await bookButtons[0].click();
|
||
await page.waitForTimeout(3000);
|
||
await page.screenshot({ path: path.join(screenshotDir, '03-after-book-click.png'), fullPage: false });
|
||
results.screenshots.push('03-after-book-click.png');
|
||
}
|
||
|
||
// Take screenshot of current state
|
||
await page.screenshot({ path: path.join(screenshotDir, '04-booking-form.png'), fullPage: true });
|
||
results.screenshots.push('04-booking-form.png');
|
||
|
||
// Get page content for analysis
|
||
const content = await page.content();
|
||
fs.writeFileSync(path.join(screenshotDir, 'page-content.html'), content);
|
||
console.log('📝 Saved page content');
|
||
|
||
// Try to find any booking widget or iframe
|
||
const iframes = await page.$$('iframe');
|
||
console.log(`Found ${iframes.length} iframes`);
|
||
|
||
for (let i = 0; i < iframes.length; i++) {
|
||
const frame = await iframes[i].contentFrame();
|
||
if (frame) {
|
||
try {
|
||
const frameContent = await frame.content();
|
||
fs.writeFileSync(path.join(screenshotDir, `iframe-${i}-content.html`), frameContent);
|
||
} catch (e) {}
|
||
}
|
||
}
|
||
|
||
// Look for any price information on the page
|
||
const pageText = await page.textContent('body');
|
||
const priceMatches = pageText.match(/£[\d,]+/g);
|
||
if (priceMatches) {
|
||
console.log('💰 Found prices on page:', priceMatches.slice(0, 10));
|
||
results.pricesFound = priceMatches;
|
||
}
|
||
|
||
results.status = 'form_found';
|
||
results.url = page.url();
|
||
|
||
} catch (error) {
|
||
console.error('❌ Error:', error.message);
|
||
results.error = error.message;
|
||
results.stack = error.stack;
|
||
await page.screenshot({ path: path.join(screenshotDir, 'error-screenshot.png'), fullPage: true });
|
||
results.screenshots.push('error-screenshot.png');
|
||
}
|
||
|
||
await browser.close();
|
||
|
||
// Save results
|
||
const resultsPath = path.join(process.env.HOME, 'holiday-planning', 'prices', 'siblu-domaine-de-kerlann.json');
|
||
fs.writeFileSync(resultsPath, JSON.stringify(results, null, 2));
|
||
console.log(`\n📝 Results saved to: ${resultsPath}`);
|
||
|
||
return results;
|
||
}
|
||
|
||
searchSiblu().catch(console.error);
|