您的位置:首页 > 编程语言 > Python开发

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

2014-02-27 15:26 344 查看
废话少说, 直接上菜.

  我假设你了解:

  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:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: