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 }); // Handle cookie consent console.log('šŸŖ Handling cookie consent...'); await page.waitForTimeout(2000); await page.evaluate(() => { const agreeBtn = document.getElementById('didomi-notice-agree-button'); if (agreeBtn) agreeBtn.click(); }); await page.waitForTimeout(1500); await page.screenshot({ path: path.join(screenshotDir, '01-homepage.png'), fullPage: false }); results.screenshots.push('01-homepage.png'); console.log('āœ… Homepage loaded'); // Navigate to the CORRECT park page console.log('šŸ” Navigating to Domaine de Kerlann park page...'); const parkUrl = 'https://siblu.co.uk/camping/france/west-coast/brittany/domaine-de-kerlann'; await page.goto(parkUrl, { waitUntil: 'networkidle', timeout: 60000 }); // Handle any new cookie popup await page.waitForTimeout(2000); await page.evaluate(() => { const agreeBtn = document.getElementById('didomi-notice-agree-button'); if (agreeBtn) agreeBtn.click(); const didomiHost = document.getElementById('didomi-host'); if (didomiHost) didomiHost.style.display = 'none'; }); await page.waitForTimeout(1000); await page.screenshot({ path: path.join(screenshotDir, '02-park-page.png'), fullPage: true }); results.screenshots.push('02-park-page.png'); console.log('āœ… Park page loaded: ' + page.url()); // Save the HTML for analysis const html = await page.content(); fs.writeFileSync(path.join(screenshotDir, 'park-page-content.html'), html); // Look for booking widget or availability search console.log('šŸ“… Looking for booking form...'); // Check for various types of booking elements const bookingElements = await page.evaluate(() => { const elements = []; // Look for forms document.querySelectorAll('form').forEach((form, i) => { elements.push({ type: 'form', index: i, action: form.action, id: form.id, className: form.className }); }); // Look for input fields document.querySelectorAll('input').forEach((input, i) => { elements.push({ type: 'input', index: i, name: input.name, inputType: input.type, placeholder: input.placeholder, id: input.id }); }); // Look for booking/search buttons document.querySelectorAll('button, a').forEach((btn, i) => { const text = btn.textContent.trim(); if (text.toLowerCase().includes('book') || text.toLowerCase().includes('availability') || text.toLowerCase().includes('search') || text.toLowerCase().includes('check')) { elements.push({ type: 'button', index: i, text: text.substring(0, 50), tagName: btn.tagName, href: btn.href || null }); } }); return elements; }); console.log('Found elements:', JSON.stringify(bookingElements, null, 2)); results.bookingElements = bookingElements; // Try to find and interact with the booking widget // Siblu often uses a "Book now" button that links to their booking engine // Look for links to booking const bookLinks = await page.$$('a[href*="booking"], a[href*="book"], a:has-text("Book"), a:has-text("Check availability")'); for (const link of bookLinks) { const href = await link.getAttribute('href'); const text = await link.textContent(); console.log(`Found book link: "${text.trim()}" -> ${href}`); } // Check if there's an inline booking widget const hasWidget = await page.evaluate(() => { const widgets = document.querySelectorAll('[class*="booking"], [class*="widget"], [id*="booking"], iframe'); return Array.from(widgets).map(w => ({ tag: w.tagName, id: w.id, className: w.className, src: w.src || null })); }); console.log('Booking widgets found:', hasWidget); results.widgets = hasWidget; // Take final screenshot await page.screenshot({ path: path.join(screenshotDir, '03-final-state.png'), fullPage: true }); results.screenshots.push('03-final-state.png'); // Look for any price information on the page const pageText = await page.textContent('body'); const priceMatches = pageText.match(/Ā£[\d,]+\.?\d*/g); if (priceMatches) { console.log('šŸ’° Found prices on page:', [...new Set(priceMatches)].slice(0, 20)); results.pricesFound = [...new Set(priceMatches)]; } // Try to find accommodation/accommodation info const accMatches = pageText.match(/(?:mobile home|caravan|chalet|lodge|accommodation|from\s*Ā£|starting\s*from)/gi); if (accMatches) { results.accommodationKeywords = accMatches.slice(0, 20); } results.url = page.url(); results.status = 'page_analyzed'; } catch (error) { console.error('āŒ Error:', error.message); results.error = error.message; await page.screenshot({ path: path.join(screenshotDir, 'error-screenshot.png'), fullPage: true }); results.screenshots.push('error-screenshot.png'); } await browser.close(); 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);