You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Puppeteer Headless Chrome突发停止运行问题排查求助

排查Puppeteer加载重页面卡住的问题

我来帮你一步步定位这个突然出现的问题,结合你的代码和描述,咱们从几个关键方向入手:

1. 优化日志与错误捕获

你的自定义日志只记录了手动输出的内容,但没捕获Puppeteer、Chrome或页面本身的异常,很可能卡住的原因(比如Chrome崩溃、页面JS报错)没被记录下来。建议:

  • 添加页面和浏览器的事件监听,捕获错误、控制台输出、资源加载失败等关键事件
  • 确保日志立即写入磁盘,避免缓冲导致日志丢失

修改后的日志和监听逻辑示例:

const logStream = fs.createWriteStream('log.txt', { flags: 'a' });
const log = (message) => {
  console.log(message);
  logStream.write(`[${new Date().toISOString()}] ${message}\n`);
  logStream.flush(); // 强制立即写入日志
};

// 监听浏览器意外断开
browser.on('disconnected', () => {
  log('Browser disconnected unexpectedly');
});

// 监听页面JS错误
page.on('error', (err) => {
  log(`Page JS error: ${err.stack}`);
});

// 监听页面控制台输出(方便排查页面内的问题)
page.on('console', (msg) => {
  log(`Page console [${msg.type()}]: ${msg.text()}`);
});

// 监听资源加载失败
page.on('requestfailed', (request) => {
  log(`Resource failed: ${request.url()} - ${request.failure().errorText}`);
});

2. 替换固定延迟为精准等待

你用了大量waitForTimeout,这种固定延迟完全依赖经验值,在页面加载波动(尤其是2-3分钟的AJAX请求)时非常不可靠。应该换成基于页面状态的等待:

  • 等待AJAX加载完成后才出现的标志性元素(比如某个数据列表、加载完成提示):
    // 替换成你页面中实际的选择器
    await page.waitForSelector('#ajax-loaded-content', { timeout: 0 });
    
  • 或者等待网络彻底空闲(比如3秒内无任何请求):
    await page.waitForNetworkIdle({ idleTime: 3000, timeout: 0 });
    

3. 检查Chrome与Puppeteer版本兼容性

如果服务器上的Chrome自动更新了,但你的Puppeteer版本没同步升级,很可能出现兼容性问题:

  1. 运行google-chrome-stable --version查看当前Chrome版本
  2. 对比Puppeteer官方的版本对应表,确保两者版本匹配
  3. 如果不匹配,要么升级Puppeteer,要么改用puppeteer-core让它自动适配现有Chrome版本

4. 排查Headless模式差异

本地浏览器是正常交互模式,而Puppeteer用的是Headless,部分页面会检测Headless环境或在该模式下加载资源失败:

  • 临时将headless改为false(如果服务器支持图形界面,或用xvfb模拟),看是否能正常运行
  • 设置与本地浏览器一致的User Agent,避免被反爬机制拦截:
    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');
    

5. 检查服务器资源限制

Chrome加载重页面会占用大量内存和CPU,如果服务器内存不足,可能被系统的OOM Killer强制杀掉:

  • 查看服务器系统日志(比如/var/log/syslog或dmesg),搜索out of memory或chrome相关的崩溃记录
  • 添加Chrome启动参数缓解内存问题:
    args: [
      '--disable-dev-shm-usage', // 解决/dev/shm内存不足问题
      '--no-sandbox', // 非root运行可省略,root运行必须加
      '--disable-setuid-sandbox'
    ]
    

6. 开启详细调试日志

你已经加了--enable-logging --v=1,可以进一步调高日志级别并捕获所有输出:

  • 将启动参数改为--enable-logging=stderr --v=2,获取更详细的Chrome日志
  • 运行脚本时将所有输出重定向到文件:
    node your-script.js > puppeteer-full.log 2>&1
    
    这个日志文件会包含Chrome的所有调试信息,能帮你找到崩溃或卡住的具体原因

完整优化后的代码示例

const fs = require('fs');
const puppeteer = require('puppeteer');

async function run() {
  const searchURL = "your-target-url";
  const logStream = fs.createWriteStream('log.txt', { flags: 'a' });
  const log = (message) => {
    console.log(message);
    logStream.write(`[${new Date().toISOString()}] ${message}\n`);
    logStream.flush();
  };

  try {
    log('Starting Puppeteer PDF process...');
    const browser = await puppeteer.launch({ 
      dumpio: true, 
      executablePath: '/usr/bin/google-chrome-stable', 
      args: [
        '--enable-logging=stderr',
        '--v=2',
        '--disable-dev-shm-usage',
        '--no-sandbox',
        '--disable-setuid-sandbox'
      ], 
      headless: 'new', // 新版Headless更接近正常浏览器
    });

    browser.on('disconnected', () => log('Browser disconnected unexpectedly'));
    const page = await browser.newPage();

    page.on('error', (err) => log(`Page error: ${err.stack}`));
    page.on('console', (msg) => log(`Page console [${msg.type()}]: ${msg.text()}`));
    page.on('requestfailed', (req) => log(`Request failed: ${req.url()} - ${req.failure().errorText}`));

    await page.setViewport({ width: 1920, height: 926 });
    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');

    log('Navigating to target URL...');
    await page.goto(searchURL, { waitUntil: 'load', timeout: 0 });
    log('Page load event completed');

    log('Waiting for AJAX content to load...');
    // 替换为你页面中AJAX加载完成后的标志性元素选择器
    await page.waitForSelector('#ajax-loaded-content', { timeout: 0 });
    log('AJAX content loaded successfully');

    log('Process completed, sending response');
    // res.send("hello"); // 保留你的业务逻辑

    await browser.close();
    log('Browser closed');
  } catch (err) {
    log(`PDF Error: ${err.stack}`);
    console.error(err);
  } finally {
    logStream.end();
  }
}

run();

建议先从日志优化和替换等待策略开始排查,这两个步骤最容易定位问题根源。如果还是不行,再检查版本兼容性和服务器资源。

内容的提问来源于stack exchange,提问作者Aayush Bansal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 02:52:27