Puppeteer无头运行无结果,浏览器控制台正常问题排查
问题:Puppeteer抓取Booking.com酒店名称返回空数组,浏览器控制台却正常
以下是用于抓取特定地点酒店名称的代码:
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); const url= 'https://www.booking.com/searchresults.en-us.html?label=gen173nr-1FCAEoggI46AdIM1gEaLUBiAEBmAExuAEXyAEP2AEB6AEB-AECiAIBqAIDuAL_6vKbBsACAdICJDA0MjU3ZGNjLTJlOWEtNDMyYi1hNDQ2LTg0MmIwMjczYjMzYtgCBeACAQ&sid=5727a604ee8453f41f52e9d9b2d7a5c8&aid=304142&ss=Mingora&ssne=Mingora&ssne_untouched=Mingora&efdco=1&lang=en-us&sb=1&src_elem=sb&src=searchresults&dest_id=-2769132&dest_type=city&checkin=2022-11-27&checkout=2022-11-30&group_adults=2&no_rooms=1&group_children=0&sb_travel_purpose=leisure' await page.goto(url); await page.screenshot({path: 'example.png'}); const selector = "#search_results_table div > h3 > a"; const titles = await page.evaluate(() => Array.from(document.querySelectorAll("h3.a4225678b2 a.e13098a59f")) .map((name) => name.textContent) ); console.log(titles.length); console.log(titles); await browser.close(); })();
这段代码里的选择器在Chrome控制台执行能正常获取酒店名称,但用Puppeteer运行时返回空数组,哪里操作错了?
可能的原因及解决办法
页面加载不完全,元素还未渲染
Puppeteer默认的page.goto(url)只等待页面load事件完成,但Booking.com的搜索结果是动态渲染的,可能代码执行时元素还没生成。可以两种方式解决:// 方式1:等待网络空闲(大部分资源加载完毕) await page.goto(url, { waitUntil: 'networkidle2' }); // 方式2:显式等待目标元素出现,超时时间设为10秒 await page.waitForSelector("h3.a4225678b2 a.e13098a59f", { timeout: 10000 });无头浏览器环境导致页面渲染差异
Booking.com可能会识别无头浏览器,返回不同的DOM结构或内容。可以禁用无头模式,或者模拟真实浏览器的UA:// 禁用无头模式,直观查看页面加载情况 const browser = await puppeteer.launch({ headless: false }); // 或者设置真实浏览器的UA await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36');动态内容需要滚动触发加载
部分搜索结果需要滚动页面才会加载,如果当前视图里没有目标元素,querySelectorAll自然返回空。可以先滚动页面再获取:// 滚动到页面底部 await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); // 等待2秒让内容加载 await page.waitForTimeout(2000);动态类名已更新
代码里用的a4225678b2、e13098a59f这类类名是网站动态生成的,可能Puppeteer访问时已经变化。改用更稳定的选择器,比如基于元素的属性或固定结构:// 比如用data-testid属性(如果网站有提供),或者父元素的固定类 const titles = await page.evaluate(() => Array.from(document.querySelectorAll("#search_results_table h3 > a[data-testid='title']")) .map(name => name.textContent.trim()) );
内容的提问来源于stack exchange,提问作者Johnfranklien
相关产品推荐
相关产品推荐

