當前位置:博客首頁>>Python >> 閱讀正文

python-DHT爬蟲中路由表的實現(xiàn)

作者: 鄭曉 分類: Python 發(fā)布于: 2016-08-22 12:31 瀏覽:9,833 評論(11)


這是DHT協(xié)議中路由表的實現(xiàn),在DHT網(wǎng)絡(luò)中,每個節(jié)點維護著一張路由表(table),表中儲存著已獲取的狀態(tài)良好的節(jié)點(node)。路由表又被劃分為多個區(qū)間桶(bucket),節(jié)點應(yīng)該儲存在這些桶中,空的表只有一個桶。當桶滿時不能再插入該桶中,除非當前節(jié)點(自己)ID也在這個桶中,在這種情況下,原桶需分裂為兩個相同大小的桶,舊桶中的節(jié)點重新分配到新的子桶中。具體細節(jié)可查閱DHT協(xié)議。

以下代碼邏輯主要來源于網(wǎng)絡(luò),我只是改了兩個bug。。。

#coding:utf-8
from time import time
from hashlib import sha1
from random import randint
#生成一個20字節(jié)長度的node_id
def node_id():
hash = sha1()
s = "".join(chr(randint(0, 255)) for i in xrange(20))
hash.update(s)
return hash.digest()
#返回Node_id的10進制長整型表示 node_id->16->10
def int_ify(nid):
assert len(nid) == 20
return long(nid.encode('hex'), 16)
#node 節(jié)點類 每個節(jié)點都有id、ip和端口屬性 重新定義了節(jié)點的等于和不等于操作
class KNode:
def __init__(self, nid, ip, port):
self.nid = nid
self.ip = ip
self.port = port
def __eq__(self, other):
return self.nid == other.nid
def __ne__(self, other):
return self.nid != other.nid
#桶滿的異常類
class BucketFull:
pass
#bucket 桶類
class KBucket:
def __init__(self, min, max):
self.min = min
self.max = max
self.nodes = []
self.lastTime = time() #當前桶的最后更新時間
#檢查一個node_id是否在桶的范圍內(nèi)
def nid_in_range(self, nid):
return self.min <= int_ify(nid) < self.max #向桶中添加節(jié)點 def append(self, node): if len(node.nid) != 20: return if len(self.nodes) < 8: if node in self.nodes: self.nodes.remove(node) self.nodes.append(node) else: self.nodes.append(node) self.lastTime = time() else: raise BucketFull#路由表類class KTable: def __init__(self, nid): self.nid = nid self.nodeTotal = 0; self.buckets = [KBucket(0, 2 ** 160)] #路由表中所有的桶的列表 默認只有一個桶 #向路由表添加節(jié)點,即向表中某個桶中添加節(jié)點,桶滿時要進行拆分 def append(self, node): if node.nid == self.nid: return index = self.bucket_index(node.nid) bucket = self.buckets[index] try: bucket.append(node) self.nodeTotal = self.nodeTotal+1 except BucketFull: if not bucket.nid_in_range(self.nid): return self.split_bucket(index) self.append(node) #返回待添加節(jié)點id應(yīng)該在哪個桶的范圍中 def bucket_index(self, nid): for index, bucket in enumerate(self.buckets): if bucket.nid_in_range(nid): return index return index #拆分桶 def split_bucket(self, index): old = self.buckets[index] point = old.max - (old.max - old.min)/2 new = KBucket(point, old.max) old.max = point self.buckets.insert(index + 1, new) for node in old.nodes: if new.nid_in_range(node.nid): new.append(node) for node in new.nodes: old.nodes.remove(node) #返回離目標最近的8個node def get_neighbor(self, target): nodes = [] if len(self.buckets) == 0: return nodes index = self.bucket_index(target) nodes = self.buckets[index].nodes min = index - 1 max = index + 1 while len(nodes) < K and (min >= 0 or max < len(self.buckets)): if min >= 0:
nodes.extend(self.buckets[min].nodes)
if max < len(self.buckets): nodes.extend(self.buckets[max].nodes) min -= 1 max += 1 num = int_ify(target) nodes.sort(lambda a, b, num=num: cmp(num^int_ify(a.nid), num^int_ify(b.nid))) return nodes[:8] #打印調(diào)試信息 def print_info(self): print '桶數(shù)量:'+str(len(self.buckets)) print '節(jié)點量:'+str(self.nodeTotal)#Demo#實例化出路由表, 隨機生成一千個node,放入表中并打印表的狀態(tài)routeTable = KTable(node_id())for i in xrange(0,1000): routeTable.append(KNode(node_id(), '127.0.0.1', '80012'))routeTable.print_info()

打印出的結(jié)果顯示路由表中的桶和節(jié)點數(shù)量十分有限,說明有大量的節(jié)點已經(jīng)被拋棄,原因在代碼中的第67行,當待加入節(jié)點所需要加入的桶已滿且自身id不在這個桶中時直接忽略。
由于這種路由表實現(xiàn)復(fù)雜、需要不停的ping檢查每個節(jié)點是否有效且儲存的節(jié)點數(shù)量有限。實際做DHT爬蟲時可不實現(xiàn),爬蟲只需要不停的認識新的node,并獲取資源infohash,所以直接通過向有效的node發(fā)送完find_node后即可刪除該node,只需等待node發(fā)送的get_peers和announce_peer通知即可。

? ? ? ?

本文采用知識共享署名-非商業(yè)性使用 3.0 中國大陸許可協(xié)議進行許可,轉(zhuǎn)載時請注明出處及相應(yīng)鏈接。

本文永久鏈接: http://yjfs.org.cn/python-dht-routetable.html

python-DHT爬蟲中路由表的實現(xiàn):目前有11 條留言

用戶評論頭像 嚴格的帥哥發(fā)表于 2016年12月15日 13:52[回復(fù)]

關(guān)注了你

用戶評論頭像 虛心的鍋餅發(fā)表于 2016年11月30日 17:28[回復(fù)]

while len(nodes) < K <– 這里的k是什么東西 沒有定義過啊

    用戶評論頭像 鄭曉發(fā)表于 2016年11月30日 17:31[回復(fù)]

    K是8, 就是每個桶的節(jié)點數(shù)量,一般都默認為8

用戶評論頭像 劉明野的博客發(fā)表于 2016年09月03日 18:17[回復(fù)]

寫的不錯

用戶評論頭像 尚愛思笑話發(fā)表于 2016年08月30日 15:38[回復(fù)]

感覺很不錯的樣子!

用戶評論頭像 恭順的水母發(fā)表于 2016年08月30日 15:26[回復(fù)]

用戶評論頭像 namechea發(fā)表于 2016年08月30日 13:13[回復(fù)]

朋友,交換鏈接嗎?

    用戶評論頭像 鄭曉發(fā)表于 2016年08月30日 13:17[回復(fù)]

    你什么站?

      用戶評論頭像 namechea發(fā)表于 2016年08月30日 13:19[回復(fù)]

      這個站:52namesilo.com Namesilo

用戶評論頭像 米表發(fā)表于 2016年08月29日 08:37[回復(fù)]

隨便看看,隨便轉(zhuǎn)轉(zhuǎn)!

用戶評論頭像 蒂歐娜發(fā)表于 2016年08月26日 17:46[回復(fù)]

風吹過,我來過!

發(fā)表評論

change vcode