2009-01-02 13 views
11

Quiero (rápidamente) poner un programa/script juntos para leer el conjunto de archivos de un archivo .torrent. Quiero utilizar ese conjunto para eliminar cualquier archivo de un directorio específico que no pertenezca al torrente.Lectura del conjunto de archivos de un torrent

¿Alguna recomendación sobre una biblioteca útil para leer este índice del archivo .torrent? Aunque no me opongo, no quiero profundizar en las especificaciones de Bittorrent y rodar una carga de código desde cero para este simple propósito.

No tengo preferencia en el idioma.

Respuesta

16

Effbot has your question answered. Aquí está el código completo para leer la lista de archivos desde el archivo .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

Tiene algún problema de Unicode, pero funciona :) – xvan

2

bencode.py del cliente original original de BitTorrent 5.x (http://download.bittorrent.com/dl/BitTorrent-5.2.2.tar.gz) le daría casi la implementación de referencia en Python.

Tiene una dependencia de importación en el paquete BTL pero es trivialmente fácil de eliminar. Luego vería bencode.bdecode (filecontent) ['info'] ['files'].

+0

esto sólo dará la capacidad de bencode y cuerdas bdecode, ¿verdad? Pero no se sabe dónde comienzan y finalizan las cadenas de conjunto de archivos codificadas. es decir, después de los metadatos bencoded y antes del bloque binario – Cheekysoft

+3

Los objetos raíz y de información son ambos diccionarios (mapeos). No hay un orden inherente de los metadatos del archivo y las cadenas de suma de verificación binarias, excepto que por convención los diccionarios se envían en orden de nombre de clave. No necesita preocuparse por el orden de almacenamiento, solo aspire todo el diccionario. – bobince

19

Utilizaría la barra de trama libtorrent que es una pequeña y rápida biblioteca de C++.
Para iterar sobre los archivos, puede usar la clase torrent_info (begin_files(), end_files()).

También hay un python interface para libtorrent:

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

Ampliando las ideas anteriores, hice lo siguiente:

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

Querrá para establecer permisos correctamente para hacer el script ejecutable de la shell:

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

Espero que esto ayude a alguien :)

0

Aquí está el código de la respuesta de Constantino anterior, ligeramente modificado para manejar caracteres Unicode en nombres de archivos Torrent y nombres de archivo de conjunto de archivos de información torrente:

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