1. 程式人生 > >Python邊學邊用--BT客戶端實現之BitTorrent檔案解析

Python邊學邊用--BT客戶端實現之BitTorrent檔案解析

複製程式碼
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'])
複製程式碼