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

Firebase Cloud Functions上Puppeteer:goto()与waitForSelector()始终失败

解决Firebase Cloud Functions中Puppeteer页面加载卡住的问题

我之前在无服务器环境下用Puppeteer做爬虫时也碰到过几乎一模一样的问题——本地跑完全正常,一部署到Cloud Functions就卡住超时,连日志都打不出来。结合你的代码和场景,给你几个优先级从高到低的解决方案:

1. 先修正低级拼写错误

你在puppeteerOptions里写的是headerless: true,这是个拼写错误!正确的参数名是headless。这个错误会导致浏览器无法以无头模式启动,本地环境可能因为系统自带Chrome能自动 fallback,但云端的容器环境里直接就会卡住,连浏览器都启动不起来,自然不会走到后续的console.log。

修正后的配置:

puppeteerOptions: {
  headless: true, // 修正拼写错误
  args: [
    '--disable-gpu',
    '--no-sandbox',
  ]
}

2. 优化Puppeteer启动参数适配云端环境

Cloud Functions的容器环境资源有限,默认的Puppeteer参数很容易导致浏览器崩溃或卡住。建议添加几个关键参数,同时开启日志输出方便排查:

puppeteerOptions: {
  headless: "new", // 推荐用新版无头模式,兼容性更好
  args: [
    '--disable-gpu',
    '--no-sandbox',
    '--disable-dev-shm-usage', // 解决云端/dev/shm内存不足的问题,这是高频坑点
    '--single-process', // 减少进程数量,节省资源
    '--no-zygote', // 配合single-process,避免额外的进程开销
  ],
  dumpio: true, // 输出浏览器的日志到Cloud Functions日志,能帮你看到启动或加载时的报错
}

3. 控制并发数量,避免资源耗尽

你的代码里用Promise.all一次性启动了所有页面的浏览器实例,Cloud Functions的CPU和内存根本扛不住这么多并发的浏览器进程,直接会导致资源耗尽卡住。建议用p-limit这类库限制并发数,比如每次最多跑2个实例:

首先安装依赖:

npm install p-limit

然后修改start函数:

const pLimit = require('p-limit');
const limit = pLimit(2); // 根据函数内存配置调整,1GB内存建议设2-3

ScraperManager.prototype.start = async function() {
  var webpagePromises = []
  for (const agency of agencies) {
    for (page_num = 0; page_num < num_of_pages; page_num++) {
      const url = setupUrl(agency, page_num);
      // 用limit包装getWebpage,控制并发执行
      const webpagePromise = limit(() => getWebpage(agency, page_num, url))
      webpagePromises.push(webpagePromise)
    }
  }
  return Promise.all(webpagePromises)
}

4. 升级Cloud Functions的资源配置

Puppeteer跑浏览器非常吃内存,默认的Cloud Functions内存(256MB)肯定不够用。建议把内存调到1GB甚至2GB,同时把超时时间拉到最大允许的540秒:

你可以在firebase.json里配置:

{
  "functions": {
    "runtimeOptions": {
      "memory": "1GB",
      "timeoutSeconds": 540
    }
  }
}

或者部署时用命令行指定:

firebase deploy --only functions:scraper --memory 1GB --timeout 540

5. 改用专为无服务器优化的Chrome包

官方Puppeteer自带的Chrome体积大,在云端环境兼容性一般。推荐用@sparticuz/chromium,这是专门为无服务器环境优化的轻量Chrome,启动更快更稳定:

首先安装依赖:

npm install @sparticuz/chromium puppeteer-core

然后修改getWebpage函数:

const chromium = require('@sparticuz/chromium');
const puppeteer = require('puppeteer-core');

async function getWebpage(agency, page_num, url) {
  var data = {}
  let browser;
  try {
    const executablePath = await chromium.executablePath();
    browser = await puppeteer.launch({
      executablePath: executablePath,
      headless: chromium.headless,
      args: [...chromium.args, '--disable-dev-shm-usage'],
      dumpio: true,
    });
    const page = await browser.newPage();
    await page.setUserAgent(constants.userAgent);
    // 加上waitUntil确保页面加载完成,避免过早等待选择器
    await page.goto(url, {timeout: 0, waitUntil: 'networkidle2'});
    console.log(`goto completes for ${url}`);
    await page.waitForSelector('div.main_container', {timeout: 0});
    console.log(`waitFor completes for ${url}`);
    const body = await page.$eval('body', el => el.innerHTML);
    data['html'] = body;
    return data;
  } catch (err) {
    console.error(`Puppeteer error for ${url}:`, err);
    return;
  } finally {
    if (browser) await browser.close();
  }
}

按这个顺序排查,应该能解决你的问题。先从拼写错误和参数优化开始,这两个是最常见的原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:05:34