7

Я пытаюсь получить метаданные около 10k + торрентов в день с помощью python libtorrent.создание демона с использованием Python libtorrent для извлечения метаданных из 100k + торрентов

Это текущий поток кода

  1. Start Libtorrent Session.
  2. Получить общее количество торрентов, нам нужны метаданные для загрузки в течение последних 1 дня.
  3. получить хеши торрентов из БД в кусках
  4. создать магнитную ссылку с использованием этих хэшей и добавить эти магнитные URI в сеансе, создав ручку для каждого URI магнита.
  5. сон в течение секунды, пока метаданные извлекаются и продолжают проверять, найдены ли метаданные или нет.
  6. Если получены метаданные, добавьте его в БД, проверьте, были ли мы ищем метаданные в течение 10 минут, если да, то удалите дескриптор, иначе вы не будете искать метаданные на данный момент.
  7. сделать выше бесконечно. и сохранить состояние сеанса для будущего.

До сих пор я пробовал это.

#!/usr/bin/env python 
# this file will run as client or daemon and fetch torrent meta data i.e. torrent files from magnet uri 

import libtorrent as lt # libtorrent library 
import tempfile # for settings parameters while fetching metadata as temp dir 
import sys #getting arguiments from shell or exit script 
from time import sleep #sleep 
import shutil # removing directory tree from temp directory 
import os.path # for getting pwd and other things 
from pprint import pprint # for debugging, showing object data 
import MySQLdb # DB connectivity 
import os 
from datetime import date, timedelta 

session = lt.session(lt.fingerprint("UT", 3, 4, 5, 0), flags=0) 
session.listen_on(6881, 6891) 
session.add_extension('ut_metadata') 
session.add_extension('ut_pex') 
session.add_extension('smart_ban') 
session.add_extension('metadata_transfer') 

session_save_filename = "/magnet2torrent/magnet_to_torrent_daemon.save_state" 

if(os.path.isfile(session_save_filename)): 

    fileread = open(session_save_filename, 'rb') 
    session.load_state(lt.bdecode(fileread.read())) 
    fileread.close() 
    print('session loaded from file') 
else: 
    print('new session started') 

session.add_dht_router("router.utorrent.com", 6881) 
session.add_dht_router("router.bittorrent.com", 6881) 
session.add_dht_router("dht.transmissionbt.com", 6881) 
session.add_dht_router("dht.aelitis.com", 6881) 

session.start_dht() 
session.start_lsd() 
session.start_upnp() 
session.start_natpmp() 

alive = True 
while alive: 

    db_conn = MySQLdb.connect( host = '', user = '', passwd = '', db = '', unix_socket='/mysql/mysql.sock') # Open database connection 
    #print('reconnecting') 
    #get all records where enabled = 0 and uploaded within yesterday 
    subset_count = 100 ; 

    yesterday = date.today() - timedelta(1) 
    yesterday = yesterday.strftime('%Y-%m-%d %H:%M:%S') 
    #print(yesterday) 

    total_count_query = ("SELECT COUNT(*) as total_count FROM content WHERE upload_date > '"+ yesterday +"' AND enabled = '0' ") 
    #print(total_count_query) 
    try: 
     total_count_cursor = db_conn.cursor()# prepare a cursor object using cursor() method 
     total_count_cursor.execute(total_count_query) # Execute the SQL command 
     total_count_results = total_count_cursor.fetchone() # Fetch all the rows in a list of lists. 
     total_count = total_count_results[0] 
     print(total_count) 
    except: 
      print "Error: unable to select data" 

    total_pages = total_count/subset_count 
    #print(total_pages) 

    current_page = 1 
    while(current_page <= total_pages): 
     from_count = (current_page * subset_count) - subset_count 

     #print(current_page) 
     #print(from_count) 

     hashes = [] 

     get_mysql_data_query = ("SELECT hash FROM content WHERE upload_date > '" + yesterday +"' AND enabled = '0' ORDER BY record_num DESC LIMIT "+ str(from_count) +" , " + str(subset_count) +" ") 
     #print(get_mysql_data_query) 
     try: 
      get_mysql_data_cursor = db_conn.cursor()# prepare a cursor object using cursor() method 
      get_mysql_data_cursor.execute(get_mysql_data_query) # Execute the SQL command 
      get_mysql_data_results = get_mysql_data_cursor.fetchall() # Fetch all the rows in a list of lists. 
      for row in get_mysql_data_results: 
       hashes.append(row[0].upper()) 
     except: 
      print "Error: unable to select data" 

     #print(hashes) 

     handles = [] 

     for hash in hashes: 
      tempdir = tempfile.mkdtemp() 
      add_magnet_uri_params = { 
       'save_path': tempdir, 
       'duplicate_is_error': True, 
       'storage_mode': lt.storage_mode_t(2), 
       'paused': False, 
       'auto_managed': True, 
       'duplicate_is_error': True 
      } 
      magnet_uri = "magnet:?xt=urn:btih:" + hash.upper() + "&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A80&tr=udp%3A%2F%2Ftracker.publicbt.com%3A80&tr=udp%3A%2F%2Ftracker.ccc.de%3A80" 
      #print(magnet_uri) 
      handle = lt.add_magnet_uri(session, magnet_uri, add_magnet_uri_params) 
      handles.append(handle) #push handle in handles list 

     #print("handles length is :") 
     #print(len(handles)) 

     while(len(handles) != 0): 
      for h in handles: 
       #print("inside handles for each loop") 
       if h.has_metadata(): 
        torinfo = h.get_torrent_info() 
        final_info_hash = str(torinfo.info_hash()) 
        final_info_hash = final_info_hash.upper() 
        torfile = lt.create_torrent(torinfo) 
        torcontent = lt.bencode(torfile.generate()) 
        tfile_size = len(torcontent) 
        try: 
         insert_cursor = db_conn.cursor()# prepare a cursor object using cursor() method 
         insert_cursor.execute("""INSERT INTO dht_tfiles (hash, tdata) VALUES (%s, %s)""", [final_info_hash , torcontent]) 
         db_conn.commit() 
         #print "data inserted in DB" 
        except MySQLdb.Error, e: 
         try: 
          print "MySQL Error [%d]: %s" % (e.args[0], e.args[1]) 
         except IndexError: 
          print "MySQL Error: %s" % str(e)  


        shutil.rmtree(h.save_path()) # remove temp data directory 
        session.remove_torrent(h) # remove torrnt handle from session 
        handles.remove(h) #remove handle from list 

       else: 
        if(h.status().active_time > 600): # check if handle is more than 10 minutes old i.e. 600 seconds 
         #print('remove_torrent') 
         shutil.rmtree(h.save_path()) # remove temp data directory 
         session.remove_torrent(h) # remove torrnt handle from session 
         handles.remove(h) #remove handle from list 
       sleep(1)   
       #print('sleep1') 

     #print('sleep10') 
     #sleep(10) 
     current_page = current_page + 1 

     #save session state 
     filewrite = open(session_save_filename, "wb") 
     filewrite.write(lt.bencode(session.save_state())) 
     filewrite.close() 


    print('sleep60') 
    sleep(60) 

    #save session state 
    filewrite = open(session_save_filename, "wb") 
    filewrite.write(lt.bencode(session.save_state())) 
    filewrite.close() 

Я пытался поддерживать выше скрипт работает в течение ночи и обнаружил, мета данных только около 1200 торрентов находятся в ночной сессии. , поэтому я ищу улучшения производительности скрипта.

Я даже попробовал расшифровку файла save_state и заметил, что есть 700 + DHT nodes. Я подключен. поэтому его не нравится DHT не работает,

То, что я планирую сделать, keep the handles active в сеансе бесконечно, пока метаданные не получены. и не собираемся удалять ручки через 10 минут, если метаданные не будут получены за 10 минут, как я это делаю сейчас.

У меня есть несколько вопросов относительно привязок python lib-torrent.

  1. Сколько ручек я могу продолжать работать? есть ли ограничение для запуска ручек?
  2. будет работать с ручками 10k + или 100k, замедляет мою систему? или есть ресурсы? если да, то какие ресурсы? Я имею в виду RAM, NETWORK?
  3. Я за брандмауэром, может быть заблокирован входящий порт, вызывающий медленную скорость извлечения метаданных?
  4. Может ли DHT-сервер использовать router.bittorrent.com или любой другой BAN мой IP-адрес для отправки слишком большого количества запросов?
  5. Могут ли другие сверстники BAN мой IP-адрес, если они узнают, что я делаю слишком много запросов только для получения метаданных?
  6. Можно ли запустить несколько экземпляров этого скрипта? или может быть многопоточным? улучшит ли производительность?
  7. Если вы используете несколько экземпляров одного и того же сценария, каждый скрипт получит уникальный идентификатор узла в зависимости от ip и порта, который я использую, является ли это жизнеспособным решением?

Есть ли лучший подход? для достижения того, что я пытаюсь?

ответ

3

Я не могу отвечать на вопросы, относящиеся к API-интерфейсам libtorrent, но некоторые из ваших вопросов относятся к bittorrent вообще.

будет работать с ручками 10k + или 100k, замедляет мою систему? или есть ресурсы? если да, то какие ресурсы? Я имею в виду RAM, NETWORK?

Метаданные-загрузки не должны использовать много ресурсов, так как они не являются полностью загружаемыми торрентами, т. Е. Они не могут выделять фактические файлы или что-то в этом роде. Но им понадобится некоторое пространство ram/disk для самих метаданных, как только они захватят первый кусок из них.

Я за брандмауэром, может быть заблокированный входящий порт, вызывающий медленную скорость извлечения метаданных?

Да, уменьшая количество сверстников, способных устанавливать соединения, становится сложнее получить метаданные (или установить какое-либо соединение вообще) на рои с низким количеством сверстников.

NAT могут вызывать такую ​​же проблему.

Может ли DHT-сервер использовать router.bittorrent.com или любой другой BAN мой IP-адрес для отправки слишком большого количества запросов?

router.bittorrent.com - это узел начальной загрузки, а не сервер как таковой. Поиск не запрашивает один узел, они запрашивают много разных (среди миллионов). Но да, отдельные узлы могут запретить, или, скорее, предел скорости, вас.

Это может быть уменьшено путем поиска случайно распределенных идентификаторов для распространения нагрузки через пространство ключей DHT.

Можно ли запустить несколько экземпляров этого скрипта? или может быть многопоточным? улучшит ли производительность?

AIUI libtorrent является достаточно неблокирующим или многопоточным, что вы можете планировать сразу несколько торрентов.

Я не знаю, имеет ли libtorrent лимит скорости для исходящих запросов DHT.

Если вы используете несколько экземпляров одного и того же сценария, каждый скрипт получит уникальный идентификатор узла в зависимости от ip и порта, который я использую, является ли это жизнеспособным решением?

Если вы имеете в виду идентификатор узла DHT, то они производятся от IP (согласно BEP 42), а не от порта. Хотя некоторый случайный элемент включен, поэтому ограниченное количество идентификаторов может быть получено на каждый IP-адрес.

И некоторые из этого могут также могут быть применимы для сценария: http://blog.libtorrent.org/2012/01/seeding-a-million-torrents/

И еще один вариант my own DHT implementation, который включает в себя CLI для насыпных-выборки торрентов.

+0

Я очень ценю ваш вход, спасибо. – AMB