欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

BT 下载和使用 python 的简易自建种子搜索引擎

最编程 2024-06-07 16:12:35
...
  • 之前网络上已经有不少开源的dht种子搜索的python代码。比较有名的是手撕包菜种子搜索引擎网站的python代码(开源在github上),但在项目介绍里的相关博文链接已经失效,来看源码,关键的种子嗅探爬虫都在目录workers下。而最重要的info_hash码(即种子唯一标识码)爬虫为simdht_worker.py文件。主要使用了CreateChen/simDownloader项目中的代码。而与fanpei91/simDHT基本一致。

  • simDHT最简单易读,单线程,建议先阅读。思路是伪装成一个DHT节点。初始化时,给自己随机生成一个20位的ID,通过大的tracker服务器(如router.bittorrent.com)获取其他节点的地址信息(find_node操作),进入DHT网络,利用KRPC协议传输B编码的字典信息,即DHT查询信息(4种,见bep05),与DHT网络中的其他节点互相通信。

  • 由于在初始化时已经从大的Tracker服务器获取了一定量的节点信息,接下来向这些节点发送find_node请求,参数中:1. 将自己的ID构造成被请求节点的(按异或)相近ID(代码为get_neighbor函数,如向ID为A的节点发送find_node请求,将自己ID构造成A[:end]+X[:20-end],也就是构造的ID的前end位与A节点ID相同,而后(20-end)位随意,end取10-15,这样伪装成A的周边节点,而按规则每个节点对周边节点的感知能力要好,它很可能将你记录在它的路由表上,使得它自己或引导其他节点主动向你通信),2. 要查找的节点ID随机生成即可。大部分随机生成的节点ID是不可能直接查找到的,那么被请求节点会返回另一批节点信息,在接受到返回的新节点信息后,向新节点继续发送请求,依此迭代进行,目的就是不断地和其他节点混脸熟,即auto_send_find_node函数。这里维护了一个有限长的双端队列(deque)存储节点。节点不断从队首取出,向其发送find_node请求,收到的应答中的新节点不断被添加到队尾。如果队列为空,则重新初始化一下。

  • 一旦和越来越多的节点混脸熟了,就会有不断的查询请求从其他节点发送过来,作为爬虫,只要处理get_peersannounce_peer请求就够了。get_peers是一个节点向另一个节点发出的查询与info_hash相关的下载者信息,包含的info_hash参数就是我们需要的种子的info_hash,但是,get_peers中包含的info_hash对应的种子可能已经失效或者难连接上,不采用。这时我们要回应它,关键是给他一个token(自己以一定方式生成,不固定,用来校验的)与一个空的nodes参数(我们没有种子的下载者信息,按协议应当返回最有可能有该信息的K个节点给查询节点,但是也可以返回空值)。

  • 这个向我查询的节点如果最终(通过其他节点)找到了资源(其他下载者,即peer),而控制该节点的下载者开始下载资源了,该节点很可能向我发送announce_peer消息,该消息告诉我们它的下载者信息。消息参数中的info_hash和下载者地址就是我们需要的,同时要验证参数中的token是否就是我之前发送给该节点的,保证真实性。返回给它的消息只是自己节点的ID。

  • 对于其他节点发送给自己的pingfind_node查询不用管即可。(可以思考,对于这两种查询是否有某种响应方式可以给自己带来更多收益)

  • 以上就是simDHT的内容了

  • 而进一步,光有种子的info_hash码还不够,能直接拿到种子的元信息就好了。这就是手撕包菜里的simMetadata.py实现的通过bep9拓展协议从之前announce_peer消息中的下载者那里获取到种子的元信息。

  • 此外,wuzhenda/simDHT0x0d/dhtfck实现了K桶等,有一定注释和他个人的理解,但作为爬虫可能并不需要这个功能,还有NanYoMyDHT-woodworm 以及DHT-simDHT增加了一点新特性,可以浏览下。

  • 以上都是python2的,基于python3的异步IO特性的DHT爬虫并不多,有whtsky/maga,而zrools基于maga,写了asyncDHT,并有图文并茂的博文,DHT爬虫:18.4GB种子分析小记值得一看

  • 另外,B编码的编解码库:python2使用的多为bencodepip install bencode。python可以使用的有bcodingpip install bcodingbetter-bencodepip install better-bencode

  • 实现bttorrent客户端的python库libtorrent,貌似只支持python2,libtorrent库的使用可以看: 从磁力链获取种子文件 - Magnet_To_Torrent2.py的43行到67行(其他都是次要代码)。还可以参考creating daemon using Python libtorrent for fetching meta data of 100k+ torrents。(注:还发现有个Simple libtorrentpip install SimpleTorrentStreaming

  • 回到文章开头使用的magneticod,它使用了python3提供的asyncio机制。主要嗅探代码部分magneticod/dht.py中的思路和之前介绍的simDHT基本相似,有点不同的是,它维护了一个自己的节点字典self._routing_table,每一轮(间隔一秒)向里面所有节点发出find_node查询然后清空字典,如果收到自己发出的find_node请求的响应时,字典中的所有节点数超出self.__n_max_neighbours数则不再加入新节点。(主要函数为async def tick_periodically(self),这个机制还有可以斟酌的地方)

  • 在大的异步结构上继承了官方的asyncio.DatagramProtocol,可以先看官方样例UDP echo client protocolUDP echo server protocol,很简明,数据的发送和接收都封装好了,并且可以通过pause_writing和resume_writing控制流量。

  • 在处理announce_peer消息时,用asyncio.ensure_future新建异步任务来抓取种子元信息,且对同一个种子元信息的多个抓取进行管理。

  • 在数据存储方面使用了python自带的sqlite,不用安装就能使用,很方便。数据库存储位置管理使用了appdirs库。

  • 作者表示近期会有一次大的重构,让我们拭目以待。