Maison > Article > développement back-end > Implémentation Python d'un exemple de téléchargeur HTTP multithread
Cet article présentera l'utilisation de Python pour écrire un téléchargeur HTTP multithread et générer un fichier exécutable .exe.
Environnement : Windows/Linux Python2.7.x
Monothread
Introduisez d'abord le monothread avant d'introduire le multi-threading. L'idée d'écrire un seul fil de discussion est la suivante :
1. Analyser l'URL
2. >
3. Construisez un package de requête http ;
4. Téléchargez le fichier.
Ce qui suit est expliqué par le code.
Analyser l'URLAnalysé par l'URL d'entrée de l'utilisateur. Si le chemin analysé est vide, la valeur attribuée est « / » ; si le numéro de port est vide, la valeur attribuée est « 80 » ; le nom du fichier téléchargé peut être modifié selon les souhaits de l'utilisateur (entrez « y »). pour indiquer un changement, entrez autre pour indiquer qu'aucune modification n'est requise).
Plusieurs fonctions d'analyse sont répertoriées ci-dessous :
#解析host和path def analyHostAndPath(totalUrl): protocol,s1 = urllib.splittype(totalUrl) host, path = urllib.splithost(s1) if path == '': path = '/' return host, path #解析port def analysisPort(host): host, port = urllib.splitport(host) if port is None: return 80 return port #解析filename def analysisFilename(path): filename = path.split('/')[-1] if '.' not in filename: return None return filenameSe connecter au serveur Web
Utilisez le module socket pour vous connecter au serveur Web en fonction de l'hôte et du port obtenus en analysant l'URL. Le code est le suivant :
import socket from analysisUrl import port,host ip = socket.gethostbyname(host) s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((ip, port)) print "success connected webServer!!"
<.>Construisez un package de requête HTTP
Construisez un package de requête HTTP basé sur le chemin, l'hôte et le port obtenus en analysant l'URL.
from analysisUrl import path, host, port packet = 'GET ' + path + ' HTTP/1.1\r\nHost: ' + host + '\r\n\r\n'
Téléchargez le fichier
Envoyez le fichier au serveur et récupérez la réponse en fonction du construit Package de requête http "Content-Length" dans l'en-tête du message.
def getLength(self): s.send(packet) print "send success!" buf = s.recv(1024) print buf p = re.compile(r'Content-Length: (\d*)') length = int(p.findall(buf)[0]) return length, bufTéléchargez le fichier et calculez le temps de téléchargement.
def download(self): file = open(self.filename,'wb') length,buf = self.getLength() packetIndex = buf.index('\r\n\r\n') buf = buf[packetIndex+4:] file.write(buf) sum = len(buf) while 1: buf = s.recv(1024) file.write(buf) sum = sum + len(buf) if sum >= length: break print "Success!!" if __name__ == "__main__": start = time.time() down = downloader() down.download() end = time.time() print "The time spent on this program is %f s"%(end - start)
Multi-thread
Capturez le champ "Content-Length" dans l'en-tête du message de réponse, Combiné au nombre de threads, le téléchargement segmenté est verrouillé. Différent du code monothread, tout le code est intégré ici dans un seul fichier et davantage de modules intégrés Python sont utilisés dans le code.
Obtenez "Content-Length" :def getLength(self): opener = urllib2.build_opener() req = opener.open(self.url) meta = req.info() length = int(meta.getheaders("Content-Length")[0]) return lengthSelon la longueur obtenue, combinez le nombre de fils pour diviser la plage :
def get_range(self): ranges = [] length = self.getLength() offset = int(int(length) / self.threadNum) for i in range(self.threadNum): if i == (self.threadNum - 1): ranges.append((i*offset,'')) else: ranges.append((i*offset,(i+1)*offset)) return rangesImplémentez le téléchargement multithread Lorsque vous écrivez du contenu dans le fichier, verrouillez le fil et utilisez avec lock au lieu de lock.acquire(). .lock. release(); Utilisez file.seek() pour définir l'adresse de décalage du fichier afin de garantir l'exactitude de l'écriture des fichiers.
def downloadThread(self,start,end): req = urllib2.Request(self.url) req.headers['Range'] = 'bytes=%s-%s' % (start, end) f = urllib2.urlopen(req) offset = start buffer = 1024 while 1: block = f.read(buffer) if not block: break with lock: self.file.seek(offset) self.file.write(block) offset = offset + len(block) def download(self): filename = self.getFilename() self.file = open(filename, 'wb') thread_list = [] n = 1 for ran in self.get_range(): start, end = ran print 'starting:%d thread '% n n += 1 thread = threading.Thread(target=self.downloadThread,args=(start,end)) thread.start() thread_list.append(thread) for i in thread_list: i.join() print 'Download %s Success!'%(self.file) self.file.close()Résultat d'exécution :
Convertir le fichier (*.py) après écrire un outil pour les fichiers exécutables (*.exe)
, comment permettre aux personnes qui n'ont pas installé Python d'utiliser cet outil ? Cela nécessite de convertir le fichier .py en fichier .exe.
Le module py2exe de Python est utilisé ici. C'est la première fois que je l'utilise, je vais donc le présenter : py2exe est un fichier exécutable qui convertit un script Python en un exécutable indépendant. fichier sur l'outil Windows (*.exe), afin que vous puissiez exécuter ce programme exécutable sous Windows sans installer Python. Ensuite, créez le fichier mysetup.py dans le même répertoire que multiThreadDownload.py et écrivez :from distutils.core import setup import py2exe setup(console=["multiThreadDownload.py"])Ensuite, exécutez la commande : Python mysetup.py py2exe génère le dossier dist, le fichier multiTjhreadDownload.exe se trouve dedans, cliquez pour exécuter :
Adresse de téléchargement de la démo : HttpFileDownload_jb51.rar
Ce qui précède est l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'apprentissage de chacun, et j'espère également que tout le monde soutiendra le. Site Web chinois PHP.