【Python作品分享】Python下载网页文件

【作品展示】

center_image

 

【作品介绍】

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  # 到循环尾部

 

发表评论 (0)

后再参与讨论