我想(快速)将程序/脚本放在一起以从 .torrent 文件中读取文件集。然后我想使用该设置从特定目录中删除任何不属于 torrent 的文件。
关于从 .torrent 文件中读取此索引的便捷库有什么建议吗?虽然我不反对它,但我不想为了这个简单的目的深入研究 bittorrent 规范并从头开始滚动大量代码。
我对语言没有偏好。
我想(快速)将程序/脚本放在一起以从 .torrent 文件中读取文件集。然后我想使用该设置从特定目录中删除任何不属于 torrent 的文件。
关于从 .torrent 文件中读取此索引的便捷库有什么建议吗?虽然我不反对它,但我不想为了这个简单的目的深入研究 bittorrent 规范并从头开始滚动大量代码。
我对语言没有偏好。
我会使用 rasterbar 的libtorrent,它是一个小而快的 C++ 库。
要遍历文件,您可以使用torrent_info类(begin_files()、end_files())。
libtorrent还有一个python 接口:
import libtorrent
info = libtorrent.torrent_info('test.torrent')
for f in info.files():
print "%s - %s" % (f.path, f.size)
Effbot 已回答您的问题。以下是从 .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"])
这是上面康斯坦丁回答的代码,稍作修改以处理种子文件名中的 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"])
来自原始 Mainline BitTorrent 5.x 客户端 ( http://download.bittorrent.com/dl/BitTorrent-5.2.2.tar.gz ) 的 bencode.py 将为您提供 Python 中的参考实现。
它对 BTL 包有导入依赖,但很容易删除。然后,您将查看 bencode.bdecode(filecontent)['info']['files']。
扩展上述想法,我做了以下工作:
~> 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
希望这可以帮助某人:)