利用DHT網絡,爬取bt種子。


DHT網絡爬蟲


傳統的Bittorrent服務

傳統的BT服務是由兩部份組成的,tracker服務和p2p服務,通過前者用戶可以知道誰擁有資源,后者是通過前者向擁有資源的用戶發起下載。


Trackerless

目前在大多數國家,提供tracker服務都是非法的。最終有一天tracker服務會像edonkey的服務一樣消失。trackerless的需求於是變得迫切起來。


DHT網絡

DHT網絡就是解決trackerless目前運用最廣的方案,核心算法叫Kademlia,也就是所謂的異或算法。在Bittorrent中它叫DHT,在edonkey中它叫Kad,兩者算法是一至的,但細節不同,前者更注重文件傳輸,后者更在意文件分享。


什么是NodeID和InfoHash

在DHT網絡中,所有的用戶和資源都有一個20bytes的ID,用戶叫NodeID,資源叫InfoHash。NodeID通常是根據用戶的IP端口計算得出的(但在DHT爬蟲中可以隨機獲取一個20bytes的串,無關緊要),InfoHash是根據torrent種子文件的info字段,用hash sha1計算得出的。在DHT協議中,

NodeID可以通過以下代碼簡單的得到

const nodeID = crypto.createHash('sha1').update(Math.random()*100000).digest()
通過種子文件計算得到InfoHash的代碼
const infoHash = crypto.createHash('sha1').update(bencode.decode('file.torrent').info).digest()
得到可傳播的magnet鏈接就簡單了
const magnet = `magnet:?xt=urn:btih:${infoHash.toString('hex').toUpperCase()}`

 

可見DHT網絡中用戶,資源都是無區別的,所以就有了xor算法之說。NodeID之間可以用異或計算出距離,NodeID和InfoHash之間同樣可以計算距離,InfoHash之間也可以計算距離。計算方法很簡單,把infoHash或NodeID換為數值,然后按位異或,就得到了距離。這很關鍵,在下面的Routing table中會運用到。異或算法得到的距離的結果雖然不是物理上的距離關系,但是在數學邏輯上是自洽的。


DHT協議

共4條

  1. ping
  2. find_node
  3. get_peers (在edonkey kad中這叫find_value)
  4. announce_peer

 

ping

是用檢查Node狀態,用以更新Routing table

find_node

通常是用來初始化Routing table,因為一開始,你在Routing table是空的,需要通過向公共節點發送find_node來填充之。

get_peers

是當用戶要下載種子資源時向其它Node發起的。如果Node有該資源,則返回資源的下載端口以供對方下載,如果沒有,則根據異或算法在自己的Routing table中尋找離資源最近的Node返回給對方,對方如此遞歸發送get_peers,直到找到資源為止。

announce_peer

當用用戶下載完種子資源,通過種子開始下載時(這里下載行為通常會回倒為tracker式下載,但也有有種子文件是有Nodes字段的,可以通過純p2p下載)通知所有曾經get_peers咨詢過的node。 announce_peer是爬蟲的關鍵,當下載開始,用戶就會通知,於是就得到了一個有效的InfoHash。


Routing table

每個Node都要維護一個Routing table以存放Node信息。 Routing table的容器為桶,稱為K桶,桶的容量為8(kad中為20)。桶的數量是可以增加的,當桶的個數超過8時,桶就會平均的分裂。桶中的保存的就是Node信息,包含NodeID、IP和端口。 當Node接受到任意一條協議時,都會試圖向Routing table中插入對方的NodeID,插入Rule如下:

  1. 通過異或算法計算距離,應該往哪個桶插入。
  2. 如果這個桶是不滿的,則插入成功。
  3. 如果這個桶是滿的,並且這個桶中不包含自己,則插入失敗。反之則分裂這個桶,並且遞歸的再嘗試插入。
理解Routing table是DHT爬蟲的關鍵,可以參考 協議文檔

 

這里是一個我開發的 BT搜索,磁力搜索,每天可以抓取infohash100w以上,metainfo20w以上。

爬蟲的關鍵

通過上述基礎知識,可以得到以下結論:

  1. 盡量認識更多的Node,這點可以通過find_node來實現。
  2. 盡量讓自己插入到對方的Routing table中,只有這樣,當對方下載資源時才會優先通知你。
  3. 插入對方的Routing table成功的關鍵在於自己的NodeID離對方的NodeID足夠的近。
  4. 爬蟲只無需現實所有的協議,只需要實現find_node(query),get_peers(response),announce_peer(response),ping(response)
  5. Engiy 的開源簡化Node.js版DHTSpider可以參考,有疑問可以github上給我留言。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM