【作品展示】
【作品介绍】
Python下载网页文件
支持市面上几乎所有视频流
程序每句话都加了注释,
程序目前有一个BUG,我已经发现了,如果大神看到可以尝试优化,目前为单线程下载,如果人气较高我将在下期发布多线程并优化下载方法!
【作品源代码】
# -*- coding:utf-8 -*- """ 程序名:网页单文件下载-Python程序 作者:我叫以赏 To Pikachu 转载注明出处!请勿用于非法用途! 全程序已标注注释! 此Python下载程序为单线程下载,多线程看热门程度 """ import requests import urllib.parse def rettextsize(b): """ 将字节容量单位处理加单位 如 1024 B ---> 1KB :param b: 输入没有标记的内容单位(以B为单位) :return: 返回处理好的容量加单位 """ kb = b / 1024 mb = kb / 1024 gb = mb / 1024 tb = gb / 1024 if int(tb) < 1024 and int(tb) > 0: return str(round(tb, 2)) + ' TB' elif int(gb) < 1024 and int(gb) > 0: return str(round(gb, 2)) + ' GB' elif int(mb) < 1024 and int(mb) > 0: return str(round(mb, 2)) + ' MB' elif int(kb) < 1024 and int(kb) > 0: return str(round(kb, 2)) + ' KB' else: return str(b) + ' B' return str(b) + ' B' if __name__ == '__main__': print_len = 60 # 进度条打印字符长度 todo = '准备下载文件' # 初始提示信息 # 模拟浏览器访问 防止一些链接加了防止爬虫检测 ua = 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko' Fragment_size = 1024 * 1024 * 10 # 分片大小 10 MB 的下载 注意:修改此项一定程度上影响程序的稳定性与速度 print('Python单线程下载网页文件,BY我叫以赏 like Pikachu 转载注明出处!请勿用于非法用途!') # 版权信息 # 不停的循环,下载完成再次引导用户输入 while True: # ------准备代码------ Downloaded_size = 0 # 已下载大小 每次任务前清零 # ------获取文件信息代码------ try: # 进入try语句 防止获取信息出错 download_url = input( '请输入文件下载网址,下载完成的文件会保存在程序的运行目录下![请添加http(s)协议头,exit退出]:') # 引导输入URL if download_url == 'exit': # 退出代码输入 break # 检测用户是否输入带协议头 if download_url.find('http://') == -1 and download_url.find('https://') == -1: raise BaseException( 'url输入错误!您的意思是:http://' + download_url + '吗?') # 没有携带就提示 data = requests.get(download_url, stream=True, headers={ "User-Agent": ua}) # 获取文件信息 stream=True 是不获取网页内容 if 'Content-Length' in data.headers: # 检测服务器是否有返回文件大小 file_size = int(data.headers['Content-Length']) # 文件大小 else: file_size = -1 # 没有返回就将大小设为-1 if 'Content-Disposition' in data.headers: # 检测服务器是否有返回文件名 # 服务器返回文件名,获取文件初始名 file_name = data.headers['Content-Disposition'] # URL解码名称 urllib.parse.unquote() 函数我也是查询资料才知道 file_name = urllib.parse.unquote(file_name[20:]) else: file_name = download_url[download_url.rfind( '/') + 1:] # 如果服务器没有返回文件名则采取URL最后出现的文件名 if file_size != -1: # 判断文件服务器是否有返回大小(可以合并到上面) print('远程文件名:%s 文件大小:%s' % (file_name, rettextsize(file_size))) # 返回了大小正常显示 else: raise BaseException('服务器没有返回文件大小!无法进行下载!') # 服务器没有返回文件大小 except BaseException as error: # 如果出错 则提示,引导用户再一次输入 # 提示错误信息 print( '程序运行时出现错误,这可能是您URL输入错误导致的,请检查URL如果确认URL没有问题,请查看错误原因,下面使我们收集的错误信息:\n错误信息-' + str(error)) continue # ------开始下载文件代码------ try: # 加入try语句 时刻监测是否出错 # with as 语句 常用于打开文件自动关闭 这里是创建文件并写入(有则清空)已编码形式存储 with open('./' + file_name, 'wb+') as handle: while Downloaded_size < file_size: # 如果已下载大小始终小于文件大小 则不停循环 # ------请求文件内容代码------ try: # 加入try语句 时刻监测是否出错 if Downloaded_size + Fragment_size >= file_size: # 这里是防止文件大小请求超出原文件大小做出限制 header = {'range': 'bytes=' + str(Downloaded_size) + '-' + str(file_size), "User-Agent": ua} # 超出大小则采用文件大小 通过range:bytes=xx-xx请求文件内容范围 else: header = {'range': 'bytes=' + str(Downloaded_size) + '-' + str( Downloaded_size + Fragment_size), "User-Agent": ua} # 通过range:bytes=xx-xx请求文件内容范围 if Downloaded_size + 1 == file_size: # 重复检测是否下载完成 Percentage = 100 # 百分比 printage = print_len # 打印已完成符号 print('\r' + "+" * printage + '-' * (print_len - printage) + ' ' + str(Percentage) + ' % ', end=todo) # 打印进度条 break # 跳出循环 data = requests.get( download_url, headers=header) # 获取文件内容信息 handle.write(data.content) # 写到文件 Downloaded_size = Downloaded_size + \ len(data.content) # 将以下载数据添加 # 更改提示信息 提示信息为 “已下载:xx%” todo = '已下载:' + rettextsize(Downloaded_size) # 计算已下载百分比 (不是分数) Percentage = int(Downloaded_size / file_size * 100) printage = int(Downloaded_size / file_size * print_len) # 计算打印已完成符号数量 print('\r' + "+" * printage + '-' * (print_len - printage) + ' ' + str(Percentage) + ' % ', end=todo) # 打印进度条 except: # 出现错误 continue # 到循环尾部 Percentage = 100 # 百分比 printage = print_len # 打印已完成符号 print('\r' + "+" * printage + '-' * (print_len - printage) + ' ' + str(Percentage) + ' % ', end=todo) # 打印进度条 print('\n下载完成!文件保存至程序运行目录下!') # 已完成信息 except BaseException as error: # 无法打开/创建文件 print('无法创建新的文件来保存远程下载信息已终止,错误信息:' + str(error)) # 打印错误 continue # 到循环尾部