如何将本地网站爬取打包函数迁移到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 }) } })
关键改动说明
- 原代码提前调用
response.send会导致后续异步逻辑未执行完就终止云函数,修正后所有逻辑执行完成再返回响应 - Puppeteer在Cloud Functions无沙箱环境运行必须添加
--no-sandbox和--disable-setuid-sandbox启动参数 - 所有异步操作(创建目录、爬取、打包、上传)都用
async/await等待执行完成,避免逻辑提前终止 - 用
archiver替代旧的zip-folder,支持Promise异步控制,打包稳定性更高 - 执行完成/出错都统一清理临时目录和zip文件,避免占用云函数临时磁盘空间
部署注意事项
- 确认你的Firebase项目已经开启了Cloud Storage服务
- 如果需要爬取其他网站,调整
urls参数即可,对应修改存储路径避免文件覆盖 - 如果爬取的网站资源多、体积大,可以适当调高云函数的内存和超时时间
内容的提问来源于stack exchange,提问作者eeerrrttt
相关产品推荐
相关产品推荐

