前言
在开发的过程中,难免需要文件从云端下载到本地,那么这期博客将会带你实现最简短的“文件下载”
基础过程:
1、获取URL(统一资源定位器)
1.1、找到资源
在资源页面按下 F12 打开 检查 ,转到 网络 ,按下 Ctrl + r ;
![](https://i-blog.csdnimg.cn/direct/0c8782d2815e42fb9f234b3cd90b59f0.png)
转到 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.contentcontent
通常,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)