Heim  >  Artikel  >  Backend-Entwicklung  >  Beispiel für eine Python-Implementierung eines Multithread-HTTP-Downloaders

Beispiel für eine Python-Implementierung eines Multithread-HTTP-Downloaders

高洛峰
高洛峰Original
2017-02-13 13:40:011516Durchsuche

In diesem Artikel wird die Verwendung von Python zum Schreiben eines Multithread-HTTP-Downloaders und zum Generieren einer ausführbaren .exe-Datei vorgestellt.

Umgebung: Windows/Linux + Python2.7.x

Single-Threaded

Führen Sie zuerst Single-Threading ein, bevor Sie Multi-Threading einführen. Die Idee, einen einzelnen Thread zu schreiben, ist:

1. Analysieren Sie die URL.

3. Erstellen Sie ein http-Anfragepaket;

Laden Sie die Datei herunter.

Das Folgende wird durch Code erklärt.

URL analysieren

Nach Benutzereingabe-URL analysiert. Wenn der analysierte Pfad leer ist, lautet der zugewiesene Wert „/“. Wenn die Portnummer leer ist, lautet der zugewiesene Wert „80“. Der Dateiname der heruntergeladenen Datei kann entsprechend den Wünschen des Benutzers geändert werden. Um eine Änderung anzuzeigen, geben Sie „Sonstiges“ ein, um anzugeben, dass keine Änderungen erforderlich sind.

Mehrere Parsing-Funktionen sind unten aufgeführt:

#解析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 filename

Mit Webserver verbinden

Verwenden Sie das Socket-Modul, um eine Verbindung zum Webserver herzustellen, basierend auf dem Host und dem Port, die Sie durch Parsen der URL erhalten haben. Der Code lautet wie folgt:

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!!"

Erstellen Sie ein HTTP-Anforderungspaket

Erstellen Sie ein HTTP-Anforderungspaket basierend auf dem Pfad, dem Host und dem Port, die Sie beim Parsen der URL erhalten haben.

from analysisUrl import path, host, port

packet = 'GET ' + path + ' HTTP/1.1\r\nHost: ' + host + '\r\n\r\n' 

Laden Sie die Datei herunter

Senden Sie die Datei an den Server und holen Sie sich die Antwort basierend auf der Konstruktion HTTP-Anforderungspaket „Content-Length“ im Nachrichtenheader.

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, buf
Laden Sie die Datei herunter und berechnen Sie die Downloadzeit.

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)

Multithreaded

Erfassen Sie das Feld „Content-Length“ im Header der Antwortnachricht. In Kombination mit der Anzahl der Threads ist der segmentierte Download gesperrt. Anders als beim Single-Threaded ist hier der gesamte Code in eine Datei integriert und im Code werden mehr integrierte Python-Module verwendet.

Erhalten Sie „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 length
Kombinieren Sie entsprechend der erhaltenen Länge die Anzahl der Threads, um den Bereich zu teilen:

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 ranges
Implementieren Sie beim Schreiben von Inhalten in die Datei den Thread und verwenden Sie lock anstelle von lock.acquire(). .lock.release(); Verwenden Sie file.seek(), um die Datei-Offset-Adresse festzulegen, um die Genauigkeit beim Schreiben von Dateien sicherzustellen.

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()
Laufergebnis:

Beispiel für eine Python-Implementierung eines Multithread-HTTP-DownloadersDatei (*.py) konvertieren Schreiben eines Tools für (*.exe) ausführbare Dateien

, wie lässt man dieses Tool von Leuten nutzen, die Python nicht installiert haben? Dies erfordert die Konvertierung der .py-Datei in eine .exe-Datei.

Das py2exe-Modul von Python wird hier zum ersten Mal verwendet, daher werde ich es vorstellen:

py2exe ist eine ausführbare Datei, die ein Python-Skript in eine unabhängig ausführbare Datei konvertiert Datei unter Windows (*.exe)-Tool, damit Sie dieses ausführbare Programm unter Windows ausführen können, ohne Python zu installieren.

Als nächstes erstellen Sie die Datei mysetup.py im selben Verzeichnis wie multiThreadDownload.py und schreiben:

from distutils.core import setup
import py2exe

setup(console=["multiThreadDownload.py"])
Führen Sie dann den Befehl aus : Python mysetup.py py2exe

generiert den dist-Ordner, die Datei multiTjhreadDownload.exe befindet sich darin. Klicken Sie zum Ausführen:

Beispiel für eine Python-Implementierung eines Multithread-HTTP-Downloaders

Demo-Download-Adresse: HttpFileDownload_jb51.rarBeispiel für eine Python-Implementierung eines Multithread-HTTP-Downloaders

Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er zum Lernen aller beiträgt, und ich hoffe auch, dass jeder ihn unterstützt Chinesische PHP-Website.

Weitere Artikel zur Python-Implementierung von Multithread-HTTP-Downloader-Beispielen finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn