Python实现文件的下载(包人性化的)

前言

       在开发的过程中,难免需要文件从云端下载到本地,那么这期博客将会带你实现最简短的“文件下载”

 基础过程:

     1、获取URL(统一资源定位器)

             1.1、找到资源

                         在资源页面按下 F12 打开 检查 ,转到 网络 ,按下   Ctrl + r 

                          转到 Img 选项卡,下面会有一推文件;

                         任意选中一张图片,点击 预览 

                         在确保文件无误后(如果找不到,再按一下  Ctrl + r  )找到 标头 选项卡;

                        这里有个 URL 复制下来,那么就是这个图片的 URL 了

        2、代码                        

                        只要你是 Python 的死党,看到 GET ,大概都想到了这串代码

value = requests.get(url = "image.baid.com", timeout = 10)

                        比较基础的人,还会想到

answer = value.json()

                        然后就会

Traceback (most recent call last):
  File "
D:\anaconda3\Lib\site-packages\requests\models.py", line 971, in json
    return complexjson.loads(self.text, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "
D:\anaconda3\Lib\json\__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "
D:\anaconda3\Lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "
D:\anaconda3\Lib\json\decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "
D:\python's files\files\24.py", line 3, in <module>
    requests.get(url=" https://image.baidu.com").json()
  File "
D:\anaconda3\Lib\site-packages\requests\models.py", line 975, in json
    raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

 

                         这是因为你在发送请求后,返回了一个非 json 文件,而代码却进行 json 解析,导致异常,就好比用记事本打开EXE文件一样,只不过 Python 不会显示乱码,而是直接报错。

                        那么我们开始讲解正确的代码:

                2.1、请求

                         请求其实很简单,会的都会

value = requests.get(url="https://
img2.baidu.com/it
/u=3120740051,3325812766&fm
=253&fmt=auto&app=138&f=JPEG?
w=600&h=240")

               2.2、 返回

                          2.2.1、打开

                                        这里首先得打开一个文件用以保存下载的文件

                                        (注意后缀名以及文件名,文件名可以自定,后缀不能改

#                  这里是文件的保存路径以及文件名     打开模式为wb
with open(file="../data/webfile/down/图片1.png", mode="wb") as down:
    down.write(...)
                        2.2.2、写入

                                        你可以想象一下,既然下载了一个文件,那么如果不能解析,那么可不可以直接把文件写入文件呢?答案是当然,这里认识一个变量,他叫

                        requests.Response.content

                                                           content

                                        通常,get(url)的返回值就是  requests.Response 类型,而至于content,你可以理解为一个文件,现在你需要将他写入本地文件;

#                这里是文件的保存路径以及文件名     打开模式为wb
with open(file="../data/webfile/down/图片1.png", mode="wb") as down:
    down.write(value.content)
                        2.2.3、关闭

                                        如果你没用 with open,那么则需要关闭文件以释放资源 

down.close()

                2.3、全部代码

import requests

value = requests.get(url="https://img2.baidu.com/it/
u=3120740051,3325812766&fm=253&fm
t=auto&app=138&f=JPEG?w=600&h=240")

#                这里是文件的保存路径以及文件名     打开模式为wb
with open(file="../data/webfile/down/图片1.png", mode="wb") as down:
    down.write(value.content)
    down.close()

3、扩展

        这里的代码主要是实现用 Python 实现一个简易的人性化下载器(总之比p2p下崽器好用)

        3.1 判断网络部分

                涉及网络请求的项目总会有一些烦人的地方,例如 url错误、网络断开,这些会导致程序崩溃,从而降低使用的体验。

                3.1.1检查网络

                        通过 socket 库,检查网络(这里的代码是从另一位博客里抄的借鉴的,如果您是作者,请私信我(wei14785050252@126.com))

def isNetChainOK(testserver=('www.baidu.com', 443)):
    import socket
    s = socket.socket()

    s.settimeout(3)
    # noinspection PyBroadException
    try:
        status = s.connect_ex(testserver)
        if status == 0:
            s.close()
            return True
        else:
            return False
    except Exception as e:
        return False

                3.1.2检查URL是否存在

                                利用常规请求,如果抛出异常,则认为URL不存在

def CheckUrl(url: str):
    import requests
    
    try:
        requests.get(url)
    except requests.exceptions.MissingSchema:
        return False
    else:
        return True

        3.2 键入URL部分

                3.2.1导入easygui和tkinter中的messagebox

import easygui
from tkinter import messagebox

                3.2.2询问用户url

url = easygui.enterbox(msg="下载器", title="请输入URL")

        3.3文件保存部分

                如果你能保证下载的类型或你有办法通过网址弄到后缀,你可以这样写

from tkinter import filedialog
file_type = [("图片文件", ("*.png", "*.jpg", "*.gif", "*.JPEG"))]
save_load = filedialog.asksaveasfilename(title="图片下载器", filetypes=file_type)

                如果是通用下载器,则这样写

from tkinter import filedialog

file_type = [("图片文件", ("*.png", "*.jpg", "*.gif", "*.JPEG")),
             ("文本文档", "*.txt"),
             ("工作文档(doc)", ("*.docx", "*.doc", "*.dot", "*.dotx", "*.rtf")),
             ("工作文档(excel)", ("*.xls", "*.xlsx", "*.et")),
             ("工作文档(ppt)", ("*.pptx", "*.ppt")),
             ("PDF文档", "*.pdf"),
             ("应用程序", ("*.exe", "*.cmd", "*.bat")),
             ("压缩包文件", ("*.zip", "*.rar", "*.jar", "*.gz")),
             ("代码文件", ("*.cpp", "*.py", "*.h")),
             ("系统文件(win)", ("*.sys", "*.dll")),
             ("其他文件", "*.*")]
save_load = filedialog.asksaveasfilename(title="下载器", filetypes=file_type)

        3.4日志部分

                如果希望记录日志,先写上下面这些函数+变量

import time
import os

diary_save_path = r"./diary/"
diary_save_name = str(time.strftime("%Y%m%d%H%M%S", time.localtime()))+'.log'
if os.path.exists('./diary') is False:
    os.mkdir(path='./diary')

logfile = open(file=diary_save_path + diary_save_name, mode='a', encoding='utf-8')


def log(Logfile=logfile, thing: str = "", note: str = '全局'):
    when = time.perf_counter()
    when_ = str(when)
    Logfile.write('[' + when_ + '][' + note + ']' + thing + '\n')


def yz_log(logFile: str):
    with open(file=logFile, mode='w', encoding='utf-8') as logFile_:
        logFile_.write('[BE]')
    time.sleep(1)
    with open(file=logFile, mode='r', encoding='utf-8') as logFile_:
        a = logFile_.read()
        if a == '[BE]':
            log(thing='日志出现输出,程序启动')
        else:
            import sys
            sys.exit()


yz_log(logFile=diary_save_path+diary_save_name)

                需要记录时,调用

log(thing = "事件", note="事件所属的种类")
#具体写法见全部代码

        3.5 计时

                这里不细说,上代码

start_time = time.perf_counter()
#你的代码
end_time = time.perf_counter()
spend_time = (end_time - start_time) * 1000
#这是消耗的时间

       全部代码

import requests
from tkinter import messagebox
import easygui
import sys
import time
import os

diary_save_path = r"./diary/"
diary_save_name = str(time.strftime("%Y%m%d%H%M%S", time.localtime())) + '.log'
if os.path.exists('./diary') is False:
    os.mkdir(path='./diary')

logfile = open(file=diary_save_path + diary_save_name, mode='a', encoding='utf-8')


def log(Logfile=logfile, thing: str = "", note: str = '全局'):
    when = time.perf_counter()
    when_ = str(when)
    Logfile.write('[' + when_ + '][' + note + ']' + thing + '\n')


def yz_log(logFile: str):
    with open(file=logFile, mode='w', encoding='utf-8') as logFile_:
        logFile_.write('[BE]')
    time.sleep(1)
    with open(file=logFile, mode='r', encoding='utf-8') as logFile_:
        a_ = logFile_.read()
        if a_ == '[BE]':
            log(thing='日志出现输出,程序启动')
        else:
            import sys
            sys.exit()


yz_log(logFile=diary_save_path + diary_save_name)


def CheckUrl(url_: str) -> bool:
    import requests

    try:
        requests.get(url_)
    except requests.exceptions.MissingSchema:
        log(thing="URL不存在", note="URL检查")
        return False
    else:
        log(thing="URL存在", note="URL检查")
        return True


def isNetChainOK(testserver=('www.baidu.com', 443)) -> bool:
    import socket
    s = socket.socket()
    s.settimeout(3)
    # noinspection PyBroadException
    try:
        status = s.connect_ex(testserver)
        if status == 0:
            s.close()
            log(thing="网络连接检查已通过", note="网络检查")
            return True
        else:
            log(thing="网络未连接", note="网络检查")
            return False
    except Exception:
        log(thing="网络未连接", note="网络检查")
        return False


url = easygui.enterbox(title="下载器", msg="请输入URL")
log(thing="用户输入了URL")

if isNetChainOK() is False:
    messagebox.showerror(title="下载器", message="网络未连接")
    log(thing="程序异常退出")
    sys.exit()
a = 1
while CheckUrl(url) is False:
    a += 1
    log(thing=f"用户第{a}次输入URL", note="URL检查")
    messagebox.showwarning(title="下载器", message="URL错误或未找到")
    url = easygui.enterbox(title="下载器", msg="请输入URL")
from tkinter import filedialog

file_type = [("图片文件", ("*.png", "*.jpg", "*.gif", "*.JPEG")),
             ("文本文档", "*.txt"),
             ("工作文档(doc)", ("*.docx", "*.doc", "*.dot", "*.dotx", "*.rtf")),
             ("工作文档(excel)", ("*.xls", "*.xlsx", "*.et")),
             ("工作文档(ppt)", ("*.pptx", "*.ppt")),
             ("PDF文档", "*.pdf"),
             ("应用程序", ("*.exe", "*.cmd", "*.bat")),
             ("压缩包文件", ("*.zip", "*.rar", "*.jar", "*.gz")),
             ("代码文件", ("*.cpp", "*.py", "*.h")),
             ("系统文件(win)", ("*.sys", "*.dll")),
             ("其他文件", "*.*")]
save_load = filedialog.asksaveasfilename(title="下载器", filetypes=file_type)
log(thing=f"用户选择了保存路径,在{save_load}", note="保存")
log(thing=f"开始请求URL,URL={url}", note="请求")
# noinspection PyBroadException
try:
    start_time = time.perf_counter()
    save_file = requests.get(url, timeout=10)
except:
    log(thing="请求失败", note="请求")
else:
    end_time = time.perf_counter()
    spend_time = (end_time-start_time)*1000
    log(thing=f'请求成功,耗时{spend_time}', note="请求")
    # noinspection PyBroadException
    try:
        with open(file=save_load, mode='wb') as d:
            log(thing="开始向保存文档写入文件", note="保存")
            start_time = time.perf_counter()
            d.write(save_file.content)
            end_time = time.perf_counter()
        spend_time = (end_time-start_time)*1000
        spend_space = os.path.getsize(save_load)
        v = spend_space/spend_time
        log(thing=f"写入完成,耗时{spend_time},大小{spend_space},传输速度{v}", note="保存")
    except:
        log(thing="写入失败", note="保存")
log(thing="程序正常退出")

最后,写作不易,请多多关照,如有侵权,请私信(联系方式 wei14785050252@126.com)

  • 23
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值