開源、可定製的網頁批註工具——Hypothesis【待實驗】

 

Matrix 首頁推薦

Matrix 是少數派的寫作社區,我們主張分享真實的產品體驗,有實用價值的經驗與思考。我們會不定期挑選 Matrix 最優質的文章,展示來自用戶的最真實的體驗和觀點。

文章代表作者個人觀點,少數派僅對標題和排版略作修改。


引言

俗話說「不動筆墨不讀書」,但在網絡閱讀的場景下,給「筆墨」找到合適的電子替代物並不容易。儘管市面上存在不少批註網頁文章的解決方案,但仔細想來,似乎很少有哪個工具能較好地同時滿足以下幾個要求:

  • 跨平臺:電子閱讀的場景非常寬泛,理想的工具應當在各個平臺上都能使用。
  • 可溯源:批註內容往往需要和原始上下文結合才便於理解。因此,理想的工具不僅應該記錄批註的內容,還應該能追溯到批註在原始文本中的位置。
  • 可遷移:批註的主要意義在於事後參考引用。爲此,理想的工具應當允許將數據以通用格式導出,最好還能提供 API 以便對接其他工具和實現自動化。

究其原因,上述目標在網頁環境下中並不容易達成,甚至是相互矛盾的:不同平臺的功能和交互邏輯各異,很難開發出通用的解決方案;網頁文本很不穩定,其內容和格式經常隨着編輯、改版而變化。因此,爲實現跨平臺和可溯源,大多數產品都選擇了犧牲可遷移性,以私有格式存儲批註數據,並且批註的對象往往並非原始網頁,而是其經過優化和重排版後的「替身」。

Instapaper 等主流工具一般是在創建的網頁「替身」上實現批註

不過,今年早些時候,我偶然發現了一個名爲 Hypothesis 的工具。這是一個開源項目,註冊和使用完全免費,收入主要通過爲教育行業定製 LMS(學習管理系統)支撐。

與 Pocket、Instapaper 等知名服務相比,Hypothesis 給我的最初印象是其貌不揚、界面簡陋,且上手門檻較高。但在熟悉操作後,我發現它正是一個能較好兼顧上述三個理想特性的工具。

概括而言,Hypothesis 實現這些特性的方式是:

  • 跨平臺:Hypothesis 沒有客戶端,其功能主要通過小書籤(bookmarklet)訪問。打開任何網頁後點擊該書籤,就可以加載 Hypothesis 的代碼、啓用批註,迴避了針對各個平臺安裝專用客戶端的麻煩。此外,它還提供了一個代理入口 https://via.hypothes.is/,通過該入口訪問網頁後可以直接開始批註。
  • 可溯源:Hypothesis 在批註時不僅會記錄批註內容,而且會通過多種方式記錄批註在原文中的位置(下文將會詳細解釋),這使得即便網頁內容發生較大變化,它仍然能準確定位。
  • 可遷移:Hypothesis 提供了完善的 API,可以結構化地導出所有批註數據。此外,Hypothesis API 還有一個半官方的網頁前端 Facet,可以搜索滿足特定條件的批註,並導出爲 HTML、CSV 等格式。

下文將首先演示 Hypothsis 的基礎操作,然後在實驗基礎上解釋該服務實現原理中的獨特之處,最後介紹基於 Hypothsis API 的一些進階用法。

一、簡易上手

我們以批註隨機挑選的一個網頁爲例(好吧,並沒有隨機,是我寫的文章,原諒這點私心),演示 Hypothesis 的基本用法。

(一)註冊和配置

首先,前往 Hypothesis 官網,註冊一個賬號

完成註冊並登錄後,點擊頁面右上角的齒輪圖標,選擇「Developer」,生成自己賬號對應的 API token,留存備用。

然後,到指引頁面找到「Hypothesis Bookmarklet」小書籤按鈕,將其拖拽到瀏覽器的書籤欄,或者點擊右鍵添加到書籤。Chrome 用戶也可以選擇安裝插件,但其功能與小書籤並無差異,沒有太大必要。

(二)批註

打開要批註的網頁,點擊上面步驟添加的小書籤。稍等片刻,Hypothesis 的工具條就會出現在頁面右側。點擊其頂部的箭頭按鈕將面板展開,然後點擊「Log in」登錄自己的賬號。

Hypothesis 的批註工具欄

注意到面板頂部的「Public」字樣,這代表批註內容將被存放在一個公開的分組(group)中,其他 Hypothesis 用戶在批註相同網頁時將可以看到你的用戶名和批註。如果對此介意,可以點擊並切換到「Private」分組。你也可以根據自己的整理需要,創建任意名稱的分組。

這時,選中網頁上任意文本,頁面就會彈出一個工具列,允許你選擇將這段文本高亮(highlight)或添加批註(annotate);批註功能支持 Markdown 語法、LaTeX 公式和添加標籤(tag)

批註過程中,Hypothesis 工具條會以數字標籤的形式實時展示已有批註的數量和位置,點擊即可快速定位和編輯。你也可以點擊工具條上的眼形按鈕隱藏高亮,或者點擊便籤按鈕添加針對整個頁面的批註。

(三)回顧、審閱和導出

Hypothesis 主界面會顯示近期批註過的網頁;點擊標題將其展開,即可看到各條批註,並進行跳轉到原文、編輯、鏈接分享等操作。你也可以通過頁面頂部的搜索框根據內容、分組、URL、標籤等條件搜索批註。

Hypothesis 管理界面

可惜的是,Hypothesis 官網的檢索功能比較簡陋,也沒有提供批量導出功能。對此,最簡單的解決方案是使用前面提到的 Facet 工具。

Facet 界面

訪問該工具頁面後,在左上角的「User」框中填入自己的 Hypothesis 用戶名,並在左下角的「Hypothesis API token」框中填入之前生成的 API token,然後根據需要填寫其他檢索條件(留空則默認顯示近期批註頁面),就可以在頁面右側看到實時更新的檢索結果。如果需要批量導出,可以點擊「CSV」或「JSON」按鈕獲得相應格式的數據,然後用 Excel 等工具進一步處理即可。

Facet 導出的 CSV 格式批註數據

二、Hypothesis 的殺手鐗——「模糊錨定」

如果只看上面的操作步驟和界面,你也許會和我最開始一樣,覺得 Hypothesis 只是一個比較簡陋的批註工具。但 Hypothesis 的真正實力在於底層——即使網頁被編輯得「面目全非」,它仍然可以準確定位到原始的批註位置。

我們可以通過一個實驗來演示 Hypothesis 對於頁面變動情況的適應能力。

下圖中的頁面是我用 Notion 創建的。Notion 的頁面由可以隨意移動和變換的塊(block)組成,可以很方便地模擬網頁文本內容和結構的變動。這個最初版本的頁面包含一個可摺疊列表,其中有三個子列表項。我用 Hypothsis 高亮了其中的第一項。

現在,交換其中第一項和第二項的順序,刷新頁面後重新打開 Hypothesis。可以看到,它正確地識別出了列表項位置的變化,維持了原來的第一項(現在的第二項)的高亮。

接着,嘗試更大幅度地改變頁面佈局,例如 (a) 將原有的高亮項移到可摺疊列表之外(相當於改變了元素的層級),或者 (b) 刪除原有高亮項、並另起一行填入相同的文本(相當於刪除原有元素、然後創建一個類似的新元素)。可以看到,Hypothesis 仍然找出了最接近的元素,並將其關聯到既有的標註上。

事實上,即使將原來被高亮的第一項完全刪除,並打亂列表的順序,Hypothesis 仍然會盡力尋找最接近的高亮項。根據下圖,它的匹配結果是原來的第三項,因爲它在層級、位置等方面最接近於被刪除的第一項。

而當將整個列表完全刪除時,Hypothesis 也就選擇了適可而止,不再嘗試高亮頁面元素,而是將丟失關聯的高亮項顯示在「orphaned」分類下,讓用戶仍然可以看到之前摘錄的內容。

那麼,Hypothesis 的這種溯源能力是如何實現的呢?爲此,首先要理解通過程序定位網頁文本難在何處。

人腦和電腦對網頁文本的認識是不一樣的。在我們眼中,網頁上的文本就是由一個個字碼成的,是一個扁平的、串狀的結構。而在電腦看來,網頁是一棵由不同層級的元素組成的「樹」(DOM 模型),而網頁上的文本就是這棵樹上的枝節。

通過瀏覽器的「檢查元素」功能即可看出用戶和電腦對網頁文本的不同認識:線性(上)和樹狀(下)

假如網站發生改版,但既有的文章內容不變,那麼在用戶眼中,文章還是原來的文章,掃視一下就能找到原來某個句子的新位置。即使少量修訂了正文內容,憑藉文義、上下文等信息來重新定位也不是難事。

但對於電腦來說,即使版式、內容只發生輕微的變動,代表着先前版本的那棵「樹」就已經面目全非了——枝節的數量、層級和排列方式都發生了改變。因此,很難只靠元素路徑、文本內容等單一維度的信息找回原有文本的新位置。

Hypothesis 是通過一套稱爲「模糊錨定」(Fuzzy Anchoring)的方法來解決這個問題的。

這種方案有點像綜合了人腦和電腦的認知方式,既將標註文本看作 DOM 樹狀結構上的元素,記錄其層級路徑;又將其看作連貫文本中的一段,記錄其所在位置和上下文。在重新加載頁面時,也結合使用這些記錄信息,通過精度要求逐漸降低的多次嘗試,定位到原始的標註文本。

具體而言,在存儲標註文本在頁面上的位置時,Hypothesis 會同時使用三種不同方法:

  1. 「範圍選擇器」RangeSelector)記錄標註文本在網頁樹狀結構中的位置,即文本開始和結尾對應的 XPath 路徑及偏移量。用通俗的話說,類似於「高亮部分開始於第一根大樹枝上的第二根小樹枝左起 3 釐米處,結束於第二根大樹枝上的第三根小樹枝左起 2 釐米處」。
  2. 將網頁上的元素逐個轉換爲文本(技術上是通過 DOM Selection API 中的 .toString 方法)並串聯起來,然後通過「文本位置選擇器」TextPositionSelector)記錄標註文本的開頭和結尾在這一整段文本中的位置。這類似於用戶對網頁文本的線性理解方式:「高亮部分從第 7610 個字開始,到第 8124 個字爲止」。
  3. 通過「文本引用選擇器」TextQuoteSelector)記錄標註文本的原始內容以及其前後各 32 個字符的上下文——類似於「高亮的這句話是『我在百貨公司當售貨員』,它的上一句是『張華考上了北京大學』,下一句是『我們都有光明的前途』」。

Hypothesis 使用的選擇器

而當用戶重新打開一個之前標註過的網頁時,Hypothesis 便會依次利用上面記錄的幾種信息,試圖定位標註文本:

  1. 嘗試用 RangeSelector 記錄的路徑和偏移量,在 DOM 中直接定位文本,然後將定位結果和文本引用選擇器中記錄的文本內容比對,如一致,則認爲匹配成功。顯然,如果網頁的內容和結構都沒有發生變化,這將是最快捷準確的方式。
  2. 如果前一種方法未成功,說明網頁的結構可能已經發生變化。這時,Hypothesis 會重新將網頁轉換爲文本,然後根據 TextPositionSelector 記錄的範圍進行定位,並將結果和之前記錄的內容比對,如一致,則認爲匹配成功。
  3. 如果仍然未能準確定位,說明網頁的結構和內容都發生了變化。這時,Hypothesis 會選擇放棄準確定位,以 TextQuoteSelector 中記錄的上下文爲關鍵詞作全文模糊搜索;如果能找到類似的上下文,並且其中「夾」着的內容和之前記錄的標註內容大致相同,就認爲這是原來的標註文本。
  4. 如果這種「前後夾擊」還是查無結果,Hypothesis 會進行最後一次嘗試,直接用 TextQuoteSelector 記錄的原始標註內容在網頁全文中作模糊搜索,並將大致相同的搜索結果看成是原來的標註文本。
  5. 如果上述努力全部歸於失敗,Hypothesis 就會將這段「無家可歸」的標註顯示在側邊欄的「孤本」(orphaned)分類下,以供用戶參考。

在這樣一套縝密機制的支撐下,Hypothesis 較強的定位回溯能力也就不難理解了。

三、API 的進階使用——以將最近批註導出爲 Markdown 爲例

儘管 Hypothesis 網站和 Facet 已經能實現多數常用功能,但還是不足以滿足更個性化的需求。我自己的習慣就是標註完一個網頁後以 Markdown 格式導出,其內容包括帶鏈接的標題和列表形式的摘錄內容:

### [標題](http://examples.com)

- 第一條高亮內容
- 第二條高亮內容
…

爲此,我製作了一個相應的 Alfred 動作

注:導入時,需要填寫自己的用戶名和 API token。該動作基於 Python 3,並且依賴 requests 和 pyperclip 用於發送請求和寫入系統剪貼板:python3 -m pip install requests pyperclip。)

對於 iOS 上的使用場景,我也製作了一個捷徑動作實現類似效果:

注:限於捷徑 app 的功能,該動作無法像 Alfred 版本那樣實現按批註在原文中的位置排列的功能,而只能根據創建批註的順序排列。)

上面的效果都是通過調用 Hypothesis API 實現的。

Hypothesis API 的功能非常完善,覆蓋了批註從添加、搜索到編輯的整個週期,具體可以查閱 API 文檔來了解。其中,與獲取和導出批註內容最相關的是搜索 API,使用要點是:

  • 地址:https://api.hypothes.is/api/search
  • 方法:GET
  • 鑑權:Bearer 方式,即應在請求 header 中加入 Authorization: Bearer <API token>
  • 參數:用戶名(user)、網址(uri)、結果條數(limit,上限爲 200)等

搜索 API 的響應爲 JSON 格式,其中:

  • rows 數組中的每個對象對應一條批註記錄,默認按照更新時間倒序排列(可以通過 sort 參數改爲創建時間或網址排列等)。
  • 每個批註對象中的 target 數組都包含 3 個對象,依次對應上文介紹過的「範圍選擇器」(RangeSelector)、「文本位置選擇器」(TextPositionSelector)和「文本引用選擇器」(TextQuoteSelector)。

因此,就獲取高亮文本內容而言,應當獲取文本引用選擇器對象下的 exact(原文)鍵值。換言之,對於序號爲 n(從 0 起算)的批註,其原文內容在輸出中的位置(JSONPath)是:

$['rows'][n]['target'][0]['selector'][2]['exact']

在此基礎上,我們就可以通過程序方式獲取符合指定條件的批註文本,並整理爲任意所需的格式。

總結與建議

除了上面提到的功能特性,Hypothesis 還有不少隱藏用法。例如,除了標註網頁,Hypothesis 還可以用來批註 PDF 文檔,無論 PDF 是存在線上還是本地。另外,通過 Hypothesis 創建的公開批註可以通過 RSS 地址 https://hypothes.is/stream.rss?user=<username> 訂閱,從而實現與 IFTTT 等自動化工具的整合等。

當然,Hypothesis 仍然有很多不足。例如,Hypothesis 通過 JavaScript 書籤啓用批註的方式,雖然具有較好的跨平臺能力,但有時會影響頁面的佈局,或和網頁原有的交互功能衝突。在 Safari 這類隱私管理較爲嚴格的瀏覽器上,其 Cookies 信息會時常被清除,導致需要頻繁重新登錄,顯得比較麻煩。

又如,Hypothesis 並不像很多其他服務那樣提供網頁備份功能,從而將其拿手的「模糊錨定」功能置於一種尷尬境地:如果連網頁本身都被刪除,再強的批註定位能力也無用武之處。因此,對於具有較高保存價值的網頁,先用 Wayback Machine 等工具創建快照副本,再用 Hypothesis 對副本做批註,會是更穩妥的做法。

更重要的是,Hypothesis 歸根結底是一個面向教育和學術應用場景開發的項目,網頁版服務只是將相關技術簡單包裝後提供給公衆的公益「副業」。外觀簡陋、上手門檻較高等特點不僅是情理之中,而且在今後很可能也會一直如此,不太可能像某些資金充裕的明星服務那樣快速迭代、花樣頻出。

因此,如果你在找的是一個美觀方便、上手即用的閱讀、批註工具,Hypothesis 可能並不適合你,付費購買 Pocket、Instapaper 等商業化服務的會籍是省心的選擇。但如果你對於批註工具的可定製性有較高的要求,或者準備將網頁批註整合進自己的知識管理流程,並且不排斥通過一定的 DIY 實現想要的效果,Hypothesis 肯定是一個值得嘗試的選擇。

> 下載少數派 客戶端 、關注 少數派公衆號 ,瞭解更妙的數字生活 🍃
> 想申請成爲少數派作者?衝!

 
 
 
143
36
 
掃碼分享
 
 
引言
 
一、簡易上手
 
(一)註冊和配置
 
(二)批註
 
(三)回顧、審閱和導出
 
二、Hypothesis 的殺手鐗——「模糊錨定」
 
三、API 的進階使用——以將最近批註導出爲 Markdown 爲例
 
總結與建議
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章