2009-01-02 67 views
11

我想(快速)將程序/腳本放在一起以從.torrent文件中讀取文件集。然後,我想使用該設置從特定目錄中刪除任何不屬於該種子文件的文件。從洪流中讀取文件集

對於從.torrent文件讀取該索引的便利庫的任何建議?雖然我不反對,但我不想深入研究BitTorrent規範,爲了這個簡單目的從頭開始編寫大量代碼。

我對語言沒有偏好。

回答

16

Effbot has your question answered。下面是完整的代碼來讀取文件從文件的.torrent(Python的2.4及以上)名單:

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"]) 
2

從原來的Mainline BitTorrent 5.x客戶端(http://download.bittorrent.com/dl/BitTorrent-5.2.2.tar.gz)的bencode.py會給你幾乎Python的參考實現。

它對BTL包有一個導入依賴性,但這很容易刪除。然後你會看到bencode.bdecode(filecontent)['info'] ['files']。

+0

這只是給儘管bencode和bdecode串吧的能力嗎? 但是不知道合編文件集字符串實際開始和結束的位置。即在經過編碼的元數據之後和二進制塊之前 – Cheekysoft 2009-01-02 13:11:28

+3

根和信息對象都是字典(映射)。文件元數據和二進制校驗和字符串沒有固有的排序順序,除了傳統字典以鍵名順序輸出。你不需要關心存儲順序,只需將整個字典吸入即可。 – bobince 2009-01-02 14:32:38

19

我會使用rasterbar的libtorrent這是一個小而快的C++庫。
要遍歷文件,您可以使用torrent_info類(begin_files(),end_files())。

還有一個python interface爲libtorrent:

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

擴大在上面的思路,我做了以下內容:

~> 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 "$*" 

你會想適當地設置權限,使shell腳本可執行:

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

希望這可以幫助別人:)

0

以下是上述康斯坦丁的答案代碼,稍加修改,以處理洪流信息洪流中的文件名和文件集的文件名Unicode字符:

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"])