多數人第一次接觸 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 類別。

這裡有一個一定要講清楚的交界點,因為那正是兩者開始不完全對等的地方:內容存取的方式不同。在 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 項商品,還順手截圖當證據。

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

我想謹慎地說,這並不是在「證明」什麼全新發現;這只是對 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 比單獨的瀏覽器工具更有說服力:爬取編排是內建的,而且不管底下是 HTTP 還是瀏覽器,引擎更換後編排方式都一樣。你只要寫一次佇列與追蹤邏輯;至於每個 crawler 要不要渲染 JavaScript,再另外決定就好。
安裝體驗與隱藏的瀏覽器下載
安裝過程大致順利,但有一個第一次用的人很容易踩到的坑。
npm install crawlee playwright 本身可以正常完成,且沒有回報漏洞。但 PlaywrightCrawler 不會直接啟動,因為你還需要再跑一次 npx playwright install chromium,下載約 81.7 MiB 的 Chromium binary。只安裝 crawlee 套件,並不會自動把瀏覽器一起抓下來。如果你沒做這一步就直接用瀏覽器 crawler,會碰到一個啟動錯誤;如果你不熟 Playwright 的封裝方式,這個錯誤其實不太直觀。這不是 Crawlee 本身的缺陷,而是沿用 Playwright 的行為,但它確實是第一次上手時的一個摩擦點,值得先提醒。

再補一個操作層面的細節:預設情況下,Crawlee 會把資料寫到本機的 storage/ 目錄。我在測試時把它導向暫存資料夾,並關掉持久化,讓環境保持乾淨;但如果你直接照一般方式跑,專案裡就會多出一個 storage/ 資料夾。這不算問題,只是先知道會比較不意外,免得它突然出現在 git status 裡。
簡單看一下第三種引擎
Crawlee 的對等性故事不只適用於 Cheerio 與 Playwright,還包括 PuppeteerCrawler。我也檢查了這個「同介面」的主張能延伸到哪裡——是從 class 與 API 表面層來看,不是實際跑一輪爬取。
這三個 crawler 類別都追溯自同一個 BasicCrawler 基底。CheerioCrawler 走的是 HttpCrawler;PlaywrightCrawler 與 PuppeteerCrawler 則都走同一個 BrowserCrawler。我透過已安裝的套件做 introspection,發現三種引擎之間有 24 個 public methods 是共用的,包括整個設計最核心的佇列與儲存操作:run、addRequests、pushData、getData、getDataset、exportData、getRequestQueue、useState、stop。而 PuppeteerCrawler 與 PlaywrightCrawler 的 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,取得結構化資料,並透過 renderMode 的 none、basic、full 來決定何時值得啟用完整瀏覽器渲染。這個 MCP server 也能讓 AI agent(如 Claude、Cursor 以及其他 MCP client)在任務中途直接抓資料,而 CLI 則可以在終端機或 CI 中執行:
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。


