用Python教你如何“养”一只DHT爬虫

废话少说, 直接上菜.
  我假设你了解:
  1, DHT协议
  2, 网络字节序/主机字节序
  3, bencode
  4, UDP
  5, 种子文件构造
  不懂的赶紧去google, 要是缺一个, 我会一口盐汽水喷死你的!
  最重要的是, 你必须会编程!!!!!!! 必须会!!!!!!!!!!!
  ok, DHT原理是什么我在这就不写了, 毕竟会看我这文章的人都是已经知道了的.
  本文贴的代码均为Python, 使用其他编程语言的人可以看注释. 为了简单, 只会说大概思路和关键性代码, 细节自行搞定.
  本文讲的是要实现一个爬虫, 所以不会跟协议文档那么严格. 只要保证你能正确请求,回应即可. 用软件开发的一句话来说: 只要接口一致, 管你内部细节代码是怎么写的.
  第一步, 构建自己的路由表, 这里涉及到大量Python代码, 请深呼吸:
  在构建自己的路由表之前, 得写两个辅助函数, 后面会用到:
  from hashlib import sha1
  from random import randint
  def node_id():
  """
  把爬虫"伪装"成正常node, 一个正常的node有ip, port, node ID三个属性, 因为是基于UDP协议,
  所以向对方发送信息时, 即使没"明确"说明自己的ip和port时, 对方自然会知道你的ip和port,
  反之亦然. 那么我们自身node就只需要生成一个node ID就行, 协议里说到node ID用sha1算法生成,
  sha1算法生成的值是长度是20 byte, 也就是20 * 8 = 160 bit, 正好如DHT协议里说的那范围: 0 至 2的160次方,
  也就是总共能生成1461501637330902918203684832716283019655932542976个独一无二的node.
  ok, 由于sha1总是生成20 byte的值, 所以哪怕你写SHA1(20)或SHA1(19)或SHA1("I am a 2B")都可以,
  只要保证大大降低与别人重复几率就行. 注意, node ID非十六进制,
  也就是说非FF5C85FE1FDB933503999F9EB2EF59E4B0F51ECA这个样子, 即非hash.hexdigest().
  """
  hash = sha1()
  s = ""
  for i in range(20):
  s += chr(randint(0, 255))
  hash.update(s)
  return hash.digest()
  def intify(nid):
  """这是一个小工具, 把一个node ID转换为数字. 后面会频繁用到."""
  assert len(nid) == 20
  return long(nid.encode('hex'), 16) #先转换成16进制, 再变成数字
  协议里说道, table里有bucket, bucket里有node, 每个bucket有K个node, 目前K=8, 即每个bucket有8个node. 由于table范围是0到2的160次方, 那么一个table最多能有(2的160次方)/K那么多的bucket.
  OK, 按照OOP编程思想来说, 那么肯定会有table, bucket, node这3个类, 无OOP的, 自己看着办.
  由于是基于Kademila而写, 所以我习惯上把这三个类名变为KTable, KBucket, KNode:

你可能感兴趣的:(用Python教你如何“养”一只DHT爬虫)