Python 通过urllib进行多线程下载

Python多线程下载

  1. http: range, content-length
  2. python实现

HTTP Range, Content-Length:

Content-Length: 1394829

HTTP头Content-Length用于描述HTTP消息实体的传输长度

Range: bytes=0-1

HTTP头信息Range用于请求服务器返回文件的某个字段,不过在大部分情况请求页面文件不会返回该页面文件的字段,而是返回全部。
(0-1表示的是前两个字节)

实现

import os, sys
from urllib.request import *
from threading import Thread

urllib.request为我们提供访问该页面的方法。
threading.Thread为我们创建多线程。

url = "" #下载文件链接
threadnum = 5 #开启线程数
savepath = "" #文件保存地址
cachesize = 4096 #缓存大小

threadpool = [] #线程池

定义变量,缓存大小单位为字节,指储存在内存中(未写入文件)的大小。开5个线程就需要4096*5字节大小的内存。

def download(startpos, endpos, _id):
	if _id == threadnum-1:
		#是最后一个线程,下载完剩余的全部
		endpos = filesize
	
	download_size = endpos-startpos #总下载大小
	download_num = download_size // cachesize #需要下载次数
	#end_download_size = 0 if download_num*cachesize == download_size else download_size - download_num*cachesize #最后一次读取的大小,如果为0则代表总下载大小整除缓存数 (方便理解)
	end_download_size = download_size % cachesize
	#请求访问文件
	reqfile = Request(url, headers = {
     "range":"bytes=%s-%s" % (startpos, endpos)})
	reqfile = urlopen(reqfile)
	print("[Thread-%s] 开始下载.下载范围:%s-%s."%(_id, startpos, endpos))
	with open("%s-%s" % (savepath, _id), 'wb') as sf:
		n = 0
		while download_num > n:
			sf.write(reqfile.read(cachesize)) #读取并写入到文件中
			n += 1
		if not end_download_size == 0: #还有剩余部分
			sf.write(reqfile.read(end_download_size)) #读取写入
	print("下载完成")

上面就是下载函数,需要提供

startpos 下载起点
endpos 下载终点
_id 线程ID

原理是

Created with Raphaël 2.2.0 线程 请求缓存大小的文件部分 写入文件 是否线程读取完毕 保存并退出线程 yes no

有了线程执行的函数,剩下需要的是开启线程的部分

req = urlopen(Request(url))
filesize = int(req.headers['content-length'])
thread_size = filesize // threadnum #每个线程下载的大小

for i in range(threadnum): #开启线程
	x = Thread(target=download, args=(i*thread_size, (i+1)*thread_size, i))
	x.start()
	threadpool.append(x)

Easy.

你可能感兴趣的:(Python,多线程,python,多线程)