在 Python 中使用 Libtorrent 下载多个 torrent 文件

Downloading Multiple torrent files with Libtorrent in Python

我正在尝试编写一个 Torrent 应用程序,它可以接收磁铁 link 列表,然后将它们一起下载。我一直在尝试阅读和理解 Libtorrent 上的文档,但我无法判断我的尝试是否有效。我设法能够将 SOCKS5 代理应用于 Libtorrent 会话并使用此代码下载单个磁铁 link:

import libtorrent as lt
import time
import os

ses = lt.session()
r = lt.proxy_settings()
r.hostname = "proxy_info"
r.username = "proxy_info"
r.password = "proxy_info"
r.port = 1080
r.type = lt.proxy_type_t.socks5_pw
ses.set_peer_proxy(r)
ses.set_web_seed_proxy(r)
ses.set_proxy(r)
t = ses.settings()
t.force_proxy = True
t.proxy_peer_connections = True
t.anonymous_mode = True
ses.set_settings(t)
print(ses.get_settings())
ses.peer_proxy()
ses.web_seed_proxy()
ses.set_settings(t)

magnet_link = "magnet"

params = {
"save_path": os.getcwd() + r"\torrents",
"storage_mode": lt.storage_mode_t.storage_mode_sparse,
"url": magnet_link
}

handle = lt.add_magnet_uri(ses, magnet_link, params)
ses.start_dht()

print('downloading metadata...')
while not handle.has_metadata():
    time.sleep(1)
    print('got metadata, starting torrent download...')
while handle.status().state != lt.torrent_status.seeding:
    s = handle.status()
    state_str = ['queued', 'checking', 'downloading metadata', 'downloading', 'finished', 'seeding', 'allocating']
    print('%.2f%% complete (down: %.1f kb/s up: %.1f kB/s peers: %d) %s' % (s.progress * 100, s.download_rate / 1000, s.upload_rate / 1000, s.num_peers, state_str[s.state]))
    time.sleep(5)

这太棒了,所有这些都可以通过单个 link 自行运行。我想做的是这样的:

def torrent_download(magnetic_link_list):
    for mag in range(len(magnetic_link_list)):
        handle = lt.add_magnet_uri(ses, magnetic_link_list[mag], params)

    #Then download all the files
    #Once all files complete, stop the torrents so they dont seed.

    return torrent_name_list

我不确定这是否在正确的轨道上,但一些建议会有所帮助。

更新:这就是我现在拥有的,在我的情况下效果很好

def magnet2torrent(magnet_link):
    global LIBTORRENT_SESSION, TORRENT_HANDLES
    if LIBTORRENT_SESSION is None and TORRENT_HANDLES is None:
        TORRENT_HANDLES = []
        settings = lt.default_settings()
        settings['proxy_hostname'] = CONFIG_DATA["PROXY"]["HOST"]
        settings['proxy_username'] = CONFIG_DATA["PROXY"]["USERNAME"]
        settings['proxy_password'] = CONFIG_DATA["PROXY"]["PASSWORD"]
        settings['proxy_port'] = CONFIG_DATA["PROXY"]["PORT"]
        settings['proxy_type'] = CONFIG_DATA["PROXY"]["TYPE"]
        settings['force_proxy'] = True
        settings['anonymous_mode'] = True

        LIBTORRENT_SESSION = lt.session(settings)

    params = {
        "save_path": os.getcwd() + r"/torrents",
        "storage_mode": lt.storage_mode_t.storage_mode_sparse,
        "url": magnet_link
        }

    TORRENT_HANDLES.append(LIBTORRENT_SESSION.add_torrent(params))


def check_torrents():
    global TORRENT_HANDLES
    for torrent in range(len(TORRENT_HANDLES)):
        print(TORRENT_HANDLES[torrent].status().is_seeding)

叫做"magnet links"(没有磁性)

在新版本的libtorrent中,添加磁铁的方法link是:

params = lt.parse_magnet_link(uri)
handle = ses.add_torrent(params)

这也让您有机会调整 add_torrent_params 对象,例如设置保存目录。

如果您要添加大量磁铁 links(或与此相关的常规 torrent 文件)并且想快速完成,更快的方法是使用:

ses.add_torrent_async(params)

该函数将立即 return 并且稍后可以在 add_torrent_alert 中拾取 torrent_handle 对象。

至于并行下载多个磁铁link,您添加它们的伪代码是正确的。您只想确保保存所有返回的 torrent_handle 对象,或者在完成添加后查询所有 Torrent 句柄(使用 ses.get_torrents())。在您的伪代码中,您似乎每次添加新的种子句柄时都会覆盖最后一个种子句柄。

您提出的退出条件是所有种子都已完成。最简单的方法就是用 handle.status().is_seeding 对它们进行轮询。即遍历您的 torrent 句柄列表并询问。请记住,对 status() 的调用需要往返 libtorrent 网络线程,这不是很快。

执行此操作的更快方法是跟踪所有尚未播种的种子,并在您获得 torrent_finished_alert 种子时 "strike them off your list"。 (您可以通过调用 ses.pop_alerts() 获得提醒)。

我要提出的另一个建议是先设置 settings_pack 对象 ,然后再创建会话。它更高效,更清洁。特别是关于打开侦听套接字然后在更改设置时立即关闭并重新打开它们。

p = lt.settings_pack()
p['proxy_hostname'] = '...'
p['proxy_username'] = '...'
p['proxy_password'] = '...'
p['proxy_port'] = 1080
p['proxy_type'] = lt.proxy_type_t.socks5_pw
p['proxy_peer_connections'] = True

ses = lt.session(p)