2009-01-02 38 views
11

Tôi muốn (nhanh chóng) đặt một chương trình/tập lệnh cùng nhau để đọc tập tin từ tệp .torrent. Tôi muốn sau đó sử dụng thiết lập để xóa bất kỳ tập tin từ một thư mục cụ thể mà không thuộc về torrent.Đọc tập tin từ torrent

Bất kỳ đề xuất nào về thư viện tiện dụng để đọc chỉ mục này từ tệp .torrent? Trong khi tôi không phản đối nó, tôi không muốn đào sâu vào thông số bittorrent và lăn một tải mã từ đầu cho mục đích đơn giản này.

Tôi không có tùy chọn ngôn ngữ.

Trả lời

16

Effbot has your question answered. Đây là mã hoàn chỉnh để đọc danh sách các tập tin từ tập tin .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"]) 
+0

Có một số vấn đề unicode, nhưng hoạt động :) – xvan

2

bencode.py từ máy khách BitTorrent 5.x chính Dòng chính (http://download.bittorrent.com/dl/BitTorrent-5.2.2.tar.gz) sẽ cung cấp cho bạn khá nhiều việc triển khai tham chiếu trong Python.

Nó có sự phụ thuộc vào gói BTL nhưng dễ tháo gỡ. Sau đó, bạn sẽ xem bencode.bdecode (filecontent) ['info'] ['files'].

+0

chỉ cung cấp khả năng bencode và chuỗi bdecode, đúng không? Nhưng không có kiến ​​thức về nơi các chuỗi tập tin bencoded thực sự bắt đầu và kết thúc. tức là sau siêu dữ liệu được mã hoá và trước khối nhị phân – Cheekysoft

+3

Đối tượng gốc và thông tin là cả hai từ điển (ánh xạ). Không có thứ tự vốn có của siêu dữ liệu tệp và chuỗi kiểm tra nhị phân, ngoại trừ các từ điển quy ước là đầu ra theo thứ tự tên khóa. Bạn không cần phải lo lắng về chính mình với thứ tự lưu trữ, chỉ cần hút toàn bộ từ điển vào. – bobince

19

Tôi sẽ sử dụng libtorrent của rasterbar là thư viện C++ nhỏ và nhanh.
Để lặp qua các tệp bạn có thể sử dụng lớp torrent_info (begin_files(), end_files()).

Ngoài ra còn có một python interface cho libtorrent:

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

Mở rộng trên những ý tưởng trên, tôi đã làm như sau:

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

Bạn sẽ muốn để thiết lập quyền một cách thích hợp để làm cho kịch bản shell thực thi:

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

Hy vọng điều này sẽ giúp người :)

0

Đây là mã từ câu trả lời của Constantine ở trên, hơi sửa đổi để xử lý các ký tự Unicode trong tên tệp torrent và tên tệp fileset trong thông tin torrent:

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"]) 
Các vấn đề liên quan