2009-01-02 10 views
11

मैं एक .torrent फ़ाइल से फाइलसेट पढ़ने के लिए एक प्रोग्राम/स्क्रिप्ट को एक साथ रखना चाहता हूं। मैं तब उस सेट का उपयोग उस विशिष्ट निर्देशिका से किसी भी फाइल को हटाने के लिए करना चाहता हूं जो धार से संबंधित नहीं है।एक धार से फाइलसेट को पढ़ना

इस इंडेक्स को .torrent फ़ाइल से पढ़ने के लिए एक आसान लाइब्रेरी पर कोई सिफारिशें? जब तक मैं इस पर कोई विरोध नहीं करता हूं, मैं इस सरल उद्देश्य के लिए स्क्रैच से कोड लोड करने के लिए बिटोरेंट स्पेक में गहरी खुदाई नहीं करना चाहता हूं।

मुझे भाषा पर कोई वरीयता नहीं है।

उत्तर

16

Effbot has your question answered। यहाँ धार फ़ाइल (अजगर 2.4+) से फ़ाइलों की सूची पढ़ने के लिए पूरा कोड है:

~> cd ~/bin 

~/bin> ls torrent* 
torrent-parse.py torrent-parse.sh 

~/bin> cat torrent-parse.py 
# torrent-parse.py 
import sys 
import libtorrent 

# get the input torrent file 
if (len(sys.argv) > 1): 
    torrent = sys.argv[1] 
else: 
    print "Missing param: torrent filename" 
    sys.exit() 
# get names of files in the torrent file 
info = libtorrent.torrent_info(torrent); 
for f in info.files(): 
    print "%s - %s" % (f.path, f.size) 

~/bin> cat torrent-parse.sh 
#!/bin/bash 
if [ $# -lt 1 ]; then 
    echo "Missing param: torrent filename" 
    exit 0 
fi 

python torrent-parse.py "$*" 

आप चाहेंगे कि:

import re 

def tokenize(text, match=re.compile("([idel])|(\d+):|(-?\d+)").match): 
    i = 0 
    while i < len(text): 
     m = match(text, i) 
     s = m.group(m.lastindex) 
     i = m.end() 
     if m.lastindex == 2: 
      yield "s" 
      yield text[i:i+int(s)] 
      i = i + int(s) 
     else: 
      yield s 

def decode_item(next, token): 
    if token == "i": 
     # integer: "i" value "e" 
     data = int(next()) 
     if next() != "e": 
      raise ValueError 
    elif token == "s": 
     # string: "s" value (virtual tokens) 
     data = next() 
    elif token == "l" or token == "d": 
     # container: "l" (or "d") values "e" 
     data = [] 
     tok = next() 
     while tok != "e": 
      data.append(decode_item(next, tok)) 
      tok = next() 
     if token == "d": 
      data = dict(zip(data[0::2], data[1::2])) 
    else: 
     raise ValueError 
    return data 

def decode(text): 
    try: 
     src = tokenize(text) 
     data = decode_item(src.next, src.next()) 
     for token in src: # look for more tokens 
      raise SyntaxError("trailing junk") 
    except (AttributeError, ValueError, StopIteration): 
     raise SyntaxError("syntax error") 
    return data 

if __name__ == "__main__": 
    data = open("test.torrent", "rb").read() 
    torrent = decode(data) 
    for file in torrent["info"]["files"]: 
     print "%r - %d bytes" % ("/".join(file["path"]), file["length"]) 
+0

कुछ यूनिकोड समस्या है, लेकिन काम करता है :) – xvan

2

मूल मेनलाइन बिटटोरेंट 5.x क्लाइंट (http://download.bittorrent.com/dl/BitTorrent-5.2.2.tar.gz) से bencode.py आपको पायथन में संदर्भ कार्यान्वयन प्रदान करेगा।

इसकी बीटीएल पैकेज पर एक आयात निर्भरता है लेकिन इसे हटाने में काफी आसान है। फिर आप bencode.bdecode (filecontent) ['info'] ['files'] देखेंगे।

+0

यह केवल bdecode तार bencode के लिए और हालांकि, सही क्षमता दे सकता है? लेकिन बेंकोडेड फाइलसेट तार वास्तव में शुरू होने और समाप्त होने का कोई ज्ञान नहीं है। यानी bencoded मेटाडाटा के बाद और बाइनरी ब्लॉक – Cheekysoft

+3

से पहले रूट और जानकारी वस्तुओं दोनों शब्दकोश (मैपिंग) हैं। फ़ाइल मेटाडेटा और द्विआधारी चेकसम स्ट्रिंग का कोई अंतर्निहित क्रम नहीं है, सिवाय इसके कि सम्मेलन शब्दकोश कुंजी नाम क्रम में आउटपुट होते हैं। आपको स्टोरेज ऑर्डर के साथ खुद को चिंता करने की ज़रूरत नहीं है, बस पूरे शब्दकोश को चूसो। – bobince

19

मैं रास्टरबार के libtorrent का उपयोग करूंगा जो एक छोटी और तेज़ सी ++ लाइब्रेरी है।
फ़ाइलों पर पुन: प्रयास करने के लिए आप torrent_info कक्षा (start_files(), end_files()) का उपयोग कर सकते हैं।

libtorrent के लिए भी एक python interface नहीं है:

import libtorrent 
info = libtorrent.torrent_info('test.torrent') 
for f in info.files(): 
    print "%s - %s" % (f.path, f.size) 
1

ऊपर विचारों पर विस्तार, मैं निम्नलिखित किया अनुमतियाँ उचित रूप में निर्धारित करने के लिए खोल स्क्रिप्ट निष्पादन योग्य बनाने के लिए:

~/bin> chmod a+x torrent-parse.sh 

आशा इस मदद करता है किसी को :)

0

यहाँ ऊपर Constantine के जवाब से कोड, थोड़ा धार जानकारी में धार फ़ाइल नाम और फ़ाइलसेट फ़ाइल नाम में यूनिकोड वर्ण को संभालने के लिए संशोधित है:

import re 

def tokenize(text, match=re.compile("([idel])|(\d+):|(-?\d+)").match): 
    i = 0 
    while i < len(text): 
     m = match(text, i) 
     s = m.group(m.lastindex) 
     i = m.end() 
     if m.lastindex == 2: 
      yield "s" 
      yield text[i:i+int(s)] 
      i = i + int(s) 
     else: 
      yield s 

def decode_item(next, token): 
    if token == "i": 
     # integer: "i" value "e" 
     data = int(next()) 
     if next() != "e": 
      raise ValueError 
    elif token == "s": 
     # string: "s" value (virtual tokens) 
     data = next() 
    elif token == "l" or token == "d": 
     # container: "l" (or "d") values "e" 
     data = [] 
     tok = next() 
     while tok != "e": 
      data.append(decode_item(next, tok)) 
      tok = next() 
     if token == "d": 
      data = dict(zip(data[0::2], data[1::2])) 
    else: 
     raise ValueError 
    return data 

def decode(text): 
    try: 
     src = tokenize(text) 
     data = decode_item(src.next, src.next()) 
     for token in src: # look for more tokens 
      raise SyntaxError("trailing junk") 
    except (AttributeError, ValueError, StopIteration): 
     raise SyntaxError("syntax error") 
    return data 

n = 0 
if __name__ == "__main__": 
    data = open("C:\\Torrents\\test.torrent", "rb").read() 
    torrent = decode(data) 
    for file in torrent["info"]["files"]: 
     n = n + 1 
     filenamepath = file["path"]  
     print str(n) + " -- " + ', '.join(map(str, filenamepath)) 
     fname = ', '.join(map(str, filenamepath)) 

     print fname + " -- " + str(file["length"]) 
संबंधित मुद्दे