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

如何将本地网站爬取打包函数迁移到Firebase Cloud Functions并上传zip到存储桶

依赖安装

首先在functions目录下执行命令安装所有需要的依赖:

npm install firebase-functions firebase-admin mkdirp archiver website-scraper website-scraper-puppeteer

完整实现代码

const functions = require('firebase-functions')
const { initializeApp } = require('firebase-admin/app')
const { getStorage } = require('firebase-admin/storage')
const mkdirp = require('mkdirp')
const path = require('path')
const os = require('os')
const fs = require('fs')
const archiver = require('archiver')
const scrape = require('website-scraper')
const PuppeteerPlugin = require('website-scraper-puppeteer')

initializeApp()
// 初始化默认存储桶
const bucket = getStorage().bucket()
// 配置云函数运行参数,爬取+打包需要更高配置支持
exports.scrapeAndUploadZip = functions.runWith({
  timeoutSeconds: 300,
  memory: '1GB'
}).https.onRequest(async (request, response) => {
  // 定义临时路径:爬取内容存放目录、最终zip文件路径
  const tempScrapeDir = path.join(os.tmpdir(), 'appseven')
  const tempZipPath = path.join(os.tmpdir(), 'appseven.zip')
  const storageDestPath = 'scraped-zips/appseven.zip' // 存储桶内的保存路径

  try {
    // 1. 创建爬取内容存放的临时目录
    await mkdirp(tempScrapeDir)

    // 2. 执行网站爬取
    await scrape({
      urls: ['https://appsevenpage.com/'],
      directory: tempScrapeDir,
      plugins: [
        new PuppeteerPlugin({
          launchOptions: {
            headless: true,
            args: ['--no-sandbox', '--disable-setuid-sandbox'] // Cloud Functions环境必须加这两个参数,否则Puppeteer启动失败
          },
          scrollToBottom: {
            timeout: 10000,
            viewportN: 10
          }
        })
      ]
    })

    // 3. 打包临时目录为zip文件
    await new Promise((resolve, reject) => {
      const output = fs.createWriteStream(tempZipPath)
      const archive = archiver('zip', { zlib: { level: 9 } })

      output.on('close', resolve)
      archive.on('error', reject)

      archive.pipe(output)
      // 将整个爬取目录的内容添加到zip根目录
      archive.directory(tempScrapeDir, false)
      archive.finalize()
    })

    // 4. 上传zip到Firebase存储桶
    await bucket.upload(tempZipPath, {
      destination: storageDestPath,
      // 可选配置:如果需要zip可公开访问,取消下面的注释
      // public: true,
      metadata: {
        contentType: 'application/zip'
      }
    })

    // 5. 清理临时文件释放空间
    fs.rmSync(tempScrapeDir, { recursive: true, force: true })
    fs.unlinkSync(tempZipPath)

    // 6. 返回成功响应
    response.status(200).send({
      status: 'success',
      zipPath: storageDestPath
      // 如果设了公开访问,可以补充返回下载地址:downloadUrl: `https://storage.googleapis.com/${bucket.name}/${storageDestPath}`
    })
  } catch (err) {
    console.error('执行失败:', err)
    // 出错也要清理临时文件,避免占用磁盘
    if (fs.existsSync(tempScrapeDir)) fs.rmSync(tempScrapeDir, { recursive: true, force: true })
    if (fs.existsSync(tempZipPath)) fs.unlinkSync(tempZipPath)
    response.status(500).send({ status: 'error', message: err.message })
  }
})

关键改动说明

  1. 原代码提前调用response.send会导致后续异步逻辑未执行完就终止云函数,修正后所有逻辑执行完成再返回响应
  2. Puppeteer在Cloud Functions无沙箱环境运行必须添加--no-sandbox和--disable-setuid-sandbox启动参数
  3. 所有异步操作(创建目录、爬取、打包、上传)都用async/await等待执行完成,避免逻辑提前终止
  4. 用archiver替代旧的zip-folder,支持Promise异步控制,打包稳定性更高
  5. 执行完成/出错都统一清理临时目录和zip文件,避免占用云函数临时磁盘空间

部署注意事项

  • 确认你的Firebase项目已经开启了Cloud Storage服务
  • 如果需要爬取其他网站,调整urls参数即可,对应修改存储路径避免文件覆盖
  • 如果爬取的网站资源多、体积大,可以适当调高云函数的内存和超时时间

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 11:06:08