2025 年最佳網頁爬蟲工具與軟體 | Thunderbit

最後更新於 August 17, 2026
2025 年最佳網頁爬蟲工具與軟體 | Thunderbit
AI 摘要
每個 Chrome 擴充功能都會附上一份 manifest.json,裡面宣告了相當大一部分的瀏覽器能力上限:要求的 API、主機匹配模式、靜態內容指令碼、可選權限,以及允許的外部連線。這是你安裝的套件裡公開可見的檔案。它無法證明執行階段程式實際用了哪些已宣告能力、哪些資料離開了你的電腦,或哪些帳號存取是透過獨立的網頁登入完成的。我檢視了這次稽核中挑選的十款網頁爬取與瀏覽器自動化擴充功能,包括 Thunderbit——也就是我們自己的產品。差異非常大。

每一個 Chrome 擴充功能都會隨附一份 manifest.json,它公開宣告了相當大一部分的瀏覽器層級能力上限:要求的 API、主機比對模式、靜態內容腳本、選用權限,以及允許的外部連線。這是你安裝套件裡就看得到的公開檔案。它不能證明執行時程式實際用了哪些已宣告能力、哪些資料離開了你的電腦,或哪些帳號存取是透過另一個網頁登入流程完成的。

我讀取了這次審查所挑選的十個爬取與瀏覽器自動化擴充功能的 manifest,包括 Thunderbit——因為那是我們自己的產品。差異非常大。有一個完全沒有宣告長駐網站存取;另一個則宣告了 13 項權限,甚至包含 clipboardRead。Thunderbit 是這份清單中唯一宣告 debugger 的擴充功能;這是一種可附加 CDP 的廣泛能力,其風險型態與頁面存取、OAuth 或使用者提供的腳本都不同。

這些都不是指控。廣泛的權限常常是實作某項功能唯一誠實的方式;較窄的權限也可能只是代表產品功能較少。重點在於:這些差異非常巨大,而且都已公開,卻從來不會出現在比較表裡。

這份分析怎麼做

每個擴充功能都從 Google 自己的更新端點下載成 .crx——也就是 Chrome 本身使用的同一個網址——接著解壓並解析。**沒有安裝任何擴充功能,也沒有執行任何擴充功能程式碼。**這只是對一份 JSON 檔的閱讀。

下載節奏大約控制在每兩秒一個請求。每個 .crx、其 SHA-256,以及抽出的 manifest.json 都保留為分析產物。Thunderbit 與其他九個擴充功能走的是同一支腳本,不是走旁路,所以它的結果列是完全同樣的方法得出。

本分析使用兩類證據,並將它們分開:

  • **已宣告的靜態行為:**主機比對模式與 content_scripts 項目,包括 matchesrun_atall_frames
  • 執行時程式可用的能力:permissionsoptional_permissions 中列出的 API。這些宣告只表示程式可能要求或呼叫它們,並不代表真的有這麼做。

本分析不會給出任何「最強」的序位分數。debuggeruserScripts、廣泛的主機存取、OAuth scope、剪貼簿存取,以及外部訊息傳遞,暴露的是不同資料,且需要不同前提條件。若要比較,必須先有威脅模型;但這份只看 manifest 的審查並沒有提供這個模型。

下方大小皆為解壓後總量,單位是 MiB(2²⁰ bytes),由 ZIP 項目加總而來。

**截至 2026-07-29。**擴充功能會更新;引用前請重新確認。

十份 manifest 宣告了什麼

Measured results chart: Declared permission strings

官方參考:Chrome 的權限宣告指南

擴充功能版本解壓後大小檔案數權限數網站存取可否存取 file://
Axiom.ai5.1.037.1 MiB2328http://*/* + https://*/*
Table Capture11.0.4121.1 MiB1154 (+3 個選用)<all_urls>
Magical3.119.116.8 MiB39513(+2 個選用)<all_urls>
Thunderbit(我們的)4.6.415.9 MiB788 個已識別(+1 個未識別的陣列字串:commands<all_urls>
Clay for Chrome1.0.06.3 MiB516*://*/*(只在自家網域注入)
Listly0.9.63.5 MiB847http://*/*https://*/*file:///*.html
Hexomatic1.8.42.7 MiB372僅限自家網域
Agenty2.9.72.2 MiB494未宣告
Clip to Clay1.8.00.7 MiB1642 個指定網域
TexAu v21.6.60.3 MiB12614 個指定網域

還有另外兩個原本在候選名單上,但沒有列進表格,原因各自都值得單獨說明。

這種差異是設計選擇,不是大小造成的

**Agenty 沒有宣告任何 host 權限,也沒有任何內容腳本。**它的四個權限是 activeTabscriptingidentityidentity.emailactiveTab 是比較窄的一種:只有在你點擊擴充功能之後,才會給它目前分頁的存取權,而且只會持續到你離開該頁面為止。你不主動呼叫它,它就不會在你的頁面上執行任何東西。整體大小只有 2.2 MiB。

Axiom.ai 宣告了 http://*/*https://*/*,並且在 <all_urls> 比對的內容腳本中注入,解壓後總量達 37.1 MiB、共有 232 個檔案——是 Agenty 的 17 倍,同時對你造訪的每一個頁面都有常駐存取權。

Hexomatic 與 Agenty 類似:只有兩項權限(storagetabs),沒有 host 權限,內容腳本也只限制在自己的兩個網域。

Clay for Chrome 則是另一種形狀,也值得分開看:它把 *://*/* 列為 host 權限,但內容腳本只會注入到自己的網域。它的常駐能力很廣,實際自動化行為卻很窄。只看權限表會把這兩者混為一談。

十個裡有五個能存取你磁碟上的檔案

file:/// 不是網站。它是你本機檔案系統在瀏覽器分頁中的呈現——你打開的 PDF、匯出的 HTML、下載的發票。

官方參考:Chrome match-pattern 文件

其中三個擴充功能明確寫了出來。另兩個則是透過另一種方式到達:<all_urls> 包含 file: scheme。

擴充功能它如何觸及 file://manifest 中是否直接寫出 file://位置
Magical在六個內容腳本項目中的四個,匹配 file:///*——Chrome 會渲染的任何本機檔案,不只是 HTML內容腳本,以及 web_accessible_resources
Listly匹配 file:///*.html內容腳本
Table Capture透過 <all_urls> 的內容腳本;同時也直接寫出該 schemeweb_accessible_resources
Axiom.ai純粹因為使用了 <all_urls> 萬用字元沒有特別寫在任何地方
Thunderbit(我們的)純粹因為使用了 <all_urls> 萬用字元沒有特別寫在任何地方

http://*/*https://*/* 並不涵蓋 file://<all_urls>*://*/* 在這裡也不一樣。上面這五個,指的是宣告以某種路徑觸及了這個 scheme——不是因為它們選了哪一種萬用字元格式。

Chrome 會把這一切放在每個擴充功能都要單獨開啟的「允許存取檔案網址」切換開關之下,且預設是關閉的,所以這裡的宣告只是請求,不是授權。十個裡有五個是如實的統計,而在這五個之中,有兩個根本沒有在 manifest 裡任何地方寫出 file://:Axiom.ai 和我們自己的 Thunderbit。

這個統計包含 web_accessible_resources,不只是內容腳本和 host 權限。Table Capture 在那裡直接寫了 file://*/*;如果忽略這個區塊,就會把它誤放進那些沒有明寫 scheme、卻仍可觸及檔案的擴充功能裡。

你在被請求之前看不到的權限

System diagram: Permissions you can't see until they're requested

optional_permissions 會先在 manifest 裡宣告,但真正使用時才會向使用者請求,所以它們不會出現在安裝時的提示裡。只有兩個擴充功能使用了它,而其中一個相當重要。

擴充功能optional_permissions其中最關鍵的一項
Table CaptureuserScriptsdownloadsidentityuserScripts 在 Chrome 開啟使用者門檻後,可於頁面情境中執行使用者提供的腳本
MagicaldownloadswebRequestwebRequest 可觀察網路流量

userScripts 在被請求之前不會出現,也不會被任何只看權限數的人看見。

它還有一個本次審查其他權限沒有的門檻;如果忽略這點,就會把它說得過頭。要使用 userScripts,光宣告是不夠的:**Chrome 需要先有明確的使用者動作。**在 Chrome 138 之前,那個門檻是全域開啟的 Developer Mode,要在 chrome://extensions 裡打開。從 Chrome 138 起,則變成該擴充功能詳細頁上的個別 Allow User Scripts 切換開關,而且預設關閉。也就是說,對一般安裝而言,這個能力雖然已被宣告,卻是靜止的。精確說法應該是有條件的:在使用者啟用 Chrome 的門檻之後,Table Capture 才能讓 userScripts API 可用。本次審查沒有測量有多少使用者會去開那個設定頁或打開切換開關。

這些都不是隱藏起來的;它們都在 manifest 裡。若只看總權限數,就會低估這兩個產品。

注入時機,不只是範圍

內容腳本「怎麼注入」常被忽略,但這會改變整體觀感。document_start 是 Chrome 提供的最早掛鉤;all_frames 則會覆蓋第三方嵌入框架。

以下是這組擴充功能中,靜態注入到所有 frame 的項目,並依宣告時機排序:

擴充功能run_atall_frames內容腳本匹配模式
Table Capturedocument_start<all_urls>
Listlydocument_startfile:///*.html 再加上所有 http 與 https
Axiom.aidocument_start僅限自家網域
Clay for Chromedocument_start僅限自家網域
Thunderbit(我們的)document_end<all_urls>
Magicaldocument_idlefile:///* 加上廣泛的 http 與 https
TexAudocument_idle(未設定)十四個指定模式

Table Capture 和 Listly 都以最早的 hook 搭配廣泛匹配模式。Axiom.ai 和 Clay for Chrome 也用相同時機,但只限自家網域——攻擊性一樣高,目標更窄。

就靜態宣告來看,<all_urls> 加上 all_frames 是匹配廣度的上限,而 Table Capture 和 Thunderbit 都站在那一層。不過它們宣告的時機不同:Table Capture 用的是 document_start;Thunderbit 的靜態內容腳本則是 document_end。執行時 API 屬於另一類能力,不能從這張表直接推論。

**只看權限數是很糟的摘要統計。**Table Capture 只宣告四項權限——比這裡多數產品都少——但它在 <all_urls> 上以 document_startall_frames 注入,另外還能按需開啟 userScripts

誰可以向這個擴充功能發訊息

externally_connectable 用來控制哪些網頁或其他擴充功能可以直接向擴充功能的 background script 發訊息。它的預設值很反直覺。

**不寫這個鍵,反而是較寬鬆的設定。**Chrome 在 externally_connectable 缺席時的預設是:任何擴充功能都可以連線,但任何網頁都不行。要把它寫出來,反而是在限制

照這個理解,表格就會反過來看:

擴充功能externally_connectable 宣告誰可以向它發訊息
Agenty未寫寬鬆預設——任何擴充功能都可連線,任何網頁都不行
Clay for Chrome未寫寬鬆預設——任何擴充功能都可連線,任何網頁都不行
Clip to Clay未寫寬鬆預設——任何擴充功能都可連線,任何網頁都不行
Listly未寫寬鬆預設——任何擴充功能都可連線,任何網頁都不行
Table Capture未寫寬鬆預設——任何擴充功能都可連線,任何網頁都不行
TexAu未寫寬鬆預設——任何擴充功能都可連線,任何網頁都不行
Thunderbit(我們的)未寫寬鬆預設——任何擴充功能都可連線,任何網頁都不行
Hexomatic八個 extension IDs 以及 六個 web origins從關閉的基線同時打開兩條通道
Axiom.ai七個 web origins,沒有 ids擴充功能通道關閉,但打開了七個網頁
Magical{"ids": [], "matches": []}這裡唯一明確關閉兩條通道的擴充功能

Chrome 的規則有兩層。根據 manifest 參考文件:

情境誰可以連線
整個鍵都不存在「所有擴充功能都可以連線,但沒有任何網頁可以連線」
鍵存在,但 ids 未設定或為 []「沒有任何擴充功能或應用程式可以連線」
鍵存在,但 matches 未設定或為 []「沒有任何網頁可以連線」

較寬鬆的預設,取決於整個鍵不存在。一旦鍵存在,兩個子欄位都會先是關閉狀態;填入值只會把各自通道放寬。

Axiom.ai 只宣告了 matches因此它的 ids 是未設定的,也就是說沒有任何擴充功能可以向它發訊息——擴充功能通道是關閉的,不是開著的。它真正打開的是七個 web origins,其中只有一個是 Axiom 自家網域:兩個是無法歸屬的第三方(*://*.tgwc.space/**://*.bitmachine.co.uk/*),其餘則是 localhost0.0.0.0、一個 Google APIs host,以及一個它並不經營的大型社群平台。

**Hexomatic 把擴充功能通道打開給八個指定 ID。**在鍵已存在的情況下,基線是零個擴充功能;填入八個就變成八個。它的六個 matches 也把另一條通道從零放寬,而其中兩個是 http://localhost:8000/*http://localhost:3000/* 這種純 HTTP——使用者機器上任何回應這些埠的服務,都被列入允許名單。

十個裡有七個完全沒寫這個鍵,包括我們自己的 Thunderbit;這七個都落在擴充功能對擴充功能訊息傳遞的寬鬆預設上。另有兩個把那條通道關掉:Magical 是明確寫 ids: [],Axiom.ai 則是有宣告這個鍵,但完全沒提 ids。只有 Magical 把兩條通道都關上。

最後那句,正是為什麼要讀 manifest,而不是只數權限。相同的擴充功能,可以在一個面向非常廣,在另一個面向卻是整份名單裡最嚴格的。

沒人會數的那個軸:OAuth scopes

manifest 可以包含 oauth2 區塊,而其中的 scope 代表的是你在其他公司的帳號存取權——這和前面那些能力完全不同,也不是任何權限數字能反映的。

官方參考:Google OAuth 2.0 scope 清單

擴充功能請求的 oauth2 scopes
Axiom.aiopenidemailprofileauth/driveauth/spreadsheets
Table Captureauth/spreadsheetsauth/userinfo.email
Agentyopenidemailprofile
其他七個,包括我們自己的未宣告

https://www.googleapis.com/auth/drive 是比較廣的那一個。Google 也提供較窄的 drive.file scope,只授權 app 自己建立的檔案,或使用者明確選取的檔案;auth/drive 則是可在整個 Google Drive 上讀、編、建、刪。auth/spreadsheets 對帳號能存取的每一份試算表也是同樣型態。Axiom.ai 與 Table Capture 都把 Google 帳號 scope 與 <all_urls> 頁面存取綁在一起。

這張表能證明的也有兩個限制。scope 是被請求,不是自動授權——Google 會顯示同意畫面,而且使用者可以拒絕,擴充功能也可能根本不去呼叫 API。另一方面,manifest 只看得到透過 Chrome identity 流程完成的 OAuth;如果某個擴充功能是把你帶到網頁登入頁面,那這裡就不會宣告任何東西。那七個零只代表「這個檔案裡沒有請求」,不代表「沒有 Google 帳號存取權」——包括我們自己的 Thunderbit 也是如此,所以這個軸才會被如實報告,而不是被拿來當成狹窄性的證據。

我們自己的擴充功能,放在同一把尺上

Thunderbit 4.6.4 與其他九個擴充功能一樣,都是透過同一個 manifest parser 解析。套件解壓後大小為 15.9 MiB,共 78 個檔案。

已宣告的靜態行為:<all_urls> 同時出現在 host permissions 和內容腳本比對中。靜態腳本會在 all_framesdocument_end 執行。由於 <all_urls> 包含 file:,只要使用者啟用 Chrome 的檔案存取切換,manifest 就能觸及本機檔案。Thunderbit 也省略了 externally_connectable,因此 Chrome 的預設會允許任何擴充功能發訊息,但不允許任何網頁。

執行時能力上限:permissions 陣列裡有九個字串:activeTabcommandsdebuggeroffscreenscriptingsidePanelstoragetabGroupstabs。Chrome 只把其中八個視為有效權限;commands 是頂層 manifest key,放在這個陣列裡並不會產生效果。Thunderbit 是這份清單裡唯一宣告 debugger 的擴充功能,它可以把 CDP 附加到分頁。manifest 也讓 scripting 可以用於執行時註冊。這些 API 所產生的能力,已經超出靜態的 document_end 這一列,但單靠 manifest 仍無法證明 Thunderbit 是否呼叫了某個特定 CDP method,或是在更早的某個時間點註冊了某段 script。

這個差異擋下了幾個很誘人、但不成立的比較。沒有更窄的 cookies 權限,不代表帶有 debugger 的程式碼就不可能接觸到某些內容。沒有 clipboardRead,也不能證明它完全碰不到剪貼簿。反過來說,宣告了 debugger,也不能證明真的有用到那些路徑。要回答這些問題,需要看原始碼或做執行時追蹤,這兩件事本分析都沒有做。

在這個維度上,Thunderbit 對靜態網站存取相當廣,在這組產品裡又是唯一宣告 debugger 的,而且在擴充功能對擴充功能訊息傳遞方面也處於 Chrome 的預設。之所以沒有單一的「最強」排名,是因為本審查沒有提供可同時套用在 CDP、OAuth、userScripts、剪貼簿與 host 存取上的共同威脅模型。

那種沒人拿來宣傳的克制設計

TexAu 只有 0.3 MiB——比這裡最小的產品還小一半——而且它列出 14 個明確網站,不是用萬用字元:包含社群網路、開發者平台、出版平台、聊天產品、商業資料供應商,以及它自己的網域。它的內容腳本也正好對這 14 個進行比對。

讀這份 manifest,你可以非常精準地知道這個擴充功能會在哪裡運作。這同時也是一種產品揭露——目標清單比行銷文案更直接地說明了工具是做什麼的。

代價也很真實:列出名稱的做法無法抓一個不在名單上的網站,而且每新增一個目標都需要發版。但「14 個指定網域」和「所有存在的 URL」是完全不同的主張,只有其中一個是清楚可讀的。

兩個與名單不符的產品

**Captain Data 的擴充功能沒有公開發佈。**Google 的更新端點對它的 extension ID 回傳的是 HTTP 204 且沒有回應內容——這是商店不會匿名提供的回應。相對地,它的 listing 頁面則是匿名可存取的:HTTP 200、509,829 bytes。抓取內容裡找不到版本字串、最後更新日期或安裝數;腳本自己的註記也說那裡的 null 只能算弱證據,而且沒有看到登入牆。這個 ID 的確存在,也來自第一方,所以最合理的解讀是只靠連結或未列出分發,但我無法把它和下架分辨開來,也不會亂猜。

**Dataflow Kit 根本沒有 Chrome 擴充功能。**它的網站描述的是一個託管式網頁應用程式,提供點選式選取與 REST API。它原本卻被放進了 Chrome extension 的候選清單——而這通常就是這類名單的建法。

既然都能查,就也看一下新舊與覆蓋範圍

商店中繼資料能補足權限之外的產品選型脈絡。同樣的欄位也在 2026-07-30 為每個擴充功能擷取。

擴充功能商店版本最後更新安裝級距
Thunderbit(我們的)4.6.42026 年 7 月 28 日200,000
Listly0.9.62026 年 7 月 25 日100,000
Axiom.ai5.1.02026 年 7 月 20 日100,000
Table Capture11.0.412026 年 6 月 26 日200,000
Magical3.119.12026 年 4 月 4 日200,000
Agenty2.9.72026 年 2 月 8 日10,000
TexAu1.6.62025 年 8 月 20 日7,000
Clay for Chrome1.0.02025 年 4 月 9 日10,000
Clip to Clay1.8.02025 年 4 月 8 日1,000
Hexomatic1.8.42024 年 9 月 6 日3,000
Captain Data未公開提供

有三個產品超過一年沒發版,Hexomatic 甚至接近兩年。對擴充功能來說,這比對函式庫更重要:Chrome 大約每四週就會推出穩定版,而擴充功能平台本身也持續在變。userScripts 的使用門檻在 Chrome 138 就改了;若某個擴充功能最後一次發版是 2024 年,它所依據的是一套不同於現在瀏覽器正在執行的規則。

這張表也有兩個不是的地方。安裝數是 Google 分級 的——1,000 / 3,000 / 7,000 / 10,000 / 100,000 / 200,000——所以只能比較量級,不能比較更細的差距;而且有些產品在自己的行銷裡會宣稱更大的數字。日期新,只代表發版時間,不代表維護品質或權限風險。

一個很有用的附帶結果是:**在這十個套件中,商店版本都和 manifest 版本一致。**這次審查解析的 CRX,就是商店現在正在提供的版本,不是過期副本。

新舊程度會影響你需要做多少後續確認,但不會改變 manifest 語意。某個上次更新已是一年前的指定網域擴充功能,仍然可能比昨天才發版的萬用字元擴充功能暴露更少頁面表面積。新版未必比較危險;如果它能及時追上 Chrome 變更,反而可能是較好的營運選擇。做候選名單時,先看商店日期來決定要重測什麼,再看 manifest 來判斷哪些地方需要更深入的能力審查。不要把這兩欄硬合成一個分數。

manifest 告訴不了你的事

已宣告的權限只是上限,不是行為。<all_urls> 代表擴充功能可能讀取你造訪的每一個頁面,並不代表它真的有這麼做,也不代表任何資料真的離開你的機器。要確認實際發生了什麼,必須在執行時觀察網路流量——那是不同的工作,這裡沒做,而上面的任何內容也都不應被當成濫用證據。

相關回顧:Chrome 擴充功能可測試性實驗

再補三個界線:

  • **Chrome 會對其中大部分做門控。**檔案存取預設關閉;activeTab 故意設得很窄;選用權限需要執行時提示;使用者在安裝時會看到權限清單。
  • **廣泛權限常常是必要的。**如果工具的任務是「從你正在看的任何頁面擷取表格」,那它不可能只靠指定網域白名單運作。範圍窄,有時是紀律;有時只是功能較少。
  • **一個版本、一天。**所有數據都來自 2026-07-29 提供的套件。

分析中做出的重要修正

這些公開統計用了三條很容易寫錯的規則。第一,<all_urls> 包含 file: scheme,但 Chrome 仍會把真正的檔案存取關在使用者控制的切換開關後面。第二,除了內容腳本和 host 權限之外,也必須檢查 web_accessible_resources.matches;Table Capture 就是在那裡明確寫了 file://*/*。第三,externally_connectable 的預設會隨著整個鍵是缺席,還是鍵存在但子欄位為空而不同。上面的表格都一致套用了這些規則。

Thunderbit 的權限總數也區分了原始字串與 Chrome 真正認得的權限。它的陣列裡有九個項目,但 commands 屬於頂層鍵,所以這裡採用的是八個已識別權限加上一個未識別字串。最後,靜態 content_scripts 宣告不能證明程式有呼叫 scripting.registerContentScripts 或某個 CDP method。這些可能性只會出現在執行時能力層級,而不會被視為觀察到的行為。原始 manifest、CRX hash 與 parser 輸出都應該在文章附錄連結出來,讓讀者能在不信任文字敘述的情況下自行驗證這些正規化處理。

如果你真的要做安裝決策,至少要分開比較四個面向:預設涵蓋哪些頁面、哪些明確的使用者動作會解鎖更多範圍、哪些瀏覽器或帳號 API 會因此可用,以及哪些外部呼叫者能向這個擴充功能發訊息。Agenty 的 activeTab 模式、Table Capture 的門控 userScripts、Axiom.ai 的 Drive scope,以及 Thunderbit 的 debugger 宣告,都不是同一條線上的點;它們是在回答不同的威脅問題。

下面這張表把這四種刻意不同的設計放在一起看:

擴充功能manifest 裡看得見的頁面範圍進一步的門檻本次審查中的非頁面能力對外訊息傳遞狀態
Agenty沒有 host 權限或靜態內容腳本使用者點擊當前分頁後才啟用 activeTabChrome identity 權限key 未寫:任何擴充功能都可連線,任何網頁都不行
Table Capture<all_urls> 上於 document_start、所有 frames 靜態注入腳本檔案存取預設關閉;userScripts 需要 Chrome 另一個使用者門檻選用的 userScriptsdownloadsidentitykey 未寫:任何擴充功能都可連線,任何網頁都不行
Axiom.aiHTTP 與 HTTPS 萬用字元存取;在自己的網域上於 document_start 注入靜態腳本針對請求的 Google scopes 需先取得 OAuth 同意已宣告的 Drive 與 Sheets OAuth scopes擴充功能呼叫者關閉;七個 web origins 打開
Thunderbit<all_urls> host 存取,以及在所有 frames 上於 document_end 靜態注入腳本檔案存取預設關閉;附加 debugger 受 Chrome 控制且有使用者可見行為已宣告的 debuggerscriptingtabs 及相關瀏覽器 APIkey 未寫:任何擴充功能都可連線,任何網頁都不行

這張表仍然不會產生勝負。Agenty 的常駐頁面範圍很窄,不代表它的後端怎麼處理送出的資料。Axiom.ai 的帳號 scopes 也不能跟一個擴充功能讀取目前頁面直接相比。Table Capture 的 userScripts 宣告在使用者啟用另一個門檻前是靜止的。Thunderbit 的 debugger 權限暴露了很大的瀏覽器控制面,但 manifest 不會透露它的程式碼實際呼叫了哪些 CDP domains 或 methods。每一列告訴你的,都只是下一步該查什麼:執行時網路流量、原始碼、同意流程,或瀏覽器 API traces。

System diagram: How to read your own

讀 Chrome 安裝提示時,這種切分也一樣重要。原始權限數無法呈現時機、frame 範圍、OAuth scope、web_accessible_resources,或 externally_connectable 鍵是否省略。反過來說,廣泛的宣告也不是蒐集或外洩的證據。manifest 審查真正有用的產出,是一份優先排序過的執行時測試計畫:先找出資料表面,再標註使用者門檻,最後觀察那條已宣告的路徑到底有沒有被走。

如何讀自己的

相關回顧:瀏覽器自動化指南

  1. chrome://extensions詳細資料 可以看到已授權的網站存取,並可把任何不需要長駐存取的項目改成 按一下時。這只能縮小上面提到的網站存取部分,對進來的訊息傳遞(externally_connectable 會不受影響地到達 service worker)或瀏覽器層級權限都沒有作用。Thunderbit 的 debugger 宣告在這裡尤其重要。Chromium 自己的擴充功能安全文件指出,debugger API「在某些情況下也可能繞過其他典型限制,例如 host 權限或檔案存取」,所以把網站存取設成「按一下時」並不能限制它能碰到什麼。這個控制也不會影響 tabswebNavigationclipboardReaddownloads,或 optional_permissions 裡的任何東西。
  2. 若看原始檔案,套件會放在 Chrome 的 Extensions/<id>/<version>/ 目錄下。要讀六個欄位:permissionsoptional_permissionshost_permissionscontent_scripts(裡面的 matchesrun_atall_frames)、externally_connectable——並記得鍵不存在對擴充功能呼叫者來說是寬鬆的——以及 web_accessible_resources,其中的 matches 也可能寫出內容腳本沒寫的 scheme。Thunderbit 的最後一欄有兩個 <all_urls> 項目,對所有 origin 開放 index.html 和兩個內嵌腳本,而且 use_dynamic_url: false,代表頁面可以測試那些穩定的 extension URL 是否能解析。
  3. 再把 listing 的最後更新日期和目前 Chrome 版本對一下。

揭露與資源:本文由 Thunderbit 發布,而我們的擴充功能也被包含在同一張表與同一個 parser 裡。我們的 開源 scraper 支柱文 會涵蓋非擴充功能工具。

試用 Thunderbit 進行網頁資料擷取

簡短版

十個爬取與自動化擴充功能——包含我們自己的——都可以從各自的 manifest 讀出來。

Agenty 沒有宣告網站存取,也沒有內容腳本;你點擊它時,它只會作用在你當下看的分頁上,整體大小 2.2 MiB。Axiom.ai 宣告了所有 HTTP 與 HTTPS URL,整體 37.1 MiB。Magical 宣告了 13 項權限,包含 clipboardRead——而且它也是這裡唯一把進來的訊息傳遞完全關閉的擴充功能。Table Capture 只宣告四項權限,卻會在 <all_urls> 上於 document_start 注入到所有 frames——這和我們的比對上限一樣,但更早;另外還能按需啟用 userScriptsTexAu 是最小的,而且它列出的目標最多——14 個模式,分布在 13 個不同屬性上。它不是唯一會列出目標的:Clip to Clay 宣告了兩個(clay.com 和一個第三方網站),Hexomatic 與 Clay for Chrome 也各自列出自己的網域。TexAu 則是唯一一個所列清單大多是別人的網站的產品。 十個裡有五個可以碰到你磁碟上的檔案,其中兩個——Axiom.ai 和我們自己的 Thunderbit——甚至從頭到尾都沒有寫出 file://

我們自己的 Thunderbit 站在較寬的一側:host 存取和靜態注入都用 <all_urls>,另外還有 debugger——這是這組裡沒有其他擴充功能宣告的。它也處於 Chrome 預設允許任何擴充功能訊息傳遞的狀態,並且在 Chrome 的使用者門檻開啟後可以觸及 file://

宣告只是上限,不是行為;這些內容也都不代表濫用。但它們確實是公開的、可以免費查核的,而且兩端之間的差距,比任何產品頁上寫的都大。

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

常見問題

廣泛權限是不是代表這個擴充功能有問題?為什麼只數權限不夠? 不是;只看數量會漏掉兩件事。<all_urls> 只代表擴充功能可能讀取你造訪的每個頁面,並不說明它實際做了什麼,也不代表任何資料會離開你的機器;而一個設計來從任何頁面擷取資料的工具,確實不可能只靠指定網域白名單運作。這裡看到的是差異,不是濫用;要確認真實行為,需要做執行時流量分析,而這次審查沒有做。至於數量本身:注入設定不是權限,所以 Table Capture 只算四項權限,卻能在 document_startall_frames<all_urls> 上注入。optional_permissions 也不會出現在安裝提示裡——Table Capture 可以在執行時請求 userScripts,讓它能在頁面情境中執行任意使用者腳本,而 Magical 可以請求 webRequest

哪一個要得最少? Agenty:四項權限、沒有 host 權限、也沒有內容腳本。它依賴 activeTab,只有在你點擊擴充功能之後才會取得目前分頁的存取權,而且只會持續到你離開該頁面。第二名是 Hexomatic,只有兩項權限,內容腳本也只限於自己的網域。

擴充功能怎麼不用宣告 file:// 就能碰到我的本機檔案? 因為 <all_urls> 包含 file: scheme。Listly、Magical 和 Table Capture 都直接寫出 file:// pattern——Magical 是在內容腳本裡,Table Capture 則是在 web_accessible_resources 裡。Axiom.ai 和 Thunderbit 則是靠萬用字元觸及它,完全沒有提到 file://http://*/*https://*/* 都不涵蓋 file://。Chrome 會把檔案存取預設設為關閉,放在每個擴充功能單獨的切換開關後面,所以這裡的宣告只是請求,不是授權。

什麼是 externally_connectable?為什麼不寫它反而比較寬鬆? 它列出哪些 web origins 或擴充功能 ID 可以向擴充功能的 background script 發訊息。Chrome 在這個鍵缺席時的預設是:任何擴充功能都能連線,但沒有任何網頁能連線。這十個裡有七個都沒寫,包括 Thunderbit。鍵存在時,Hexomatic 把擴充功能通道開給八個指定 ID;Axiom.ai 開了七個 web origins,但把擴充功能通道關著;Magical 則用空清單把兩條通道都關掉。

Thunderbit 自己的 manifest 寫了什麼? <all_urls> 用於 host 存取與靜態內容腳本注入,內容腳本在 all_framesdocument_end 執行;整體 15.9 MiB、78 個檔案;以及權限陣列中的九個字串。這九個裡有八個是 Chrome 認得的權限:activeTabdebuggeroffscreenscriptingsidePanelstoragetabGroupstabscommands 是頂層 manifest key,放在那個陣列裡不會產生效果。這組裡沒有其他擴充功能宣告 debugger。Thunderbit 也會在 Chrome 開啟檔案存取門檻後,透過 <all_urls> 觸及 file://,並省略了 externally_connectable。由於執行時行為沒有真的跑過,所以這份審查不主張它實際呼叫了哪些 CDP 或 scripting 方法。

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

1 次點擊 內擷取任何頁面的資料

獲 250,000+ 用戶信賴
提供免費方案
從網頁到試算表
描述你需要什麼——Thunderbit 的 AI Agent 會幫你抓取並匯出到 Excel、Google Sheets、Airtable 或 Notion。可免費開始。
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week