iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python边学边用--BT客户端实现之
  • 811
分享到

Python边学边用--BT客户端实现之

客户端边学Python 2023-01-31 02:01:22 811人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

BitTorrent文件使用bencode编码,其中包括了4种数据类型: 'd' 开头表示是dict类型,'e'表示结束 'l' (小写字母L)开头表示是list类型,'e'表示结束 'i'开头表示是integer类型,'e'表示结束,可

BitTorrent文件使用bencode编码,其中包括了4种数据类型:

'd' 开头表示是dict类型,'e'表示结束

'l' (小写字母L)开头表示是list类型,'e'表示结束

'i'开头表示是integer类型,'e'表示结束,可以表示负数

以数字开头表示string类型,数字为string长度,长度与string内容以':'分割

默认所有text类型的属性为utf-8编码,但是大多数BitTorrent包含codepage 和 encoding属性,指定了text的编码格式

BitTorrent的标准参见:Http://www.bittorrent.org/beps/bep_0003.html

以下是自己写的python实现,初学Python,代码写起来还都是C/C++风格,慢慢改进吧。

 

 torrent_file.py
复制代码
import os
from datetime import tzinfo
from datetime import datetime

import bcodec

_READ_MAX_LEN = -1

class BTFORMatError(BaseException):
    pass
    
class TorrentFile(object):
    
    __metainfo = {}
    __file_name = ''
    
    def read_file(self, filename):
        
        torrent_file = open(filename, 'rb')
        data = torrent_file.read(_READ_MAX_LEN)
        torrent_file.close()
        
        data = list(data)
        metainfo = bcodec.bdcode(data)
        if metainfo and type(metainfo) == type({}):
            self.__file_name = filename
            self.__metainfo = metainfo
        else:
            raise BTFormatError()
           
    def __is_singlefile(self):
        return 'length' in self.__metainfo.keys()
    
    def __decode_text(self, text):
        encoding = 'utf-8'
        resultstr = ''
        if self.get_encoding():
            encoding = self.get_encoding()
        elif self.get_codepage():
            encoding = 'cp' + str(self.get_codepage())
        if text:
            try:
                resultstr = text.decode(encoding=encoding)
            except ValueError:
                return text
        else:
            return None
        return resultstr
    
    def __get_meta_top(self, key):
        if key in self.__metainfo.keys():
            return self.__metainfo[key]
        else:
            return None
    def __get_meta_info(self,key):
        meta_info = self.__get_meta_top('info')
        if meta_info and key in meta_info.keys():
                return meta_info[key]
        return None
    
    def get_codepage(self):
        return self.__get_meta_top('codepage')
    def get_encoding(self):
        return self.__get_meta_top('encoding')
    
    def get_announces(self):
        announces = []
        ann = self.__get_meta_top('announce')
        if ann:
            ann_list = []
            ann_list.append(ann)
            announces.append(ann_list)
        announces.append(self.__get_meta_top('announce-list'))
        return announces
    
    def get_publisher(self):
        return self.__decode_text(self.__get_meta_top('publisher'))
    def get_publisher_url(self):
        return self.__decode_text(self.__get_meta_top('publisher-url'))
    
    def get_creater(self):
        return self.__decode_text(self.__get_meta_top('created by'))
    def get_creation_date(self):
        utc_date = self.__get_meta_top('creation date')
        if utc_date is None:
            return utc_date
        creationdate = datetime.utcfromtimestamp(utc_date)
        return creationdate
    def get_comment(self):
        return self.__get_meta_top('comment')
          
    def get_nodes(self):
        return self.__get_meta_top('nodes')
    
    def get_piece_length(self):
        return self.__get_meta_info('piece length')
    
    def get_files(self):
        
        files = []
        pieces = self.__get_meta_info('pieces')
        name = self.__decode_text(self.__get_meta_info('name'))
        piece_length = self.get_piece_length()
        
        if not pieces or not name:
            return files
        
        if self.__is_singlefile():
            file_name = name
            file_length = self.__get_meta_info('length')
            if not file_length:
                return files
            
            pieces_num = file_length/piece_length
            if file_length % piece_length:
                pieces_num = int(pieces_num) + 1
            if 20*pieces_num > len(pieces):
                return  files
                           
            file_pieces = []
            i = 0
            pn = 0
            while pn < pieces_num:
                file_pieces.append(pieces[i:i+20])
                i += 20
                pn += 1
            
            files.appen({'name':[file_name], 'length':file_length, 'peaces':file_pieces})
            return files
        

        folder = name
        meta_files = self.__get_meta_info('files')
        if not meta_files:
            return files
        
        total_length = 0
        for one_file in self.__get_meta_info('files'):
            
            file_info = {}
            path_list = []
            path_list.append(folder)
                        
            if 'path' not in one_file.keys():
                break
            for path in one_file['path']:
                path_list.append(self.__decode_text(path))
            file_info['name'] = path_list
            
            if 'length' not in one_file.keys():
                break
            
            file_info['length'] =  one_file['length']
            
            piece_index = int(total_length / piece_length)
            total_length += one_file['length']
            pieces_num = int(total_length / piece_length) - piece_index
            pieces_num = int(file_info['length']/piece_length)
            
            if total_length % piece_length:
                pieces_num += 1
            
           # print  (piece_index+pieces_num)*20, len(pieces),pieces_num,file_info['length'], self.get_piece_length()
            
            if (piece_index+pieces_num)*20 > len(pieces):
                break
            
            file_info['pieces'] = []
            
            pn = 0
            while pn < pieces_num:
                file_info['pieces'].append(pieces[piece_index*20:piece_index*20+20])
                pn += 1

            files.append(file_info)
            
        return files
    
if __name__ == '__main__':
    #filename = r".\huapi2.torrent"
    #filename = r".\mh5t3tJ0EC.torrent"
    filename = r".\huapi2.1.torrent"   
    torrent = TorrentFile()

    print "begin to read file"
    try:
        torrent.read_file(filename)
    except (IOError,BTFormatError), reason:
        print "Read bittorrent file error! Error:%s" %reason
     
    print "end to read file"

    print "announces: " , torrent.get_announces() 
    print "peace length:", torrent.get_piece_length()
    print "code page:" , torrent.get_codepage()
    print "encoding:" , torrent.get_encoding()
    print "publisher:" ,torrent.get_publisher()
    print "publisher url:", torrent.get_publisher_url()
    print "creater:" , torrent.get_creater()
    print "creation date:", torrent.get_creation_date()
    print "commnent:", torrent.get_comment()
    print "nodes:", torrent.get_nodes()
    torrent.get_files()
    for one_file in torrent.get_files():
        print 'file name:', '\\'.join(one_file['name'])
        print 'file length:', one_file['length']
        print 'pieces:', list(one_file['pieces'])
复制代码
bcodec.py
复制代码
  1 '''
  2 Created on 2012-9-30
  3 
  4 @author: ddt
  5 '''
  6 def bdcode(data):
  7     data = list(data)
  8     return _read_chunk(data)
  9     
 10 def _read_chunk(data):
 11     
 12     chunk = None
 13     
 14     if len(data) == 0:
 15         return chunk
 16     
 17     leading_chr = data[0]
 18                      
 19     if leading_chr.isdigit():
 20         chunk = _read_string(data)
 21     elif leading_chr == 'd':
 22         chunk = _read_dict(data)
 23     elif leading_chr == 'i':
 24         chunk = _read_integer(data)
 25     elif leading_chr == 'l':
 26         chunk = _read_list(data)
 27 
 28     #print leading_chr, chunk
 29     return chunk
 30                            
 31 def _read_dict(data):
 32     
 33     if  len(data) == 0 or data.pop(0) != 'd': 
 34         return None
 35     
 36     chunk = {} 
 37     while len(data) > 0 and data[0] != 'e':
 38         
 39         key = _read_chunk(data)
 40         value = _read_chunk(data)
 41         
 42         if key and value and type(key) == type(''):
 43             chunk[key] = value
 44         else:
 45             return None
 46         
 47     if len(data) == 0 or data.pop(0) != 'e':
 48         return None
 49     
 50     return chunk
 51 
 52 def _read_list(data):
 53 
 54     if  len(data) == 0 or data.pop(0) != 'l': 
 55         return None
 56     
 57     chunk = []
 58     while len(data) > 0 and data[0] != 'e':
 59         value = _read_chunk(data)
 60         if value:
 61             chunk.append(value)
 62         else:
 63             return None
 64         
 65     if len(data) == 0 or data.pop(0) != 'e': 
 66         return None
 67 
 68     return chunk
 69 
 70 def _read_string(data):
 71     
 72     str_len = ''
 73     while len(data) > 0 and data[0].isdigit():
 74         str_len +=  data.pop(0)
 75     
 76     if len(data) == 0 or data.pop(0) != ':':
 77         return None
 78     
 79     str_len = int(str_len)
 80     if str_len > len(data):
 81         return None
 82     
 83     value = data[0:str_len]
 84     del data[0:str_len]
 85     return ''.join(value)
 86 
 87 def _read_integer(data):
 88    
 89     integer = ''
 90     if len(data) < len('i2e') or data.pop(0) != 'i': 
 91         return None
 92     
 93     sign = data.pop(0)
 94     if sign != '-' and not sign.isdigit():
 95         return None
 96     integer += sign
 97     
 98     while len(data) > 0 and data[0].isdigit():
 99         integer += data.pop(0)
100     
101     if len(data) == 0 or data.pop(0) != 'e':
102         return None
103 
104     return  int(integer)
复制代码

--结束END--

本文标题: Python边学边用--BT客户端实现之

本文链接: https://www.lsjlt.com/news/186402.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python边学边用--BT客户端实现之
    BitTorrent文件使用bencode编码,其中包括了4种数据类型: 'd' 开头表示是dict类型,'e'表示结束 'l' (小写字母L)开头表示是list类型,'e'表示结束 'i'开头表示是integer类型,'e'表示结束,可...
    99+
    2023-01-31
    客户端 边学 Python
  • python实现ssh客户端
    以下程序均来自《Python.UNIX和Linux系统管理指南》ssh有两种登陆方式,一种是使用用户名、密码方式,另一种是使用加密,不再使用密码使用用户名、密码方式,前提是曾经ssh登陆过远程机器,在用户目录的.ssh目录下的known_h...
    99+
    2023-01-31
    客户端 python ssh
  • Python MQTT客户端实现
    如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:12951803 1.安装paho-mqtt 使用Python Package Index (PyPi) pip install ...
    99+
    2023-01-31
    客户端 Python MQTT
  • python利用socket实现客户端和服务端之间进行通信
    目录一、socketsocket通信的条件:IP和端口形象比喻二、客户端实现过程三、服务器实现过程四、演示五、实现持续通信过程前言: 今天教大家通过Python进行Socket网络编...
    99+
    2024-04-02
  • python中如何实现客户端通信
    这篇文章将为大家详细讲解有关python中如何实现客户端通信,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1、实现流程创建一套接字。用connect()函数连接到服务器。使用sendall()向服务器发送...
    99+
    2023-06-15
  • Python基于socket实现TCP客户端和服务端
    目录一、基于socket实现的TCP客户端二、基于socket实现的TCP服务端三、socket实现的多任务版TCP服务端1、面向对象版本一、基于socket实现的TCP客户端 im...
    99+
    2024-04-02
  • 怎么用golang实现rtsp客户端
    近年来,视频成为了信息传递的一个重要形式,也因此而催生了一种被广泛应用的视频流协议——RTSP(Real Time Streaming Protocol,实时流协议)。相比于HTTP,RTSP获得了更高的传输效率和更低的延迟,加上其支持多种...
    99+
    2023-05-14
  • Python如何实现MySQL客户端操作库
    这篇文章主要介绍了Python如何实现MySQL客户端操作库,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获。下面让小编带着大家一起了解一下。PyMySQL 是一个纯 Python...
    99+
    2024-04-02
  • Java聊天室之实现客户端群聊功能
    目录一、题目描述二、解题思路三、代码详解一、题目描述 题目实现:不同的客户端之间需要进行通信,一个客户端与其他的多个客户端进行通信,实现群聊功能。 实现一个客户端与其他多个客户端进行...
    99+
    2022-11-13
    Java实现聊天室 Java 聊天室 Java 客户端群聊
  • Python中怎么实现服务端与客户端连接
    本篇内容主要讲解“Python中怎么实现服务端与客户端连接”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python中怎么实现服务端与客户端连接”吧!服务端我们使用 socket 模块的&nbs...
    99+
    2023-06-08
  • python客户端与服务器端通信怎么实现
    Python客户端与服务器端通信可以通过套接字(socket)实现。1. 服务器端首先需要创建一个套接字,并绑定到指定的IP地址和端...
    99+
    2023-09-08
    python 服务器
  • Python如何利用IMAP实现邮箱客户端功能
    目录概述什么是IMAP?IMAP和POP有什么区别?如何设置IMAP服务的SSL加密方式?涉及知识点示例效果图核心代码邮箱设置总结概述 在日常工作生活中,都是利用个人或公司的...
    99+
    2024-04-02
  • python使用UDP实现客户端和服务器对话
    目录UDP 客户端UDP 服务端注意事项UDP 客户端 一个使用UDP协议的客户端示例代码,用于实现连续对话。请注意,UDP是无连接协议,因此在实现连续对话时需要特别小心。 以下是...
    99+
    2023-03-23
    python UDP对话 python UDP客户端服务器
  • Java聊天室之实现聊天室客户端功能
    目录一、题目描述二、解题思路三、代码详解一、题目描述 题目实现:实现聊天室客户端。运行程序,用户登录服务器后,可以从用户列表中选择单个用户进行聊天,也可以选择多个用户进行聊天。 二、...
    99+
    2022-11-13
    Java实现聊天室 Java 聊天室 Java 客户端
  • Python培训教程:基于Python的ModbusTCP客户端实现
    Python培训教程:基于Python的ModbusTCP客户端实现Modbus协议是由Modicon公司(现在的施耐德电气Schneider Electric)推出,主要建立在物理串口、以太网TCP/IP层之上,目前已经成为工业领域通信协...
    99+
    2023-06-02
  • Python基于socket怎么实现TCP客户端和服务端
    这篇文章主要讲解了“Python基于socket怎么实现TCP客户端和服务端”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python基于socket怎么实现TCP客户端和服务端”吧!一、基...
    99+
    2023-06-30
  • PHP+Socket系列之实现客户端与服务端数据传输
    本篇文章给大家带来了关于php+socket的相关知识,其中主要介绍了什么是socket?php+socket如何实现客户端与服务端数据传输?感兴趣的朋友下面一起来看一下,希望对大家有帮助。socket介绍实现网络进程之间的通信,几乎所有应...
    99+
    2023-05-14
    php socket
  • Modbus协议及基于Python的ModbusTCP客户端实现
    Modbus 协议是由 Modicon 公司(现在的施耐德电气 Schneider Electric )于1979年为使用可编程逻辑控制器(PLC)通信而推出,主要建立在物理串口、以太网 TCP/IP...
    99+
    2023-09-23
    python 开发语言
  • Python socket怎么实现服务端和客户端数据传输
    今天小编给大家分享一下Python socket怎么实现服务端和客户端数据传输的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了...
    99+
    2023-06-30
  • python如何使用UDP实现客户端和服务器对话
    这篇文章主要介绍“python如何使用UDP实现客户端和服务器对话”,在日常操作中,相信很多人在python如何使用UDP实现客户端和服务器对话问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”python如何使...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作