Spring Cloud + Netty 打造分布式可集群部署的 DHT 磁力爬虫(开源)

演示地址: https://dodder.cc

三年前,照着 Python 版的 DHT 网络爬虫用 Java 重写了一遍,当时大学还未毕业,写出来的代码比较杂乱,数据跑到 1600 万的时候就遇到了瓶颈,最近辞职了想学习一波 Spring Cloud 微服务开发,于是就有了现在这个项目。

学习一门新的技术总是枯燥无味的,不知道大家有没有这样的感觉,照着官方文档或者 Demo 去敲代码,不仅印象不深刻容易忘记,而且特别无聊,所以对于我个人而言,在学习一门新技术时喜欢去找一个自己感兴趣的实战场景,然后再进行学习实践,遇到不懂的再去 Google 或者看官方文档,而不是按部就班地买本书一页一页的全部看完,只有自己要用到什么的时候再去查相关的文档,这样子对应用场景以及技术要点才会更加深刻。

闲话不多说了,接下来谈谈 DHT 网络爬虫吧。

对于老湿鸡来说,到磁力搜索网站去搜索番号是他们获取资源的一种快速途径,对于这种网站,广告也是一大堆的,那么身为 IT 技术人,能不能自己来实现一个呢?

答案肯定是可以的,而且技术含量也不是特别高,但实现之前,Bittorrent 协议以及其 Wire Peer 扩展协议,还是必须要了解的,前者在官方文档还能详细找到,后者在维基百科上貌似已经被删掉了(官方文档里只有简单的介绍了,整个协议数据收发的流程已经没有了)。

参考协议:
http://www.bittorrent.org/bep...
http://www.bittorrent.org/bep...

除此之外,还需要熟悉 Torrent 种子文件里的结构信息,Bittorrent 协议以及 Torrent 种子文件信息大多都采用 bencode 编码,学习之前,可以先去了解一下这个编码,和 json 有点类似,不过也不是必要的,不用自己去实现,有现成的编解码库。

对前面的东西了解过后,再整理下整个爬取的流程:

使用 Netty 本地模拟一个 DHT 网络节点加入到 DHT 网络中去(即向启动节点发送 find_node 请求)

收到 find_node 回复解析出更多的 DHT 节点信息,向这些节点发送 find_node 节点(目的就是让更多的人知道自己,专业术语就是把自己的节点 ID 加入到对方的桶里,和推销自己差不多吧~)

那些收到 find_node 请求的节点,把我们的节点 ID 加入到桶里之后,它就会向我们发送 find_node、get_peers、announce_peer 请求。

对于其他节点发送给我们的请求,我们需要根据协议进行回复,否则对方会认为我们是个不活跃节点把我们从对方的桶里删除,并且不会发送 announce_peer 消息给我们

对于 get_peers 消息里的 info_hash 我们可以进行忽略,因为此时对方也是在查找对应 info_hash 的种子文件,只有收到 announce_peer 消息时的 info_hash 对我们才有用,因为它表示当前对方正在指定端口下载该种子文件的 metadata 信息。

根据 announce_peer 中的 info_hash 到指定 ip 端口使用 wire peer 扩展协议进行 metadata 数据的交换(即下载)

下载成功,解析出种子文件列表信息入库。

具体实现请参考我的开源项目: https://github.com/xwlcn/Dodder

代码如有问题,欢迎指正,仅供技术交流,切勿用作非法、商业用途。