
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/crawleeCrawlee 的 CheerioCrawler 是基于 Cheerio 的輕量級抓取方案本地開發非常方便npx crawlee create即可初始化項目但直接把它丟進 AWS Lambda 運行會遇到存儲狀態殘留、文件系統只讀、執行環境復用三大問題。本文以 Crawlee 3.12 版本文檔為骨架結合當前倉庫源碼完整講解如何改造代碼、用內存存儲替換文件存儲、將爬蟲包裝為 Lambda handler并通過 zip 壓縮包或 Lambda Layers 完成部署最終從 Lambda 中直接返回抓取數據。讀完本文你將掌握一套可復制的「無狀態 CheerioCrawler AWS Lambda」部署方案并理解其背后的存儲后端切換原理。為什么本地能跑、Lambda 上卻要改代碼在本地npx crawlee create會生成一個開箱即用的 Crawlee 項目該命令由倉庫中的 CreateProjectCommand.ts 實現。但 AWS Lambda 的運行環境與本地有本質差異主要體現在兩點文件系統只讀Lambda 提供的是只讀根文件系統唯一的可寫位置是/tmp而且/tmp也不保證持久。Crawlee 默認把 Dataset、RequestQueue、KeyValueStore 寫到磁盤默認目錄./storage直接運行必然失敗。環境復用導致有狀態AWS 為了降低冷啟動時間會在一次執行結束后把運行環境保留一段時間后續調用會復用同一進程。如果 Crawlee 的所有實例共享同一份存儲第二次調用就會讀到第一次運行殘留的狀態產生極難排查的臟數據問題。因此部署前需要完成兩類改造讓每個 Lambda 調用使用獨立的存儲配置以及關閉磁盤持久化、改用內存存儲。改造一為爬蟲注入獨立的 Configuration 實例Crawlee 默認所有爬蟲實例共享同一份全局存儲這在單進程場景下很方便但在 Lambda 中就是狀態泄漏的根源。解決辦法是每實例化一個爬蟲就給它傳一個全新的Configuration實例并且顯式設置persistStorage: false。按 3.12 版本文檔的寫法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: false是關鍵它告訴 Crawlee 改用內存存儲而不是文件系統存儲。從當前倉庫源碼可以印證這一點——service_locator.ts 中getStorageBackend()會依據configuration.persistStorage的值在兩種存儲后端之間切換persistStorage為true默認時創建FileSystemStorageBackend數據落盤到configuration.storageDir默認./storagepersistStorage為false時創建MemoryStorageBackend數據全部保存在內存中天然適配 Lambda 只讀文件系統。也就是說這一行配置直接決定了底層存儲后端的選擇而非僅僅少寫點文件。關于persistStorage的默認值與優先級在 configuration.ts 中可以看到該字段的定義/** default true */ persistStorage: field(coerceBoolean.default(true), CRAWLEE_PERSIST_STORAGE),即persistStorage默認值為true對應環境變量CRAWLEE_PERSIST_STORAGE。因此如果你不想改代碼也可以通過給 Lambda 設置環境變量CRAWLEE_PERSIST_STORAGEfalse達到同樣效果。但文檔推薦的顯式傳Configuration方式還有一個額外好處——它同時解決了存儲共享問題。Configuration類本身是一個不可變值對象configuration.ts值在構造時一次性解析完畢之后任何賦值都會拋出TypeError。它的解析優先級從高到低為constructor options environment variables crawlee.json schema defaults該優先級鏈在resolveAll()configuration.ts中實現構造參數優先其次環境變量再其次項目根目錄的crawlee.json文件讀取邏輯見loadFileOptions()最后才是 schema 默認值。更全面的配置說明可參考 docs/guides/configuration.mdx。補充在當前主倉庫v4的源碼結構中CheerioCrawler的構造函數為constructor(options?: CheerioCrawlerOptions)見 cheerio-crawler.ts更推薦把配置放進 options 的configuration字段例如new CheerioCrawler({ requestHandler: router, configuration })。本文主體按 3.12 版本化文檔的第二參數寫法演示兩種方式語義一致。改造二把爬蟲邏輯包裝成 Lambda handlerConfiguration注入完成后下一步是把所有邏輯包進一個handler函數——這就是 AWS 之后真正執行的Lambda 本體// 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); };注意一個容易被忽略的細節new CheerioCrawler(...)和new Configuration(...)必須放在handler函數內部每次調用都新建實例而不是放在模塊頂層只創建一次。為什么必須每次新建爬蟲實例AWS 會在首次執行后讓環境繼續存活一段時間以減少冷啟動因此后續調用會命中同一個已運行過的爬蟲實例。若復用實例上次運行留在內存/存儲中的數據會被本次調用讀取到結果被污染爬蟲的內部狀態如 RequestQueue 游標、統計信息可能與新的輸入不一致。文檔的結論非常直接TLDR: Keep your Lambda stateless.讓 Lambda 保持無狀態。這是無服務器架構下使用 Crawlee 最重要的一條原則。改造三爬蟲結束后返回抓取數據最后一步是讓 Lambda 真正輸出結果。Crawlee 的CheerioCrawler繼承自BasicCrawler其getData()方法會打開默認 Dataset 并讀取全部條目見 basic-crawler.ts 的實現內部調用Dataset.open()后執行dataset.getData(...args)。由于我們關閉了持久化存儲數據直接從內存 Dataset 中取出。在crawler.run(startUrls)結束后調用它把結果作為 Lambda 響應體返回// 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(), } };至此完整的src/main.js就緒每次調用新建無狀態爬蟲 → 內存存儲 → 抓取 → 返回數據。其中requestHandler: router來自 Crawlee 模板生成的 routes.jssrc/routes.js用于按請求標簽分發處理邏輯。部署打包上傳與 Lambda 配置代碼改造完成后進入部署環節。方式一直接上傳 zip 壓縮包在項目目錄下執行zip -r package.zip .將整個項目包含node_modules文件夾打包然后在 AWS Lambda 控制臺把package.zip作為代碼源上傳即可。方式二用 Lambda Layers 承載依賴推薦AWS 對直接上傳有50MB 限制。Crawlee 項目本身通常遠小于此限制但依賴樹一旦龐大起來很容易超標。更穩妥的做法是用Lambda Layers單獨托管node_modules把node_modules單獨打包成 zip壓縮包內應只有一個名為node_modules的文件夾將該壓縮包上傳到 AWS S3再基于該對象創建 Lambda Layer在 Lambda 函數配置中掛載這個 Layer。這樣做的兩個好處多個 Lambda 可以共享同一份依賴同時代碼部分保持精簡上傳更快、更新更靈活。配置 handler 與測試上傳代碼后在 Lambda 的Runtime Settings中設置 handler。handler 的命名規則是用/表示目錄層級用.表示具名導出。我們的 handler 名為handler從src/main.js導出因此填src/main.handler點擊Test按鈕發送一個測試事件即可觸發運行。測試事件的具體內容暫時無關緊要——如果你后續想參數化爬蟲可以解析 AWS 作為第一個參數傳入 handler 的event對象例如把起始 URL 放進事件體。內存與臨時存儲配置建議在 AWS Lambda 控制臺的Configuration標簽頁中可以調整函數內存大小與臨時存儲ephemeral storage大小內存大小會顯著影響 Lambda 的執行速度CheerioCrawler 屬于 CPU/IO 密集型更大的內存通常帶來更強的 CPU 配額從而明顯縮短抓取耗時若單次運行的數據量較大可適當調大 ephemeral storage以容納內存之外的臨時文件官方文檔對內存與性能/成本的換算關系有詳細說明可按需查閱。對于瀏覽器類爬蟲Playwright/Puppeteer還需要額外處理瀏覽器二進制文件如通過sparticuz/chromium以 Lambda Layer 方式托管 Chromium、注入executablePath與args并建議將內存設置到1024MB 或以上、同步調大超時時間——這套方案在本文檔的姊妹篇 docs/deployment/aws-browsers.md 中有完整講解可作為下一步的參考。總結Lambda 上跑 CheerioCrawler 的四個要點注入獨立Configuration每次實例化爬蟲都傳入新的Configuration避免多個調用共享存儲導致狀態泄漏persistStorage: false切換到底層MemoryStorageBackendservice_locator.ts適配 Lambda 只讀文件系統也可通過環境變量CRAWLEE_PERSIST_STORAGEfalse等價實現handler 內每次新建爬蟲保持 Lambda 無狀態防止環境復用時訪問到上次運行的實例getData()返回結果爬蟲結束后從內存 Dataset 取數作為 Lambda 響應返回basic-crawler.ts。掌握這四點你就能把本地用npx crawlee create生成的 Cheerio 項目平滑遷移到 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創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考