什麼是關鍵字鏈結?

2021-08-26 03:22:50 字數 1728 閱讀 4407

什麼是關鍵字鏈結?

什麼是關鍵字鏈結?

部落格服務hatena diary(支援關鍵字鏈結,這是個很特別的功能。

該功能在前面的圖5.3(p.112)的關鍵字鏈結截圖中已介紹過。如圖5.3所示,寫部落格時部分關鍵字會自動加上鏈結,鏈結目標就是該關鍵字的解釋頁面。wiki的實現也能給wiki關鍵字自動加鏈結,這個功能與它很相似。

被鏈結的關鍵字就是使用者在hatena keyword(http://k. hatena.ne.jp/)上新增的關鍵字。本書執筆時(2023年8月),hatena keyword已有27萬條以上關鍵字,使用者每天建立的新關鍵字大約有100個。

關鍵字鏈結功能就是將輸入的文章與27萬條關鍵字字典進行匹配,將必要的地方替換成鏈結。鏈結替換操作實際上只是將特定關鍵字替換成html鏈結標籤而已,所以問題就是如何對文章中的關鍵字進行文字替換。

關鍵字鏈結的例子

hatena diary是部落格

→hatena diary是部落格

最初的實現

hatena diary剛剛上線時,該功能並沒有花太多功夫,簡單地採用了正規表示式,將字典中的所有單詞用or連線做成正規表示式。

(foo|bar|baz| ...)

就是這種正規表示式。假設將文字放在$text變數中,那麼把替換選項和替換字串看作表示式的eval選項進行組合,變成以下形式就可以了:

use uri::escape;

$text =~s/(foo|bar|baz)/&replace_keyword($1)/ge;

sub replace_keyword {

my$w = shift;

returnsprintf '%s', uri_escape($w),$w;

出問題了!——關鍵字字典越來越大

由於關鍵字是使用者建立的,剛上線時單詞數並不多,從資料庫中取出後直接建立正規表示式以實現關鍵字鏈結,這種奢侈的處理也完全沒有問題。但是,隨著關鍵字的數量不斷增加,問題就來了。處理正規表示式要花費很長時間。最耗時的地方有兩處:

u編譯正規表示式的處理;

v用正規表示式進行模式匹配的處理。

對於u,可以預先建立正規表示式並保持在記憶體或磁碟上,即通過快取的方法能夠繞過去了。

對於問題v,把完成了關鍵字鏈結的正文文字進行快取等處理後,開始時能繞過該問題,但要將新添的關鍵字反映到關鍵字鏈結中,必須花費一定時間重新建立快取,或者從部落格服務的特性上看,多一半文章的訪問量並不大,導致快取很難生效,所以該問題並沒有完全解決。

用模式匹配實現關鍵字鏈結的問題

隨著服務的運營,關鍵字的單詞數超過了10萬條,而且hatenadiary增加的整體訪問量使得關鍵字鏈結的處理次數也增加了許多,系統終於承受不住了。

關鍵字鏈結計算耗費大量時間的原因在於正規表示式的演算法。詳細情況可以參考正規表示式的書籍,簡單來說,正規表示式的模式匹配是基於自動機實現的。而且,perl的正規表示式實現採用的是nfa(nondeterministic finite automata,非確定型有窮自動機)。不僅perl,實用的語言大多採用了nfa引擎。

像(foo|bar|baz)這種模式匹配,nfa會使用一種簡單的方法,從輸入的開頭嘗試匹配,失敗的話就嘗試下乙個單詞,如果又失敗了,就再次嘗試下乙個單詞。因此,foo不匹配就嘗試bar,如果還不匹配,就嘗試baz……如此迴圈下去。因此,計算量與關鍵字的個數成比例。

服務剛開始時,關鍵字個數很少,相應的計算量也很少,所以沒有發生什麼問題。

本文節選自《大規模web服務開發技術》一書

圖書詳細資訊:

什麼是關鍵字鏈結?

什麼是關鍵字鏈結?什麼是關鍵字鏈結?部落格服務 hatena diary 支援關鍵字鏈結,這是個很特別的功能。該功能在前面的圖5.3 p.112 的關鍵字鏈結截圖中已介紹過。如圖5.3 所示,寫部落格時部分關鍵字會自動加上鏈結,鏈結目標就是該關鍵字的解釋頁面。wiki 的實現也能給 wiki 關鍵字...

new關鍵字 this關鍵字 base關鍵字

使用new,所做的三件事 1.類是引用物件,引用物件是在堆中開闢空間 在堆中開闢空間 2.在開闢的堆空間中建立物件 3.呼叫物件的構建函式 4.隱藏父類成員 子類的成員可以與隱藏從父類繼承的成員,類似於重寫。public new void sayhello this關鍵字的使用 1.代表當前類的物件...

this關鍵字 static關鍵字

1.當成員變數和區域性變數重名,可以用關鍵字this來區分 this 代表物件,代表那個物件呢?當前物件 this就是所在函式所屬物件的引用 簡單說 那個物件呼叫了this所在的函式,this就代表哪個物件 this也可以用於在建構函式中呼叫其他建構函式 注意 只能定義在建構函式的第一行,因為初始化...