Puppeteer偶发打开about:blank页面问题求助:原因与解决办法
Puppeteer频繁打开about:blank页面问题排查与解决
问题背景
在Windows虚拟机部署定时网页爬虫(每隔数小时运行一次),多数情况正常,但频繁出现Puppeteer打开about:blank而非目标页面(aliexpress.com)的情况。
复现代码:
import puppeteer from 'puppeteer' import { scheduleJob } from 'node-schedule'; async function run() { const browser = await puppeteer.launch({ headless: false, executablePath: chromePath, defaultViewport: null, timeout: 0, args: ['--no-sandbox', '--start-maximized'], }); const page = await browser.newPage(); await page.evaluateOnNewDocument(() => { Object.defineProperty(navigator, 'webdriver', { get: () => false, }); }); await page.goto('https://aliexpress.com', { waitUntil: 'networkidle0', timeout: 0, }); } run(); scheduleJob('scrape aliexpress', `0 */${hours} * * *`, run);
原因分析
- 浏览器资源未回收:每次
run()都会新建Chrome浏览器实例,但未主动关闭。虚拟机资源有限,多次运行后内存/CPU耗尽,导致新页面无法正常加载目标URL,停留在about:blank。 - 定时任务重叠执行:如果前一次爬虫任务因网络或页面加载慢未完成,新的定时任务又启动,多个浏览器实例抢占资源,引发加载异常。
- 目标网站拦截或网络问题:虚拟机网络不稳定,或AliExpress的反爬机制触发,导致
page.goto()请求失败,页面停留在初始的about:blank。 - Puppeteer与Chrome版本不兼容:
executablePath指定的Chrome版本和当前Puppeteer版本不匹配,导致页面加载逻辑出现异常。
解决方案
1. 强制回收浏览器资源
在run()中添加try/finally块,确保无论任务成功或失败,都关闭浏览器实例:
async function run() { let browser = null; try { browser = await puppeteer.launch({ headless: false, executablePath: chromePath, defaultViewport: null, timeout: 0, args: ['--no-sandbox', '--start-maximized', '--disable-gpu'], // 减少GPU资源占用 }); const page = await browser.newPage(); await page.evaluateOnNewDocument(() => { Object.defineProperty(navigator, 'webdriver', { get: () => false, }); }); await page.goto('https://aliexpress.com', { waitUntil: 'networkidle2', // 改用更稳定的等待策略,降低超时概率 timeout: 30000, // 恢复超时设置,避免无限等待 }); // 此处添加你的爬虫业务逻辑 } catch (error) { console.error('爬虫执行出错:', error); } finally { if (browser) { await browser.close(); // 确保浏览器实例被销毁 } } }
2. 避免定时任务重叠
添加运行状态锁,确保同一时间只有一个爬虫任务在执行:
let isRunning = false; async function run() { if (isRunning) { console.log('已有任务在运行,跳过本次执行'); return; } isRunning = true; let browser = null; try { // 原有爬虫逻辑... } finally { isRunning = false; if (browser) { await browser.close(); } } }
3. 增强错误处理与重试机制
对page.goto()添加重试逻辑,应对临时网络问题或拦截:
async function gotoWithRetry(page, url, maxRetries = 3) { let retries = 0; while (retries < maxRetries) { try { await page.goto(url, { waitUntil: 'networkidle2', timeout: 30000, }); // 验证页面是否加载成功 const pageUrl = await page.url(); if (!pageUrl.includes('about:blank')) { return; } } catch (error) { console.log(`加载失败,重试第${retries+1}次`, error); } retries++; await new Promise(resolve => setTimeout(resolve, 5000)); // 重试前等待5秒 } throw new Error(`重试${maxRetries}次后仍无法加载页面`); } // 在run()中替换原page.goto: await gotoWithRetry(page, 'https://aliexpress.com');
4. 对齐Puppeteer与Chrome版本
- 若使用指定的Chrome,确认其版本与Puppeteer兼容(可查看Puppeteer官方文档的版本对应表);
- 或移除
executablePath配置,让Puppeteer自动下载匹配版本的Chrome,避免版本不兼容问题。
5. 优化虚拟机资源配置
增加Windows虚拟机的内存和CPU分配,避免因资源不足导致浏览器无法正常运行。
内容的提问来源于stack exchange,提问作者Usman Sabuwala
相关产品推荐
相关产品推荐

