Downloading Multiple torrent files with Libtorrent in Python

时间:2019-04-17 01:47:32

标签: python python-3.x libtorrent libtorrent-rasterbar

I'm trying to write a torrent application that can take in a list of magnet links and then download them all together. I've been trying to read and understand the documentation at Libtorrent but I haven't been able to tell if what I try works or not. I've managed to be able to apply a SOCKS5 proxy to a Libtorrent session and download a single magnet link using this code:

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)

This is great and all for runing on its own with a single link. What I want to do is something like this:

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

I'm not sure if this is even on the right track or not, but some pointers would be helpful.

UPDATE: This is what I now have and it works fine in my case

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)

1 个答案:

答案 0 :(得分:2)

它被称为“磁性链接”(非磁性)。

在新版本的libtorrent中,添加磁链的方式为:

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

这也使您有机会调整add_torrent_params对象,以设置实例的保存目录。

如果您要添加大量磁力链接(或与此相关的常规torrent文件)并希望快速进行操作,则更快的方法是使用:

ses.add_torrent_async(params)

该函数将立即返回,以后可以在torrent_handle中拾取add_torrent_alert对象。

对于并行下载多个磁链,添加它们的伪代码是正确的。您只想确保保存所有返回的torrent_handle对象,或在添加完所有种子句柄后使用ses.get_torrents()查询所有种子句柄。在伪代码中,每次添加新的洪流句柄似乎都将其覆盖。

您表示要退出的条件是所有种子都已完成。最简单的方法是使用handle.status().is_seeding轮询所有对象。即遍历您的洪流句柄列表并询问。请记住,对status()的调用需要往返libtorrent网络线程,这不是超级快。

执行此操作的较快方法是跟踪所有尚未播种的种子,并在获得torrent_finished_alert种子时“将其从列表中剔除”。 (您可以通过致电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)