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

Я пытаюсь написать торрент-приложение, которое может взять список магнитных ссылок и затем загрузить их все вместе. Я пытался прочитать и понять документацию на 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)

1 Ответ

2 голосов
/ 18 апреля 2019

Это называется "магнитные звенья" (не магнитные).

В новых версиях 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_alert с для торрентов. (вы получаете оповещения по телефону ses.pop_alerts()).

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

* * +1032 т.е.
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)
...