xiaobian 发表于 2013-1-15 03:10:03

多线程下载文件

#!/usr/bin/python#coding=gbkimport reimport osimport sysimport timeimport globimport stringimport socketimport getoptimport urllibimport urllib2import threadingfrom sgmllib import SGMLParser############################################################################### self-defined exception classes##############################################################################class ConnectionError(Exception): passclass URLUnreachable(Exception):passclass CanotDownload(Exception):pass############################################################################### multiple threads download module starts here##############################################################################class HttpGetThread(threading.Thread):    def __init__(self, name, url, filename, range=0):      #print " name ",name      #print " url ",url      #print " filename ",filename         #print " range ",range      threading.Thread.__init__(self, name=name)      self.url = url      self.filename = filename      self.range = range      self.totalLength = range - range +1      try:            self.downloaded = os.path.getsize(self.filename)      except OSError:            self.downloaded = 0      self.percent = self.downloaded/float(self.totalLength)*100      self.headerrange = (self.range+self.downloaded, self.range)      self.bufferSize = 8192    def run(self):      try:            self.downloaded = os.path.getsize(self.filename)      except OSError:            self.downloaded = 0      self.percent = self.downloaded/float(self.totalLength)*100      #self.headerrange = (self.range+self.downloaded, self.range)      self.bufferSize = 8192      #request = urllib2.Request(self.url)      #request.add_header('Range', 'bytes=%d-%d' %self.headerrange)      downloadAll = False      retries = 1      while not downloadAll:            if retries > 10:                break            try:               self.headerrange = (self.range+self.downloaded, self.range)                request = urllib2.Request(self.url)                request.add_header('Range', 'bytes=%d-%d' %self.headerrange)                conn = urllib2.urlopen(request)                startTime = time.time()                data = conn.read(self.bufferSize)                while data:                  f = open(self.filename, 'ab')                  f.write(data)                  f.close()                  self.time = int(time.time() - startTime)                  self.downloaded += len(data)                  self.percent = self.downloaded/float(self.totalLength) *100                                 data = conn.read(self.bufferSize)                downloadAll = True            except Exception, err:                retries += 1                time.sleep(1)                continue#分割文件方便多线程下载def Split(size,blocks):      ranges = []    blocksize = size / blocks    for i in xrange(blocks-1):      ranges.append((i*blocksize,blocksize*i+blocksize-1))    ranges.append(( blocksize*(blocks-1), size-1))    #print ranges    return ranges#获得文件大小def GetHttpFileSize(url):    length = 0    try:      conn = urllib.urlopen(url)      headers = conn.info().headers      for header in headers:            if header.find('Length') != -1:                length = header.split(':')[-1].strip()                length = int(length)    except Exception, err:      pass            return lengthdef hasLive(ts):    for t in ts:      print "\n thread name ",t.getName()," alive ",t.isAlive()      if t.isAlive():            return True    return False#def MyHttpGet(url, output=None, connections=4):    """    arguments:      url, in GBK encoding      output, default encoding, do no convertion      connections, integer    """      length = GetHttpFileSize(url)    startTime = time.time() #开始时间    #print " startTime ",startTime    mb = length/1024/1024.0    if length == 0:      raise URLUnreachable    blocks = connections    if output:      filename = output    else:      output = url.split('/')[-1]    ranges = Split(length, blocks)    names = []    #names = ["%s_%d" %(filename,i) for i in xrange(blocks)]    for i in xrange(blocks):      names.append("%s_%d" %(filename,i))    ts = []    #print "+++++++++++++++++++++++++++ blocks ",blocks    for i in xrange(blocks):      t = HttpGetThread(" 下载线程 "+str(i), url, names, ranges)      t.setDaemon(True)      t.start()      ts.append(t)    live = hasLive(ts)    startSize = sum() # 已下载多少    #print "++++++++++ startSize ",startSize       etime = 0 #    rate = 0 # 下载速度 *    while live:      try:            etime = time.time() - startTime            d = sum()/float(length)*100            downloadedThistime = sum()-startSize            try:                rate = downloadedThistime / float(etime)/1024            except:                rate = 0.0            progressStr = u'\rFilesize: %d(%.2fM)Downloaded: %.2f%%Avg rate: %.1fKB/s' %(length, mb, d, rate)            sys.stdout.write(progressStr)            sys.stdout.flush()            #sys.stdout.write('\b'*(len(progressStr)+1))            live = hasLive(ts)            time.sleep(0.8)      except KeyboardInterrupt:            print            print "Exit..."            for n in names:                try:                  os.remove(n)                except:                  pass            sys.exit(1)                print    etime = time.time() - startTime    print " endTime ",time.time()    printu'耗时: %d:%d, 平均速度:%.2fKB/s' %(int(etime)/60, int(etime)%60,rate)   f = open(filename, 'wb')    for n in names:      f.write(open(n,'rb').read())      try:            os.remove(n)      except:            pass    f.close()if __name__ == "__main__":    url = "http://www.jszg.com.cn/webpage/网页作业/天黑黑.mp3"    output = "孙燕姿---天黑黑.mp3"    connections = 10    MyHttpGet(url,output,connections);
页: [1]
查看完整版本: 多线程下载文件