[英]Java: Efficient data structure to store object with no 'logical' duplicates
[英]Best efficient data structure to store URIs for a web Crawler in Java
我正在構建實現了解析部分的Web爬網程序。 現在,我想將獲得的URI存儲到有效的數據結構中。 我應該使用什么? 我正在使用Jena庫進行解析。
哈希。
例如:URL:scheme:// domain:port / path?query_string#fragment_id。
將URL解析為字符串后,將URL存儲為:
hash ['scheme'] =方案;
hash ['domain'] =域;
hash ['port'] =端口;
hash ['path'] =路徑;
hash ['query_string'] = query_string;
hash ['fragment_id'] = fragment_id;
我猜您想自動丟棄重復項,這樣就不會對URI進行兩次爬網了嗎? 然后我建議一個HashSet 。
它會自動丟棄重復項,並且在最佳情況下插入復雜度仍然保持不變。 請注意,當您使用自己的類表示URI而不是默認類java.net.URI時 ,必須重寫URI類的int hashCode()
方法以返回URI字符串的基於文本的哈希。 Object的默認方法為每個對象創建唯一的哈希碼,即使內容相同。
爬網程序通常使用Queue
來保留要檢查的URI和隨附的Set
以在將URI插入上述隊列並將URI檢查后將其放入集合中之前檢查是否重復。
如果鏈接的數量適合內存,則可以將LinkedList
作為隊列,將HashSet
作為集合。 否則,您可以將外部數據庫用於這兩個目的,也可以將排隊服務器(例如ActiveMQ)用作隊列,而將數據庫用作集合。
我將要處理的URI隊列和已處理的URI存儲在Redis中(http://redis.io/)。 Redis是一個非常快的半永久鍵值存儲,對各種數據結構(包括列表(URI隊列)和哈希(映射))具有本機支持。 這樣,這些數據結構將在Java應用程序重新啟動后幸免。 您還可以運行多個應用程序實例,而無需通過Redis進行通信。
通常,在Web爬網應用程序中-您需要管理url以丟棄蜘蛛陷阱 (有時稱為“黑洞”),放棄對同一頁面的頻繁訪問,還需要將url用作頁面內容的全局標識符。
但是另一個有趣的時刻- 放棄兩次訪問相同的URL是錯誤的 ( 因為網頁的內容可能會隨時間變化 )。
因此,滿足這些要求的最佳方法是使用某種優先級隊列 ,並將每個url與元組關聯:{url, hash(url) }。 當您獲得新的URL時-只需計算其哈希值,並且如果您的數據庫記錄中具有相同的哈希值-只需對此URL設置低優先級並將其放入優先級隊列即可。
Web搜尋器要求優先級隊列訪問URL。 因此,只有具有最高優先級的url的頁面才會被首先訪問。
您可以構建自己的哈希函數,以最佳方式滿足您的需要(例如-從url字符串中刪除參數,並從其余字符串中計算哈希)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.