模型 / 資料集
karust/openserp avatar
karust/openserp

OpenSERP:自架六引擎 SERP API,把搜尋結果與頁面內文一次取回

Self-hosted SERP API for AI, SEO & automation. Browser-rendered Google, Bing, Yandex, Baidu, DuckDuckGo and Ecosia search with page extraction 🎉

1,390 個 Star156 個 ForkGoMIT

秒懂

它是什麼?
OpenSERP 以 Go 撰寫,用瀏覽器渲染方式抓取 Google、Bing、Yandex、Baidu、DuckDuckGo 與 Ecosia,提供統一 JSON schema、mega/search 合併去重,以及 extract 參數直接回傳目標頁的 markdown。它適合想擺脫按次計費、又願意自行維運抓取節點的人。
適合誰用?
如果你需要的是可自控、不按搜尋次數計費的 SERP 後端,而且團隊有能力處理代理池與瀏覽器渲染的維運,OpenSERP 值得進到試用階段:先用 docker run --rm -p 127.0.0.1:7000:7000 karust/openserp:latest serve -a 0.0.0.0 -p 7000 起服務,再用 /mega/search?engines=bing,google&text=...&extract=1&mode=any 觀察 engines_responded 與 engines_failed 的實際比例。反過來說,若你的場景要求穩定的服務水準承諾、或不想碰代理與反爬對抗,自架版本就不是合適的起點。
可以商用嗎?
可以。MIT 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
還在維護嗎?
有在維護。儲存庫最近一次提交在 55 天前。
用什麼語言寫的?
主要是 Go(依據 GitHub 的語言統計)。

以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。

開源專案深度解析

它要解決的是按次計費與引擎覆蓋率的雙重問題

付費 SERP API 的計費模型是按查詢次數走,對需要大量抓取排名或餵資料給 LLM 的場景,成本會隨用量線性上升。OpenSERP 的定位是把這件事搬回自己的機器上:README 開頭寫得很直接,no API keys, no per-search billing,一行指令就能在 localhost 拿到結構化結果。它同時強調涵蓋付費 API 未必支援的引擎,README 列出六個:Google、Yandex、Baidu、Bing、DuckDuckGo、Ecosia。對做 SEO 排名追蹤的人來說,Yandex 與 Baidu 的獨立端點是實際差異點,這兩個市場的資料在英文系工具裡經常缺席。目標讀者輪廓清楚:需要搜尋結果作為 agent 工具或 SEO 後端、有基本容器或 Go 環境、並且不排斥自己處理代理與節點的人。若你只是想偶爾查幾筆結果,這個專案的維運成本不會划算。

六個引擎共用一套 schema,megasearch 負責合併與去重

架構上,OpenSERP 以 Go 撰寫,提供每個引擎的專屬端點,但刻意讓六者的 JSON schema 一致,呼叫端不需要為不同引擎寫不同解析邏輯。真正值得看的是 /mega/search 這條路徑:它接受 engines=bing,google 這類逗號分隔清單,一次送出查詢,再把多引擎結果合併、去重。README 的範例回應揭露了內部的資料流。meta 區塊回報 request_id、requested_at、took_ms,以及 engines_responded 與 engines_failed 兩個陣列,等於把「哪些引擎這次沒回來」直接攤在回應裡。results 陣列中每一筆帶有 id、rank、type、title、url、domain、favicon、position.absolute、engine,以及 domain_info(tld、sld、category)。範例中部分結果還多出 classification,標示 content_type 為 article、source_hint 為 encyclopedia。最後是 clusters:以 canonical_url 為單位聚合成叢集,內含 occurrences 陣列記錄每個引擎的排名與對應 result_id,並給出 engines_count、best_rank 與 score。這個設計意味著跨引擎比對是伺服器端做完才回傳,呼叫端拿到的是已經對齊過的視角,而不是自己寫迴圈去比對網域。

extract=1 把搜尋與頁面內文壓進同一次請求

第二個機制是 URL 抽取。在請求中加上 extract=1,回應的每筆結果會多一個 extracted 物件,內含 title、format、content、mode_used、fetched_at。範例中 format 為 markdown,content 是目標頁的正文 markdown,mode_used 顯示為 fast。這個欄位名稱本身就是一個訊號:抽取有多種模式,fast 只是其中一種,而不同模式在速度與完整度之間必然有取捨,README 沒有把各模式的差異展開說明。對 RAG 或 agent 流程而言,這個設計省掉一輪抓取:搜尋結果與內文在同一個回應裡抵達,不必先拿 URL 再自己發第二次請求、自己處理 HTML 清理。代價是請求時間被拉長,範例的 took_ms 為 720,但那只涵蓋單一引擎回應的情況,不能推論成一般水準。另外要注意 extracted.content 在範例中是被截斷顯示的,實際長度與截斷策略需要自行確認。

啟動方式:Docker 一行,或 go install 一行

取得方式有三條路。Docker 的預建映像發佈在 Docker Hub 的 karust/openserp,README 給的指令是 docker run --rm -p 127.0.0.1:7000:7000 karust/openserp:latest serve -a 0.0.0.0 -p 7000,或直接 docker compose up。Go 環境則用 go install github.com/karust/openserp@latest,接著 openserp search duckduckgo "open source serp api" --format markdown 就能在終端機拿到結果。從原始碼建置是 git clone、cd openserp、go build -o openserp .、./openserp serve。服務起來後,第一個請求範例是 curl "http://127.0.0.1:7000/mega/search?engines=bing,google&text=golang+vs+rust&extract=1&mode=any"。這裡有兩個關鍵參數值得記住:extract=1 開啟內文抽取,mode=any 表示回傳第一個回應的引擎,README 的註解寫得很清楚。輸出格式支援 JSON、Markdown、Text 與 NdJSON,過濾條件涵蓋語言、日期範圍、檔案類型與 site,另外還有 image search、AI summaries、answer boxes、people-also-ask、related searches 這些 SERP 特徵。

mode=any 的取捨,以及代理與快取的維運現實

mode=any 讓第一個回應的引擎決定結果,這在延遲敏感的 agent 場景很合理,但它同時意味著回傳內容取決於當下哪個引擎先回來,同一組參數在不同時間可能給出不同引擎的排名。範例回應中 engines_requested 是 bing 與 google,engines_responded 只有 bing,engines_failed 為空陣列。失敗清單為空卻只有一個引擎回應,這個組合值得注意:呼叫端如果只看 results 而不檢查 engines_responded,很容易誤以為兩個引擎都成功。這是使用這個 API 時必須自己寫進程式邏輯的檢查。另一個現實是抓取本身。README 把 proxies、cache、resilient mode 列為功能,說明作者清楚知道瀏覽器渲染抓搜尋引擎會被擋、會逾時、會回傳非預期頁面。resilient mode 的具體行為在提供的材料中沒有展開,無法確認它做了幾次重試、退避策略為何。可以確定的是,這些機制的存在本身就是維運負擔的證據:你要準備代理、要監控失敗率、要在引擎改版時跟著調整。這不是設定完就放著的服務。

什麼情況下它會是錯的工具

第一種情況是需要服務水準承諾的產品。自架意味著可用性由你的節點與代理池決定,OpenSERP 不提供也不承諾任何引擎的穩定回應率,engines_failed 這個欄位的存在就說明了失敗是預期內的常態而非例外。第二種情況是只想低頻查詢、不想碰容器與代理的人:裝起來的成本遠高於直接用託管服務。第三種是對搜尋引擎服務條款敏感的情境。README 沒有討論這塊,而瀏覽器渲染抓取搜尋結果在多數引擎的條款裡屬於灰色地帶,這個風險由部署者承擔,專案的 MIT 授權並不處理它。第四種是要求結果百分之百可重現的場景:搜尋結果本身隨時在變,加上 mode=any 的引擎選擇不確定性,同一組參數不保證得到相同輸出。若你的用途需要可重現的資料集,得自己加上快照與版本標記。

與 SerpApi 這類託管服務的差異在責任歸屬

最直接的替代方案是 SerpApi 這類託管 SERP API。兩者的差別不只是價格模型,而是責任歸屬。託管服務把代理輪替、引擎改版追蹤、反爬對抗、可用性監控全部收走,你付出的是按次計費與被綁定的引擎清單;OpenSERP 把這些全部交還給你,換來的是零邊際成本與自行增減引擎的自由。這個交換在用量達到某個門檻後才划算,門檻取決於你的人力成本而非查詢量。另一個方向是自己寫爬蟲。OpenSERP 相對 DIY 的價值在於已經處理好的部分:六引擎統一的 schema、clusters 的跨引擎去重、extracted 的 markdown 轉換、以及 JSON/Markdown/Text/NdJSON 四種輸出。自己從零寫這些,等於重做一遍它已經做完的整合工作。至於官方生態,README 列出 JavaScript/TypeScript SDK(@openserp/sdk)、Python SDK(openserp)、MCP server(@openserp/mcp)與 n8n 社群節點,這些客戶端同時支援自架伺服器與託管 API,設定方式分別是 baseUrl 與 apiKey。也就是說,採用自架並不會把你鎖在無法切換的位置。

授權、維護成本與升級前該確認的事

授權是 MIT,寬鬆條款,商用與修改都允許,只需保留著作權聲明。這部分不構成採用障礙,但要注意 MIT 只涵蓋程式碼本身,不涵蓋你抓取回來的搜尋結果內容,也不處理搜尋引擎的服務條款,這兩件事的合規判斷要由部署方自己做,此處不提供法律意見。維護成本方面,從版本節奏可以看出專案處於活躍狀態:v0.8.3、v0.8.6、v0.8.12 三個版本分別落在 2026 年 6 月 12 日、6 月 29 日與 7 月 22 日,間隔約兩到三週,最新一次推送與 v0.8.12 發布時間幾乎一致。這種頻率通常反映抓取類專案的本質:引擎端一改版就得跟。這也意味著升級不是可選項,而是維持可用的必要動作,採用時應該把「定期更新映像」算進維運排程。升級前建議先確認該版本是否更動了回應 schema,因為 clusters、extracted、classification 這些欄位一旦改名或調整結構,依賴它們的程式會直接壞掉。專案有 CI workflow 與 Go Reference 文件,README 也指向 examples 目錄收錄 JavaScript 與 Python 的搜尋、AI grounding、SEO、內容抽取與圖片搜尋範例,這些是評估整合成本時比 README 正文更有用的材料。

編輯結論

如果你需要的是可自控、不按搜尋次數計費的 SERP 後端,而且團隊有能力處理代理池與瀏覽器渲染的維運,OpenSERP 值得進到試用階段:先用 docker run --rm -p 127.0.0.1:7000:7000 karust/openserp:latest serve -a 0.0.0.0 -p 7000 起服務,再用 /mega/search?engines=bing,google&text=...&extract=1&mode=any 觀察 engines_responded 與 engines_failed 的實際比例。反過來說,若你的場景要求穩定的服務水準承諾、或不想碰代理與反爬對抗,自架版本就不是合適的起點。導入前務必自行驗證三件事:目標引擎在你所在網路環境下的實際可用率、extract=1 對你關心的站台是否真能取回正文、以及 MIT 授權下你對搜尋引擎服務條款的合規判斷。

官方來源

  1. karust/openserp on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
社群筆記

社群筆記