2016-12-07 4 views
1

J'écris un programme qui doit télécharger un tas de fichiers à partir du Web avant même de courir, donc je créé une fonction qui va télécharger tous les fichiers et " initialiser » le programme appelé init_program, comment cela fonctionne: est-il passe par un couple dicts qui ont urls à un gistfiles sur GitHub. Il tire les URL et utilise urllib2 pour les télécharger. Je ne serai pas en mesure d'ajouter tous les fichiers, mais vous pouvez l'essayer en clonant le repo here. Voici la fonction qui va créer les fichiers des GIST:Accélérer la vitesse de processus de téléchargement de fichiers sur le web

def init_program(): 
    """ Initialize the program and allow all the files to be downloaded 
     This will take awhile to process, but I'm working on the processing 
     speed """ 

    downloaded_wordlists = [] # Used to count the amount of items downloaded 
    downloaded_rainbow_tables = [] 

    print("\n") 
    banner("Initializing program and downloading files, this may take awhile..") 
    print("\n") 

    # INIT_FILE is a file that will contain "false" if the program is not initialized 
    # And "true" if the program is initialized 
    with open(INIT_FILE) as data: 
     if data.read() == "false": 
      for item in GIST_DICT_LINKS.keys(): 
       sys.stdout.write("\rDownloading {} out of {} wordlists.. ".format(len(downloaded_wordlists) + 1, 
                        len(GIST_DICT_LINKS.keys()))) 
       sys.stdout.flush() 
       new_wordlist = open("dicts/included_dicts/wordlists/{}.txt".format(item), "a+") 
       # Download the wordlists and save them into a file 
       wordlist_data = urllib2.urlopen(GIST_DICT_LINKS[item]) 
       new_wordlist.write(wordlist_data.read()) 
       downloaded_wordlists.append(item + ".txt") 
       new_wordlist.close() 

      print("\n") 
      banner("Done with wordlists, moving to rainbow tables..") 
      print("\n") 

      for table in GIST_RAINBOW_LINKS.keys(): 
       sys.stdout.write("\rDownloading {} out of {} rainbow tables".format(len(downloaded_rainbow_tables) + 1, 
                        len(GIST_RAINBOW_LINKS.keys()))) 
       new_rainbowtable = open("dicts/included_dicts/rainbow_tables/{}.rtc".format(table)) 
       # Download the rainbow tables and save them into a file 
       rainbow_data = urllib2.urlopen(GIST_RAINBOW_LINKS[table]) 
       new_rainbowtable.write(rainbow_data.read()) 
       downloaded_rainbow_tables.append(table + ".rtc") 
       new_rainbowtable.close() 

      open(data, "w").write("true").close() # Will never be initialized again 
     else: 
      pass 

    return downloaded_wordlists, downloaded_rainbow_tables 

Cela fonctionne, oui, mais il est extrêmement lent, en raison de la taille des fichiers, chaque fichier a au moins 100.000 lignes en elle. Comment puis-je accélérer cette fonction pour la rendre plus rapide et plus conviviale?

+0

Hmmm, cela dépend de votre connexion wifi. Il n'y a presque aucun moyen que vous pouvez accélérer cela, sauf améliorer votre wifi. Désolé de dire. – Qwerty

+0

@Qwerty même avec filetage? Je veux dire est lent, oui il vaudra la peine à la fin, mais il est un processus d'initialisation lente .. Eh bien ... – papasmurf

+2

http://stackoverflow.com/a/9010299/2308683 –

Répondre

1

Il y a quelques semaines je faisais face à une situation similaire où il était nécessaire de télécharger de nombreux fichiers énormes, mais toutes les solutions simples Python pures que j'ai trouvé était pas assez bon en termes de téléchargement optimisation. Donc, j'ai trouvé Axel - accélérateur de téléchargement en ligne de commande Light pour Linux et Unix

Qu'est-ce que Axel? Axel essaie d'accélérer le processus de téléchargement en utilisant plusieurs connexions pour un fichier, similaire à DownThemAll et d'autres célèbres programmes . Il peut également utiliser plusieurs miroirs pour un téléchargement.

En utilisant Axel, vous obtiendrez des fichiers plus rapidement à partir d'Internet. Ainsi, Axel peut accélérer un téléchargement jusqu'à 60% (environ, selon certains tests ).

Usage: axel [options] url1 [url2] [url...] 

--max-speed=x  -s x Specify maximum speed (bytes per second) 
--num-connections=x -n x Specify maximum number of connections 
--output=f  -o f Specify local output file 
--search[=x]  -S [x] Search for mirrors and download from x servers 
--header=x  -H x Add header string 
--user-agent=x  -U x Set user agent 
--no-proxy  -N Just don't use any proxy server 
--quiet   -q Leave stdout alone 
--verbose  -v More status information 
--alternate  -a Alternate progress indicator 
--help   -h This information 
--version  -V Version information 

Comme axel est écrit en C et il n'y a pas d'extension C pour Python, donc j'utilisé le module subprocess de l'exécuter à l'extérieur et fonctionne parfaitement pour moi.

Vous pouvez faire quelque chose comme ceci:

cmd = ['/usr/local/bin/axel', '-n', str(n_connections), '-o', 
       "{0}".format(filename), url] 
process = subprocess.Popen(cmd,stdin=subprocess.PIPE, stdout=subprocess.PIPE) 

Vous pouvez également analyser les progrès de chaque téléchargement analysant la sortie de la sortie standard.

while True: 
     line = process.stdout.readline() 
     progress = YOUR_GREAT_REGEX.match(line).groups() 
     ... 

+0

Cela ne fonctionne que si le site d'hébergement supporte les téléchargements parallèles –

+0

C'est vrai, mais peut être utile dans la plupart des cas.Mais ce n'est pas une balle d'argent, malheureusement. – GustavoIP

+0

@GustavolP Je travaille également sur une machine Windows .. C'est un génie de travailler autour si donc – papasmurf

0

Vous bloquez pendant que vous attendez pour chaque téléchargement. Le temps total est donc la somme du temps d'aller-retour pour chaque téléchargement. Votre code passera probablement beaucoup de temps à attendre le trafic réseau. Une façon d'améliorer cela est de ne pas bloquer pendant que vous attendez chaque réponse. Tu peux le faire de plusieurs façons. Par exemple en transmettant chaque requête à un thread (ou processus) séparé, ou en utilisant une boucle d'événement et des coroutines. Lisez sur les modules de threading et d'asyncio.

+0

Elaborer ce que vous entendez par blocage en attendant chaque téléchargement? – papasmurf

+1

urlopen() suivi de read() signifie que vous attendez l'ouverture d'une connexion, l'envoi de la requête et l'arrivée de la réponse. Ce trafic réseau est susceptible de prendre beaucoup de temps et la plupart du temps, votre code attend le trafic réseau. Lorsque vous avez beaucoup de demandes à faire, vous ne voulez pas attendre la réponse à la première, avant de commencer la suivante. –

+0

Alors, comment proposez-vous que je fais ça? Créer une file d'attente de threads, et juste les tirer quand j'en ai besoin? – papasmurf