Crawlee 實測:一套 Node 框架,兩種爬取引擎

最後更新於 July 17, 2026
Crawlee 實測:一套 Node 框架,兩種爬取引擎
AI 摘要
This Crawlee review evaluates the framework as a crawler layer that can run either lightweight Cheerio extraction or real browser automation. The article compares its two engines on identical fixtures, showing where Cheerio is enough, where Playwright is required, and how Crawlee's queue and routing model changes the shape of a scraping project. It highlights Crawlee's value for teams that need crawl orchestration rather than only page rendering. The review also covers setup weight, engine switching, public practice-site behavior, and the operational tradeoff of adopting a full Node scraping framework.

多數人第一次接觸 Crawlee,往往不是因為想特地找它,而是因為在想另一個問題:「我到底該用哪個無頭瀏覽器?」但其實這個問題問歪了,而 Crawlee 正是為了把方向拉回來才存在。它不是瀏覽器,而是建構在 Node/TypeScript 上的框架;需要的時候,它會幫你把瀏覽器包起來,不需要的時候,就直接省掉。

我花了幾天時間,在 Node v22.22.3 與 macOS 上,搭配一組可控的 fixture 和幾個公開示範網站測試 Crawlee 3.17.0。它最核心的賣點——同一個函式庫、同一套 API,底層卻能在 HTTP 爬取與真實瀏覽器之間切換——正是我最想驗證的部分,因為這會直接決定 Crawlee 值不值得放進你的技術棧,還是你乾脆直接用 Playwright 就好。先講結論:這套「雙引擎」的說法確實站得住腳,但也有幾個我等一下會提到的前提條件。

Crawlee 到底是什麼,又不是什麼

Crawlee 自我定位為一個用於 Node.js 的網頁爬取與瀏覽器自動化函式庫,目標是打造穩定、可靠的爬蟲。它的官方說明涵蓋範圍很廣:可以為 AI、LLM、RAG 或 GPT 擷取資料;可下載 HTML、PDF、JPG、PNG 等各種檔案;支援 Puppeteer、Playwright、Cheerio、JSDOM 與原生 HTTP;可在有頭或無頭模式下執行;還內建 proxy 輪替。功能面非常廣,所以更需要先講清楚 Crawlee 不是什麼。

它不是渲染引擎,也沒有自己的瀏覽器。當你需要執行 JavaScript 時,Crawlee 會去驅動 Playwright 或 Puppeteer,再由它們去驅動 Chromium(或其他瀏覽器)。它也不是你透過網路直接呼叫的託管服務——它是一個要自己安裝、自己執行的依賴套件。更精確地說,Crawlee 是包在抓取器上層的那一層:負責爬蟲類別、請求佇列、儲存、連結追蹤邏輯。你可以把它理解成「爬取框架」,底下留了一個可替換的引擎插槽。

補充一下,我測試的版本是 3.17.0(發佈於 2026-06-04),使用 TypeScript,授權為 Apache-2.0。根據 2026-07-09 的 apify/crawlee 顯示,repo 大約有 24.6k 顆 star。Star 數本來就會浮動——我觀察的兩天內就多了 53 顆——所以這只能當作截圖當下的數字,不是固定值。

兩種引擎:CheerioCrawler 與 PlaywrightCrawler

真正體現這套設計價值的地方就在這裡,也是我花最多時間測試的部分。

CheerioCrawler 走的是 HTTP 路徑。它直接透過網路抓原始 HTML,並用 Cheerio 解析——沒有瀏覽器、沒有 JavaScript 執行、沒有渲染。速度快、成本低。PlaywrightCrawler 則是瀏覽器路徑。它會啟動真正的 Chromium,把頁面完整渲染出來,包括任何由 JavaScript 建立的 DOM,甚至還能截圖。

這是兩個能力明顯不同的引擎,而 Crawlee 想傳達的是:它們的用法幾乎一樣。兩者都接受 requestHandler,都提供 run(),也都能透過 enqueueLinks 追蹤連結。從一個引擎切到另一個引擎,不是重寫程式,只是換一個 class——我實際驗證過,做法就是讓抽取邏輯完全不變,只改包住它的 crawler 類別。

Crawlee two engines one API

這裡有一個一定要講清楚的交界點,因為那正是兩者開始不完全對等的地方:內容存取的方式不同。在 CheerioCrawler 的 handler 裡,你拿到的是 $——一個已經解析好的靜態 DOM,你可以像 jQuery 那樣查詢它。在瀏覽器 handler 裡,你拿到的是活的 page 物件。所以佇列、路由、「把這些資料推上去、追蹤那些連結」這些流程都一樣,但真正讀取頁面的那一行程式,寫法會不同。Crawlee 自己的文件也明確提到這點——它把共用介面限制在爬取操作上,而把內容存取列為會變動的部分。

引擎取得方式會執行 JavaScript 嗎?我的實測(1 個動態頁)最適合
CheerioCrawler原生 HTTP + Cheerio 解析不會約 0.035 秒靜態 HTML、JSON API、追求速度
PlaywrightCrawler透過 Playwright 啟動真實 Chromium約 4.967 秒JavaScript 渲染頁面、截圖

這些時間來自同一台機器、單次執行——不是基準測試,只是拿來看取捨的輪廓。瀏覽器路徑在同一個 URL 上,大約慢了兩個數量級。這就是渲染的成本,也就是為什麼你不會預設就選它。

測試重點:同一個 URL,從 0 到 8/8

說法很容易講,真正讓我相信這套雙引擎設計的原因,是我可以先讓它失敗,再只靠換一個 class 把它救回來。

我先做了一個本機動態 fixture——一個商品目錄頁,頁面中的商品卡片是 JavaScript 在載入後才注入的,這也是現代網站最常見的樣子。我把 CheerioCrawler 指向這個頁面,它回傳 0 張商品卡。這不是 bug,而是正常現象:Cheerio 根本沒有執行 JavaScript,所以它解析到的 HTML 裡壓根沒有那些卡片。接著我把同一個 URL 改交給 PlaywrightCrawler,其他什麼都不動,它就渲染出 8/8 項商品,還順手截圖當證據。

Crawlee Cheerio 0 vs Playwright 8/8

為了確認這不是我自己 fixture 的特殊情況,我又拿同樣的方法去測公開網站——Quotes to Scrape 的 JavaScript 示範頁,它同樣是在前端動態生成 quotes。結果完全一致:CheerioCrawler 看到 0 則 quote,PlaywrightCrawler 則抓回 10 則。

Crawlee public Quotes JS ten

我想謹慎地說,這並不是在「證明」什麼全新發現;這只是對 Crawlee 自己文件中既有說法的再次驗證——它從 3.0 版開始就讓不同 crawler 類別共用相同的基底 class 與介面。但這正是價值所在:那句「同一套介面,可選 HTTP 或瀏覽器」不是行銷話術,而是我在一個可控 fixture 與一個不受我控制的網站上,真的從 0 到完整資料重現出來的結果。

HTTP 路徑什麼時候更強

看到上面那段,很多人會直覺解讀成「那就永遠用瀏覽器吧」。別這樣做。雙引擎設計之所以重要,正是因為瀏覽器是昂貴的備援方案,而不是預設選項。

在靜態內容上,CheerioCrawler 的表現又快又準。我的靜態商品 fixture 以 12/12 的完整召回率抓到全部商品,並透過 enqueueLinks({ selector: '.next-page' }) 追蹤分頁,總耗時約 0.155 秒。另一個文章頁則能正確取出標題與 3/3 段正文,並把登入/訂閱/版權聲明等模板內容和主文分得很乾淨。

最值得記住的一點是:很多 JavaScript 動態載入的頁面,背後其實都接著一個 JSON API。我的動態 fixture 資料就是來自一個 endpoint,當我直接把 CheerioCrawler 對準那個 API 時,它在約 0.035 秒內就拿回 8/8 筆商品——完全不需要瀏覽器。相同資料,瀏覽器路徑卻要花近五秒才渲染完成。這道理雖然老,但一直都對:如果你能直接還原底層請求,就不要啟動 Chromium。Crawlee 讓你可以針對不同 crawler 做這個選擇,而不用換框架。

為什麼說 Crawlee 真的是「爬取框架」(而不只是瀏覽器包裝)

如果你只是要把單一頁面渲染出來,其實根本不需要 Crawlee——直接用 Playwright 或 Puppeteer 就可以。單純的瀏覽器函式庫不會幫你處理爬取流程:沒有佇列、沒有去重、沒有深度控制,也沒有重試。這才是 Crawlee 真正有價值的地方,而且這部分跟引擎無關。

我用 fixture 的根頁做了一次同網域爬取,並搭配 enqueueLinks 與深度追蹤。Crawlee 一共走了 11 個頁面,深度分布為 {0:1, 1:3, 2:7}——也就是 1 個根頁、1 層外 3 頁、2 層外 7 頁——而且能正確以 maxRequestsPerCrawl 當作停止條件。RequestQueue 負責所有排程與紀錄。當我把請求送到一個回應 HTTP 500 的頁面時,Crawlee 會先重試,最後再透過 failedRequestHandler 把失敗明確拋出,而不是默默吃掉或讓整個執行直接炸掉。

Crawlee one-line engine switch

這也是為什麼 Crawlee 比單獨的瀏覽器工具更有說服力:爬取編排是內建的,而且不管底下是 HTTP 還是瀏覽器,引擎更換後編排方式都一樣。你只要寫一次佇列與追蹤邏輯;至於每個 crawler 要不要渲染 JavaScript,再另外決定就好。

安裝體驗與隱藏的瀏覽器下載

安裝過程大致順利,但有一個第一次用的人很容易踩到的坑。

npm install crawlee playwright 本身可以正常完成,且沒有回報漏洞。但 PlaywrightCrawler 不會直接啟動,因為你還需要再跑一次 npx playwright install chromium,下載約 81.7 MiB 的 Chromium binary。只安裝 crawlee 套件,並不會自動把瀏覽器一起抓下來。如果你沒做這一步就直接用瀏覽器 crawler,會碰到一個啟動錯誤;如果你不熟 Playwright 的封裝方式,這個錯誤其實不太直觀。這不是 Crawlee 本身的缺陷,而是沿用 Playwright 的行為,但它確實是第一次上手時的一個摩擦點,值得先提醒。

Crawlee setup install weight

再補一個操作層面的細節:預設情況下,Crawlee 會把資料寫到本機的 storage/ 目錄。我在測試時把它導向暫存資料夾,並關掉持久化,讓環境保持乾淨;但如果你直接照一般方式跑,專案裡就會多出一個 storage/ 資料夾。這不算問題,只是先知道會比較不意外,免得它突然出現在 git status 裡。

簡單看一下第三種引擎

Crawlee 的對等性故事不只適用於 Cheerio 與 Playwright,還包括 PuppeteerCrawler。我也檢查了這個「同介面」的主張能延伸到哪裡——是從 class 與 API 表面層來看,不是實際跑一輪爬取。

這三個 crawler 類別都追溯自同一個 BasicCrawler 基底。CheerioCrawler 走的是 HttpCrawlerPlaywrightCrawlerPuppeteerCrawler 則都走同一個 BrowserCrawler。我透過已安裝的套件做 introspection,發現三種引擎之間有 24 個 public methods 是共用的,包括整個設計最核心的佇列與儲存操作:runaddRequestspushDatagetDatagetDatasetexportDatagetRequestQueueuseStatestop。而 PuppeteerCrawlerPlaywrightCrawler 的 public method set 甚至完全一致。跨引擎真正的差異,只會出現在 HTTP 與瀏覽器的交界處,而這也正是你本來就會預期差異存在的地方。

但有一個邊界要說清楚:我沒有實際執行 PuppeteerCrawler 的 live crawl。因為 puppeteer 這個 peer dependency 是選配,而我的測試環境沒有裝它;若要測,還得再下載一套瀏覽器。所以這裡對 Puppeteer 的相容性,是透過結構驗證——相同的基底 class、相同的共享 methods、相同的 handler context 形狀——而不是透過實跑結果來確認。即使介面相同,底層行為也不會完全一樣:Crawlee 自己的指南也提到,Playwright 會自動等待元素,而 Puppeteer 則通常需要你明確等待。這是引擎本身的差異,不是 Crawlee 的問題,但它代表「同一套 API」不等於「每個 handler 裡都能寫完全一樣的 code」。

這次我沒有測的部分

以下這些項目是我刻意保留、沒有納入本輪測試的,避免你把結果解讀得比實際更廣。

  • 規模。 這次全部都只在小型 fixture 與短篇公開爬取上測試。沒有 100~1,000 頁的大型長跑,因此我不能代表 Crawlee 在 autoscaling 或真實高負載下的穩定性。
  • 佇列持久化與恢復。 我沒有在爬取中途手動中斷,再觀察 RequestQueue 是否能在崩潰後順利接續。這是長時間任務的重要能力,但這次尚未驗證。
  • Dataset 與 KeyValueStore 匯出。 我在測試框架裡是自己手寫 JSON/CSV 匯出,沒有實際使用 Crawlee 內建的 Dataset / KeyValueStore 匯出體驗;而這其實可能正是選用這個框架的一大便利點。
  • Proxy 與 session pools。 Crawlee 內建 proxy 輪替與 fingerprinting 功能。我把這些功能嚴格視為合規與營運工具,而不是「反機器人繞過」的賣點,所以也沒有特別壓測它們。

另外,上述所有時間數據都是單機、單次執行的結果。它們只反映 HTTP 與瀏覽器成本的「輪廓」,不是正式 benchmark,我也不會把它們當作 benchmark 來引用。

優點與缺點

優點

  • HTTP 與瀏覽器爬取共用同一套 API;引擎切換真的只是換 class,且在本機 fixture 與公開網站上都驗證到從 0 到完整資料的差異。
  • 真正的爬取框架:有 RequestQueue、帶深度控制的 enqueueLinks、重試機制與 failedRequestHandler,不只是頁面渲染器。
  • 當 JavaScript 不是問題時,HTTP 擷取相當準確又快速(靜態 12/12、文章段落 3/3、透過 JSON API 8/8)。
  • 瀏覽器路徑能補回 HTTP 路徑物理上看不到的內容,還能截圖。
  • Apache-2.0、TypeScript、持續維護中。

缺點

  • 瀏覽器 crawler 需要額外執行 npx playwright install chromium(約 81.7 MiB),而 npm install crawlee 不會自動處理;這點很容易漏掉。
  • 瀏覽器渲染有真實的單頁成本(我測到約 5 秒,對比 sub-second 的 HTTP 路徑)。
  • 直接執行時會預設產生 storage/ 目錄。
  • 規模、佇列持久化/恢復、以及內建 Dataset 匯出體驗,在我的測試中都還沒有被充分驗證。
  • Proxy 與 fingerprinting 功能必須在網站條款與法律允許的範圍內使用;那是責任,不是可以隨便依賴的捷徑。

什麼時候該選 Crawlee,什麼時候該選託管 API

Crawlee 是一個很適合自己動手搭建的工具,而這對很多團隊來說正是正解。當你希望在自己的 Node 程式碼庫裡掌控爬蟲、在同一個專案中混用 HTTP 與瀏覽器爬取,並且自行管理佇列與儲存時,就很適合用它。如果你願意自己維運,未來也能承擔擴充一整批瀏覽器的責任,Crawlee 會給你一個乾淨、設計良好的骨架。

另一條路,就是完全不自己管這些基礎設施。如果你不想把時間花在照顧 Chromium instance、proxy 輪替和 anti-bot 處理上,那麼託管 API 就是替代方案——而這正是我們在 Thunderbit 的開發者工具組所對應的位置。對技術使用者來說,Thunderbit 不是 Chrome 擴充功能,而是 AI 爬取的 API、MCP server 與 CLI。你可以呼叫 POST /distill,把頁面轉成乾淨、適合 LLM 使用的 Markdown;或呼叫帶有 JSON Schema 的 POST /extract,取得結構化資料,並透過 renderModenonebasicfull 來決定何時值得啟用完整瀏覽器渲染。這個 MCP server 也能讓 AI agent(如 Claude、Cursor 以及其他 MCP client)在任務中途直接抓資料,而 CLI 則可以在終端機或 CI 中執行:

試用 Thunderbit 進行網頁資料擷取

npx -y @thunderbit/thunderbit-cli distill "<url>" -f markdown > out.md

對開發者來說,真正重要的差別是:Crawlee 提供的是原材料——渲染後的 HTML、解析後的節點——而整個流程由你自己維護;託管 API 則直接回傳符合 schema 的結構化 JSON,並把 JS 渲染、CAPTCHA、anti-bot 等處理放在伺服器端。這兩者適合的工作不同。你若想要最大控制權,又不怕維運,就選 Crawlee;如果你想直接拿資料,不想自己經營瀏覽器集群,那就選託管方案。很多團隊最後會兩者都用:一個處理客製化爬取,一個處理「直接給我結構化資料」的情境。你也可以從 Thunderbit 的定價 看看成本上的差異。

結論

該不該用 Crawlee?我的答案是:該——如果你是 Node 或 TypeScript 開發者,想要一套同時涵蓋 HTTP 與瀏覽器爬取、而且底下真的有爬取佇列的單一框架。它的雙引擎承諾,正是選它的理由,而且在我的測試中表現得很穩:同一個 URL 只靠換一個 class 就能從 0 變成完整資料,靜態擷取準確又快速,佇列與深度追蹤也如文件所說正常運作。

但也要帶著兩個觀念上路。第一,第一次使用 PlaywrightCrawler 時,要預留隱藏的瀏覽器下載成本;第二,不要假設我這次沒測到的部分——像是規模、崩潰後恢復、內建匯出——會跟我測到的部分一樣成熟,除非你自己在實際工作負載上驗證過。作為你自建爬蟲的基礎,Crawlee 是一個很強、也設計得很好的工程作品;但如果你想要的是一條完整、免維護的資料管線,它比較像起點,而不是終點。

試用 Thunderbit 進行網頁資料擷取 Get Started Free

常見問題

Crawlee 是免費的嗎?授權是什麼? 是的。Crawlee 是開源軟體,採用 Apache-2.0 授權,並可透過 npm 安裝(npm install crawlee)。我測試的版本是 3.17.0。若要使用瀏覽器 crawler,還需要透過 Playwright 額外下載 Chromium;這同樣免費,但會讓你的環境增加約 81.7 MiB。

CheerioCrawler 和 PlaywrightCrawler 該怎麼選? 如果資料存在原始 HTML,或後端其實有對應的 JSON API,就用 CheerioCrawler——它快很多,而且不會啟動瀏覽器。若內容是由 JavaScript 渲染出來,且你發現 HTTP 路徑拿到的是空結果,就該用 PlaywrightCrawler。在我的測試裡,HTTP 引擎在 JS 渲染頁面上回傳 0 筆,而瀏覽器引擎則完整拿回全部內容。由於它們共用同一套 API,所以切換只需要換 class,不必重寫。

Crawlee 執行時一定需要瀏覽器嗎? 只有瀏覽器 crawler 才需要。CheerioCrawler 完全不需要瀏覽器。PlaywrightCrawler(以及 PuppeteerCrawler)則需要瀏覽器 binary,請用 npx playwright install chromium 安裝。要注意的是,單純 npm install crawlee 不會自動下載瀏覽器,這是最常見的首次使用陷阱。

Crawlee 能處理分頁和多頁爬取嗎? 可以,而且這正是它相較於單獨瀏覽器函式庫的一大優勢。enqueueLinks 可以追蹤連結(包括像 .next-page 這類分頁選擇器),RequestQueue 負責去重與爬取管理,還能設定深度控制與 maxRequestsPerCrawl 限制。在測試中,我做了一次同網域爬取,從深度 0 到 2 一共走了 11 頁,而失敗請求也會透過 failedRequestHandler 明確回報。

Crawlee 跟託管爬取 API 相比如何? Crawlee 是自架型方案:你自己寫、自己跑爬蟲,也自己負責擴充、proxy 與 anti-bot 處理。像 Thunderbit 的 distill / extract 這類託管 API,則會直接回傳乾淨的 Markdown 或符合 schema 的結構化 JSON,並把渲染與 anti-bot 處理放在伺服器端,透過 API、MCP server 與 CLI 提供服務。若你想完全掌握自己的資料管線,就選 Crawlee;如果你不想自己維運與擴充瀏覽器基礎設施,就選託管 API。

Ke
Ke
Thunderbit 技術長|資深資料科學家與機器學習專家 Ke Shen 在機器學習與資料科學領域擁有近十年經驗,畢業於哥倫比亞大學,曾任 Walmart Labs 資深資料科學家。他精通 Python、R、Java 與統計學,且具備深受同儕認可的深厚專業,分享如何將複雜的 AI 演算法從理論落實到可投入生產的架構的實戰見解。
目錄
Thunderbit · AI 網路數據代理

一鍵 中從任何頁面提取數據

全球超過 25 萬用戶信賴
提供免費方案
使用 AI 提取數據
輕鬆將數據傳輸到 Google Sheets、Airtable 或 Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week