Загрузка нескольких торрент-файлов с помощью Libtorrent в Python

Я пытаюсь написать торрент-приложение, которое может принимать список магнитных ссылок, а затем загружать их все вместе. Я пытался прочитать и понять документацию на Libtorrent, но не смог сказать работает ли то, что я пытаюсь, или нет. Мне удалось применить прокси-сервер SOCKS5 к сеансу Libtorrent и загрузить одну магнитную ссылку, используя этот код:

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)

Это здорово, и все для запуска самостоятельно с одной ссылкой. Я хочу сделать что-то вроде этого:

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)

person Stone Monarch    schedule 17.04.2019    source источник


Ответы (1)


Это называется «магнитные ссылки» (не магнитные).

В новых версиях libtorrent магнет-ссылка добавляется следующим образом:

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

Это также дает вам возможность настроить объект add_torrent_params, например, установить каталог для сохранения.

Если вы добавляете много магнитных ссылок (или обычных торрент-файлов, если на то пошло) и хотите сделать это быстро, более быстрый способ — использовать:

ses.add_torrent_async(params)

Эта функция вернется немедленно, и объект torrent_handle можно будет забрать позже в add_torrent_alert.

Что касается параллельной загрузки нескольких магнитных ссылок, ваш псевдокод для их добавления верен. Вы просто хотите убедиться, что вы либо сохранили все объекты torrent_handle, которые вы возвращаете, либо запросите все дескрипторы торрента, как только вы закончите их добавлять (используя ses.get_torrents()). В вашем псевдокоде вы, кажется, перезаписываете последний дескриптор торрента каждый раз, когда добавляете новый.

Условие, которое вы указали для выхода, заключалось в том, что все торренты были заполнены. Самый простой способ сделать это — просто опросить их всех с помощью handle.status().is_seeding. то есть просмотрите свой список торрент-дескрипторов и спросите об этом. Имейте в виду, что вызов status() требует обращения к сетевому потоку libtorrent, что не очень быстро.

Более быстрый способ сделать это — отслеживать все торренты, которые еще не раздаются, и «вычеркивать их из своего списка», когда вы получаете torrent_finished_alerts для торрентов. (вы получаете оповещения, позвонив по номеру ses.pop_alerts()).

Еще одно мое предложение: сначала настроить объект settings_pack, а затем создать сеанс. Это более эффективно и немного чище. Особенно в отношении открытия сокетов для прослушивания, а затем их немедленного закрытия и повторного открытия при изменении настроек.

i.e.

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)
person Arvid    schedule 18.04.2019
comment
Благодаря тонну. этой информации было достаточно, чтобы помочь мне расшифровать документацию libtorrent, а также понять, как все это работает. Я обновлю свой вопрос через секунду, чтобы у него было то, что я сделал. Все еще изучаю функцию ses,pop_alerts() - person Stone Monarch; 03.05.2019