php dht爬虫,利用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條
ping
find_node
get_peers (在edonkey kad中這叫find_value)
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如下:
通過異或算法計算距離,應該往哪個桶插入。
如果這個桶是不滿的,則插入成功。
如果這個桶是滿的,并且這個桶中不包含自己,則插入失敗。反之則分裂這個桶,并且遞歸的再嘗試插入。理解Routing table是DHT爬蟲的關鍵,可以參考協議文檔
這里是一個我開發的
爬蟲的關鍵
通過上述基礎知識,可以得到以下結論:
盡量認識更多的Node,這點可以通過find_node來實現。
盡量讓自己插入到對方的Routing table中,只有這樣,當對方下載資源時才會優先通知你。
插入對方的Routing table成功的關鍵在于自己的NodeID離對方的NodeID足夠的近。
爬蟲只無需現實所有的協議,只需要實現find_node(query),get_peers(response),announce_peer(response),ping(response)
Engiy?的開源簡化Node.js版DHTSpider可以參考,有疑問可以github上給我留言。
總結
以上是生活随笔為你收集整理的php dht爬虫,利用DHT网络,爬取bt种子。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构总结
- 下一篇: matlab怎么画地震反应谱,地震工程学