99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

Python學(xué)習(xí)之多線程HTTP下載器的編寫詳解

發(fā)布時(shí)間:2017-02-14 15:20  回復(fù):0  查看:3031   最后回復(fù):2017-02-14 15:20  
本文和大家分享的主要是使用python 語言編寫多線程HTTP 下載器,并生成 .exe 可執(zhí)行文件的相關(guān)方法步驟,一起來看看吧,希望對大家 學(xué)習(xí)python有所幫助。
  環(huán)境:windows/Linux + Python2.7.x
   單線程
  在介紹多線程之前首先介紹單線程。編寫單線程的思路為:
  1.  解析 url ;
  2.  連接 web 服務(wù)器;
  3.  構(gòu)造 http 請求包;
  4.  下載文件。
  接下來通過代碼進(jìn)行說明。
   解析url
  通過用戶輸入url 進(jìn)行解析。如果解析的路徑為空,則賦值為 '/' ;如果端口號為空,則賦值為 "80” ;下載文件的文件名可根據(jù)用戶的意愿進(jìn)行更改(輸入 'y' 表示更改,輸入其它表示不需要更改)。
  下面列出幾個(gè)解析函數(shù):
  # 解析 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
   連接web服務(wù)器
  使用socket 模塊,根據(jù)解析 url 得到的 host port 連接 web 服務(wù)器,代碼如下:
  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 !! "
   構(gòu)造http請求包
  根據(jù)解析url 得到的 path, host, port 構(gòu)造一個(gè) HTTP 請求包。
   from analysisUrl  import path, host, port
  packet = 'GET ' + path + ' HTTP/1.1\r\nHost: ' + host + '\r\n\r\n'
   下載文件
  根據(jù)構(gòu)造的http 請求包,向服務(wù)器發(fā)送文件,抓取響應(yīng)報(bào)文頭部的 "Content-Length" 。
   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
  下載文件并計(jì)算下載所用的時(shí)間。
   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)
  運(yùn)行結(jié)果示意圖:
Python學(xué)習(xí)之多線程HTTP下載器的編寫詳解
多線程
  抓取響應(yīng)報(bào)文頭部的"Content-Length" 字段,結(jié)合線程個(gè)數(shù),加鎖分段下載。與單線程的不同,這里將所有代碼整合為一個(gè)文件,代碼中使用更多的 Python 自帶模塊。
  得到"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
  根據(jù)得到的Length ,結(jié)合線程個(gè)數(shù)劃分范圍:
   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
  實(shí)現(xiàn)多線程下載,在向文件寫入內(nèi)容時(shí),向線程加鎖,并使用  with lock  代替lock.acquire( )...lock.release( ); 使用 file.seek( ) 設(shè)置文件偏移地址,保證寫入文件的準(zhǔn)確性。
   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()
  運(yùn)行結(jié)果:
Python學(xué)習(xí)之多線程HTTP下載器的編寫詳解
(*.py)文件轉(zhuǎn)化為(*.exe)可執(zhí)行文件
  當(dāng)寫好了一個(gè)工具,如何讓那些沒有安裝Python 的人使用這個(gè)工具呢?這就需要將 .py 文件轉(zhuǎn)化為 .exe 文件。
  這里用到Python py2exe 模塊,初次使用,所以對其進(jìn)行介紹:
  py2exe 是一個(gè)將 Python 腳本轉(zhuǎn)換成 windows 上可獨(dú)立執(zhí)行的可執(zhí)行文件( *.exe )的工具,這樣,就可以不用裝 Python windows 上運(yùn)行這個(gè)可執(zhí)行程序??稍?/span> 下載地址  中下載對應(yīng)的版本。
  接下來,在multiThreadDownload.py 的同目錄下,創(chuàng)建 mysetup.py 文件,編寫:
   from distutils.core  import setup import py2exe
   setup(console=["multiThreadDownload.py"])
  接著執(zhí)行命令: Python mysetup.py py2exe
  生成dist 文件夾, multiTjhreadDownload.exe 文件位于其中,點(diǎn)擊運(yùn)行即可。
Python學(xué)習(xí)之多線程HTTP下載器的編寫詳解
上面就是我使用Python 實(shí)現(xiàn)多線程 HTTP 下載器的過程,各位有什么好的想法意見,還望不吝賜教 !
來源: 博客園
您還未登錄,請先登錄

熱門帖子

最新帖子

?