
Crawlee 实战将 CheerioCrawler 项目部署到 AWS Lambda 的完整指南【免费下载链接】crawleeCrawlee—A web scraping and browser automation library for Node.js to build reliable crawlers. In JavaScript and TypeScript. Extract data for AI, LLMs, RAG, or GPTs. Download HTML, PDF, JPG, PNG, and other files from websites. Works with Puppeteer, Playwright, Cheerio, JSDOM, and raw HTTP. Both headful and headless mode. With proxy rotation.项目地址: https://gitcode.com/GitHub_Trending/cr/crawlee在本地用npx crawlee create创建 Crawlee 项目并跑通爬虫很容易但当你想把 CheerioCrawler 项目部署到 AWS Lambda 这个无服务器环境时会遇到两个核心障碍Lambda 的文件系统是只读的无法落盘持久化存储以及Lambda 实例会被复用容器在首次执行后会存活一段时间以降低冷启动延迟。本文基于 Crawlee 3.16 的官方部署文档结合仓库源码完整讲解如何改造代码、打包并成功部署到 AWS Lambda最终通过handler函数返回爬取结果。为什么在 Lambda 上运行 Crawlee 需要改代码Crawlee 默认行为是所有 crawler 实例共享同一套存储Request Queue、Dataset、Key-Value Store 默认落在本地./storage目录下对应配置项storageDir的默认值见 configuration.ts。这在本地单进程场景下很方便但在 AWS Lambda 中却会带来隐患文件系统只读Lambda 的执行环境只有/tmp目录可写项目根目录是只读的默认的基于文件系统的存储后端会直接失败。实例复用导致有状态AWS 会在一次执行结束后让环境保持存活一段时间后续请求会复用同一个容器。如果 crawler 和存储被共享上一次运行遗留的数据和状态会泄漏到下一次调用产生极难排查的 bug。因此核心改造思路就两条每次调用都创建独立的Configuration实例并把persistStorage设为false让 Crawlee 改用纯内存存储。第一步创建 Crawlee 项目在本地终端执行npx crawlee create按提示选择 Cheerio 模板完成项目初始化。此时项目的入口文件是src/main.jsCrawlee 模板默认结构后续所有改造都在该文件内进行。第二步给爬虫传入独立的 Configuration 实例在实例化CheerioCrawler时把Configuration作为第二个构造参数传入// For more information, see https://crawlee.dev/ import { CheerioCrawler, Configuration, ProxyConfiguration } from crawlee; import { router } from ./routes.js; const startUrls [https://crawlee.dev]; const crawler new CheerioCrawler({ requestHandler: router, }, new Configuration({ persistStorage: false, })); await crawler.run(startUrls);关于这两个关键点可以从源码层面进一步理解persistStorage是什么它被定义在 configuration.ts默认值为true对应的环境变量是CRAWLEE_PERSIST_STORAGE。设为false即告诉 Crawlee 不要持久化存储。false时底层发生什么存储后端由服务定位器按配置惰性创建。在 service_locator.ts 中可以看到getStorageBackend()会根据persistStorage决定使用FileSystemStorageBackend持久化到磁盘还是MemoryStorageBackend纯内存。Lambda 只读文件系统的场景下persistStorage: false会让 Crawlee 自动选择内存后端无需你再做任何存储适配。为什么必须传独立实例Configuration默认存在一个全局单例Configuration.getGlobalConfiguration()。不传第二个参数时crawler 会使用全局配置也就意味着所有 crawler 共享同一存储后端传入独立实例后每个 Lambda 调用里的 crawler 都有自己隔离的存储空间互不干扰。第三步把逻辑包装进 handler 函数AWS Lambda 需要导出一个约定的入口函数也就是 Lambda 将要执行的 handler。改造方式是把爬虫逻辑整体移入一个异步函数并导出// For more information, see https://crawlee.dev/ import { CheerioCrawler, Configuration } from crawlee; import { router } from ./routes.js; const startUrls [https://crawlee.dev]; export const handler async (event, context) { const crawler new CheerioCrawler({ requestHandler: router, }, new Configuration({ persistStorage: false, })); await crawler.run(startUrls); };重要提示保持 Lambda 无状态stateless务必在每次 Lambda 调用时都新建 crawler 实例。因为 AWS 会在首次执行后让环境存活一段时间以减少冷启动后续调用会访问到已使用过的 crawler 实例跨调用复用状态会引发难以调试的问题。核心原则一句话每次调用都是全新的 crawler。第四步让 Lambda 返回爬取结果爬虫运行结束后通过crawler.getData()获取本次爬取的数据并封装成 Lambda 的标准响应结构返回。getData()对应 dataset.ts 中 Dataset 的读取 API返回 Dataset 中的数据项。最终src/main.js的完整形态// For more information, see https://crawlee.dev/ import { CheerioCrawler, Configuration } from crawlee; import { router } from ./routes.js; const startUrls [https://crawlee.dev]; export const handler async (event, context) { const crawler new CheerioCrawler({ requestHandler: router, }, new Configuration({ persistStorage: false, })); await crawler.run(startUrls); return { statusCode: 200, body: await crawler.getData(), } };这里event是 AWS 传入的第一个参数包含触发事件的全部信息。你可以通过解析event对象例如其中的查询参数或请求体来进一步参数化爬虫运行。第五步打包并部署到 AWS Lambda在项目目录下执行zip -r package.zip .该命令会把整个项目包含node_modules目录压缩为一个 zip 包然后在 AWS Lambda 控制台将package.zip上传为代码源。node_modules 太大怎么办使用 Lambda LayersAWS 对直接上传有50MB 大小限制。Crawlee 项目通常远小于此但依赖树庞大时很容易超限。更优雅的方案是使用Lambda Layers将node_modules目录单独打包成一个 zip压缩包内需包含名为node_modules的顶层文件夹由于该 zip 体积可能接近 50MB 限制建议先上传到 AWS S3再基于该对象创建 Lambda Layer在 Lambda 函数配置中挂载这个 Layer这样多个 Lambda 可以共享依赖函数本体代码部分保持尽可能精简。值得对照的是仓库中另一份部署文档 aws-browsers.md 展示了浏览器版PlaywrightCrawler的同类做法浏览器二进制同样通过sparticuz/chromium打包进 Layer并在代码中用aws_chromium.executablePath()指定可执行文件路径同时传入aws_chromium.args适配 Lambda 缺少 GPU 加速的硬件环境。这印证了 Layer 是 Lambda 部署大型依赖的标准姿势。配置 Runtime Settings上传代码后在 Lambda 的Runtime Settings中设置handler指向入口函数用/描述目录层级用.表示命名导出我们的函数名为handler从src/main.js导出因此 handler 名填写src/main.handler内存、超时与临时存储配置在 AWS Lambda 控制台的Configuration标签页中可以配置 Lambda 的内存大小和临时存储ephemeral storage大小内存大小会显著影响 Lambda 的执行速度内存越大分配的 CPU 计算能力越强。CheerioCrawler 属于轻量级 HTTP 爬虫但若并发或请求量大建议预留充足内存。临时存储如果爬虫有写/tmp的需求例如下载文件、浏览器二进制解压需要相应调大。部署完成后点击Test按钮发送一个测试事件即可验证。测试事件的具体内容目前不影响运行后续可以根据需要解析event对象来参数化爬取目标。常见问题与排错要点问题原因与解决存储写入报错 / 无法创建 storage 目录未设置persistStorage: falseCrawlee 尝试写只读文件系统确认每个 crawler 都传入独立的Configuration多次调用结果串数据在 Lambda 容器复用时复用了全局单例配置务必在 handler 内每次新建 crawler 实例上传 zip 超过 50MB改用 Lambda Layers 承载node_modules代码包只保留业务源码Lambda 直接超时在 Configuration 中调大超时与内存先本地测量爬虫执行耗时再据此设置handler 找不到检查 Runtime Settings 的 handler 是否与导出路径一致src/main.handler以及package.json的main字段指向src/main.js小结将 Crawlee 的 CheerioCrawler 项目部署到 AWS Lambda本质上是围绕两个环境约束做适配只读文件系统→ 通过persistStorage: false切换到内存存储后端容器复用→ 每次调用创建独立Configuration与 crawler 实例保持 Lambda 无状态。改造完成后zip打包必要时配合 Lambda Layers上传代码、设置src/main.handler入口即可运行。同样的思路也适用于 GCP Cloud Functions 部署指南——那边同样要求persistStorage: false并导出 handler 函数区别仅在于 GCP 按package.json的main字段定位入口、打包时排除node_modules由平台自行安装依赖。【免费下载链接】crawleeCrawlee—A web scraping and browser automation library for Node.js to build reliable crawlers. In JavaScript and TypeScript. Extract data for AI, LLMs, RAG, or GPTs. Download HTML, PDF, JPG, PNG, and other files from websites. Works with Puppeteer, Playwright, Cheerio, JSDOM, and raw HTTP. Both headful and headless mode. With proxy rotation.项目地址: https://gitcode.com/GitHub_Trending/cr/crawlee创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考