用Python教你如何“养”一只DHT爬虫
来源:互联网 发布:软件测试阶段划分 编辑:程序博客网 时间:2024/05/01 16:35
废话少说, 直接上菜.
我假设你了解:
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:
我假设你了解:
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:
0 0
- 用Python教你如何“养”一只DHT爬虫
- 用Python教你如何“养”一只DHT爬虫
- 一只爬虫带你看世界【1】
- 一只爬虫带你看世界【2】
- 一只爬虫带你看世界【3】
- 一只爬虫带你看世界【4】
- 一只爬虫带你看世界【6】
- 一只爬虫带你看世界【7】
- 一只爬虫带你看世界【8】
- 一只爬虫带你看世界【9】
- 一只爬虫带你看世界【10】
- 一只爬虫带你看世界【11】
- 第一只python小爬虫
- 一只爬虫的产生
- 教你分分钟学会用python爬虫框架Scrapy
- DHT网络爬虫
- DHT网络爬虫
- DHT爬虫 原理分析
- Python 设计模式——用模式改善软件设计
- 手机常识(二)
- 用C++语言做Linux开发工具之粘合剂Makefile
- 程序中抛出异常
- c
- 用Python教你如何“养”一只DHT爬虫
- hdu3594 强连通 tarjan
- 并查集带删除操作uva11987(好)
- Linux实时内存数据库eXtremeDB性能
- Android源码的git下载地址
- solr教程,值得刚接触搜索开发人员一看
- exit,_exit.atexit,return,strerror 函数
- 关闭后台程序的必要
- linux下小企鹅中文输入法安装----笛风读书笔记系列