如何用Puppeteer点击希尔顿官网日历弹窗的下月按钮?
问题描述
使用Puppeteer操作希尔顿官网时,无法点击日历弹窗的下月按钮,日历弹窗截图如下:
代码问题
以下代码行执行无效:
await page.click('[data-testid="calendar-container"] > [class="flex justify-between"] > [class="sr-only"]');
hilton_constants.js 文件
START_MONTH: "September", START_DAY: 1, START_YEAR: 2023, END_MONTH: "September", END_DAY: 4, END_YEAR: 2023,
主Node函数
const puppeteer = require('puppeteer-extra'); const constants = require('./hilton_constants.js'); const fs = require('fs/promises'); // * Main Function let browser; async function hiltonScan() { browser = await puppeteer.launch({ headless: false }); const [page] = await browser.pages(); const ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"; await page.setUserAgent(ua); await page.setViewport({ width: 750, height: 10700 }); // Block resources await page.setRequestInterception(true); page.on('request', (request) => { if (request.resourceType() === 'image' || request.resourceType() === 'font' || request.resourceType() === 'media') { request.abort(); } else { request.continue() } }); await page.goto('https://www.hilton.com/en/', { waitUntil: "domcontentloaded" }); // Fill in Location await page.type('[class="form-input w-full"]', "Seattle, WA, USA"); // Click calendar UI to select dates await page.click('[data-testid="search-dates-button"]'); await page.waitForSelector('[data-testid="calendar-container"]'); // ! This is NOT WORKING - Fill in calendar UI stay dates await fill_stayDates(page, constants); //* Helper function for above: click to the correct starting month async function fill_stayDates(page, constants){ const findMonth = async targetMonth => { for (let i = 0; i < 12; i++) { // Not sure if this is causing an error const month = await page.$eval('[id^="calendar-month-"]', el => el.textContent); if (month.includes(targetMonth)) break; //! THIS IS NOT WORKING await page.click('[data-testid="calendar-container"] > [class="flex justify-between"] > [class="sr-only"]'); }; await findMonth(constants.START_MONTH); await chooseDay(constants.START_DAY); await findMonth(constants.END_MONTH); await chooseDay(constants.END_DAY); // click X button to close await page.click('[class="stroke-text"]'); }; //! this works, comment out for now Click Find a Hotel // await page.click('[data-testid="search-submit-button"]'); // Wait for navigation await page.waitForNavigation(); } } // * Call the main function (async () => { console.log('Starting the Hilton scraper program...'); await hiltonScan() .catch(err => console.error(err)) .finally(() => browser?.close()); })();
核心问题:fill_stayDates函数中用于切换目标月份的下月按钮点击代码无法执行,需解决该问题。
解决方案
1. 修正选择器问题
原选择器依赖的sr-only类是屏幕阅读器专用的隐藏元素,实际可交互的下月按钮是它的父级或带有明确标识的元素。替换为精准的交互元素选择器:
// 优先使用data-testid标识的按钮 await page.click('[data-testid="calendar-next-button"]'); // 若data-testid不存在,使用aria标签选择器 await page.click('[aria-label="Next month"]');
2. 增加元素可见性与可交互性检查
点击前确保按钮已完全渲染并可操作,避免因元素未加载完成导致点击失效:
// 等待按钮可见且可交互 await page.waitForSelector('[aria-label="Next month"]', { visible: true, timeout: 5000 }); await page.click('[aria-label="Next month"]');
3. 修复findMonth函数语法错误
原函数的for循环缺少闭合},导致逻辑异常,修正后完整函数:
const findMonth = async targetMonth => { for (let i = 0; i < 12; i++) { // 等待月份标题加载完成 await page.waitForSelector('[id^="calendar-month-"]', { visible: true }); const month = await page.$eval('[id^="calendar-month-"]', el => el.textContent.trim()); if (month.includes(targetMonth)) break; // 点击下月按钮 await page.waitForSelector('[aria-label="Next month"]', { visible: true }); await page.click('[aria-label="Next month"]'); } };
4. 补充chooseDay函数实现
原代码缺少日期选择的核心函数,补充如下:
async function chooseDay(day) { // 等待目标日期元素可见 await page.waitForSelector(`[data-testid="calendar-day-${day}"]`, { visible: true }); await page.click(`[data-testid="calendar-day-${day}"]`); }
5. 优化日历弹窗加载等待逻辑
调用日期选择函数前,确保日历弹窗完全渲染:
await page.click('[data-testid="search-dates-button"]'); // 等待日历内的月份标题可见,确认弹窗加载完成 await page.waitForSelector('[id^="calendar-month-"]', { visible: true }); await fill_stayDates(page, constants);
内容的提问来源于stack exchange,提问作者Nelson Mak
相关产品推荐
相关产品推荐

