Python实现多线程HTTP下载器示例


Posted in Python onFebruary 11, 2017

本文将介绍使用Python编写多线程HTTP下载器,并生成.exe可执行文件。

环境:windows/Linux + Python2.7.x

单线程

在介绍多线程之前首先介绍单线程。编写单线程的思路为:

1.解析url;

2.连接web服务器;

3.构造http请求包;

4.下载文件。

接下来通过代码进行说明。

解析url

通过用户输入url进行解析。如果解析的路径为空,则赋值为'/';如果端口号为空,则赋值为"80”;下载文件的文件名可根据用户的意愿进行更改(输入'y'表示更改,输入其它表示不需要更改)。

下面列出几个解析函数:

#解析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服务器

使用socket模块,根据解析url得到的host和port连接web服务器,代码如下:

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

构造http请求包

根据解析url得到的path, host, port构造一个HTTP请求包。 

from analysisUrl import path, host, port

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

下载文件

根据构造的http请求包,向服务器发送文件,抓取响应报文头部的"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

下载文件并计算下载所用的时间。 

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)

多线程

抓取响应报文头部的"Content-Length"字段,结合线程个数,加锁分段下载。与单线程的不同,这里将所有代码整合为一个文件,代码中使用更多的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

根据得到的Length,结合线程个数划分范围:

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

实现多线程下载,在向文件写入内容时,向线程加锁,并使用with lock代替lock.acquire( )...lock.release( );使用file.seek( )设置文件偏移地址,保证写入文件的准确性。

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

运行结果:

Python实现多线程HTTP下载器示例

将(*.py)文件转化为(*.exe)可执行文件

当写好了一个工具,如何让那些没有安装Python的人使用这个工具呢?这就需要将.py文件转化为.exe文件。

这里用到Python的py2exe模块,初次使用,所以对其进行介绍:

py2exe是一个将Python脚本转换成windows上可独立执行的可执行文件(*.exe)的工具,这样,就可以不用装Python在windows上运行这个可执行程序。

接下来,在multiThreadDownload.py的同目录下,创建mysetup.py文件,编写:

from distutils.core import setup
import py2exe

setup(console=["multiThreadDownload.py"])

接着执行命令:Python mysetup.py py2exe

生成dist文件夹,multiTjhreadDownload.exe文件位于其中,点击运行即可:

Python实现多线程HTTP下载器示例

Python实现多线程HTTP下载器示例

demo下载地址:HttpFileDownload_3water.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python文件和目录操作详解
Feb 08 Python
Python中执行存储过程及获取存储过程返回值的方法
Oct 07 Python
详解Python nose单元测试框架的安装与使用
Dec 20 Python
Python实现的将文件每一列写入列表功能示例【测试可用】
Mar 19 Python
Python实现爬虫从网络上下载文档的实例代码
Jun 13 Python
pycharm打开命令行或Terminal的方法
Jan 16 Python
python 错误处理 assert详解
Apr 20 Python
基于tensorflow for循环 while循环案例
Jun 30 Python
python 实现压缩和解压缩的示例
Sep 22 Python
详解Python描述符的工作原理
Jun 11 Python
用Python编写简单的gRPC服务的详细过程
Jul 04 Python
Python内置类型集合set和frozenset的使用详解
Apr 26 Python
Python  pip安装lxml出错的问题解决办法
Feb 10 #Python
使用Python脚本和ADB命令实现卸载App
Feb 10 #Python
Python中str is not callable问题详解及解决办法
Feb 10 #Python
python用Pygal如何生成漂亮的SVG图像详解
Feb 10 #Python
Ubuntu下创建虚拟独立的Python环境全过程
Feb 10 #Python
简单谈谈Python中的几种常见的数据类型
Feb 10 #Python
Python使用QQ邮箱发送Email的方法实例
Feb 09 #Python
You might like
php使用多个进程同时控制文件读写示例
2014/02/28 PHP
基于PHP微信红包的算法探讨
2016/07/21 PHP
Laravel开启跨域请求的方法
2019/10/13 PHP
12种不宜使用的Javascript语法整理
2013/11/04 Javascript
jquery如何获取复选框的值
2013/12/12 Javascript
鼠标经过tr时,改变tr当前背景颜色
2014/01/13 Javascript
基于jQuery的JavaScript模版引擎JsRender使用指南
2014/12/29 Javascript
jQuery基于ajax实现星星评论代码
2015/08/07 Javascript
jquery实现漂亮的二级下拉菜单代码
2015/08/26 Javascript
js操作数据库实现注册和登陆的简单实例
2016/05/26 Javascript
jQuery EasyUI菜单与按钮详解
2016/07/13 Javascript
jQuery实现圣诞节礼物动画案例解析
2016/12/25 Javascript
详解Vue监听数据变化原理
2017/03/08 Javascript
Angular2使用vscode断点调试ts文件的方法
2017/12/13 Javascript
vue.js实现标签页切换效果
2018/06/07 Javascript
Vue与Node.js通过socket.io通信的示例代码
2018/07/25 Javascript
vue中利用Promise封装jsonp并调取数据
2019/06/18 Javascript
python实现矩阵乘法的方法
2015/06/28 Python
Python中matplotlib中文乱码解决办法
2017/05/12 Python
微信跳一跳python辅助软件思路及图像识别源码解析
2018/01/04 Python
python 剪切移动文件的实现代码
2018/08/02 Python
在ubuntu16.04中将python3设置为默认的命令写法
2018/10/31 Python
详解pandas中MultiIndex和对象实际索引不一致问题
2019/07/23 Python
利用css3 translate完美实现表头固定效果
2017/02/28 HTML / CSS
领先的荷兰线上超市:荷兰之家Holland at Home(支持中文)
2021/01/21 全球购物
班主任工作年限证明
2014/01/12 职场文书
大专毕业自我鉴定
2014/02/04 职场文书
本科毕业生自荐信
2014/06/02 职场文书
公司总经理任命书
2014/06/05 职场文书
篮球比赛策划方案
2014/06/05 职场文书
教师四风问题整改措施
2014/09/25 职场文书
无刑事犯罪记录证明范本
2014/09/29 职场文书
先进党员事迹材料
2014/12/24 职场文书
2015年化验室工作总结
2015/04/23 职场文书
长辈生日祝福语大全(72句)
2019/08/09 职场文书
linux中nohup和后台运行进程查看及终止
2021/06/24 Python