005 requests的基础使用-下载文件
1、常规下载
用requests模块的get方法获取URL,并将结果存储到一个名为“file”的变量中。然后,将这个变量的内容写入目标文件。
#coding = utf-8 import requests url = "https://www.python.org/static/img/python-logo@2x.png" file = requests.get(url) open('C:\\Users\\Downloads\\python\\img.png', 'wb').write(file.content)
执行成功后,在文件夹下能够查看到已下载的图片

注意:open函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写
open(name[, mode[, buffering]])
-
name : 一个包含了你要访问的文件名称的字符串值。
如果不写文件名只填写目录,执行时会报错的,如下
C:\Users\PycharmProjects\myProject\venv\Scripts\python.exe C:/Users/PycharmProjects/myProject/main.py Traceback (most recent call last): File "C:\Users\PycharmProjects\myProject\main.py", line 6, in <module> open('C:\\Users\\Downloads\\python', 'wb').write(file.content) FileNotFoundError: [Errno 2] No such file or directory: 'C:\\Users\\Downloads\\python' Process finished with exit code 1
2、下载大文件(分块/流下载)
如何用requests.get()请求一个太大的文件?
若下载到一半暂停了,想继续下载怎么办?
若有个大文件有多人同时请求,对服务器造成大压力怎么办?
采用分块下载文件,每次从服务器中读取固定大小的文件,会大大的缓解了多人访问时给服务器带来的压力。
我们可以这样做,在get()方法里面加一个参数stream=True,即:
requests.get(url,stream=True)
如果不加stream=True,那么你的硬盘很可能就不停被写入,文件会变得无比巨大,最后磁盘空间不够死机。不要问我为什么知道。
当stream=True时,后边需要自己执行Response.close()操作进行关闭结束,否则只有所有的响应体数据被读取完毕连接才会被释放,用with即可以不用close()。
当stream=True时,get请求会先建立连接,而不会把content内容或text内容下载到内存里,等开始对content操作的时候,get请求这个时候才开始下载数据。
当stream=True时,如果是下载大的文件时,用True可以先对请求的类型进行判断,如果是大文件,可以中止请求,而不用浪费大流量开销。
接着,我们在当前工作目录中创建一个名为python1.pdf的文件,并打开它进行写入。
然后,我们指定每次要下载的块大小。我们已经将其设置为1024000字节(即1MB),接着遍历每个块,并在文件中写入这些块,直到块结束。
#coding = utf-8 import requests url = "https://readthedocs.org/projects/python-guide/downloads/pdf/latest/" file = requests.get(url, stream=True) with open('C:\\Users\\Downloads\\python\\python1.pdf', 'wb') as fp: for item in file.iter_content(1024000):
print("1")
fp.write(item)
通过执行完的结果可以看出,文件是分批下载的
C:\Users\PycharmProjects\myProject\venv\Scripts\python.exe C:/Users/PycharmProjects/myProject/main.py 1 1 1 1 1 Process finished with exit code 0
3、分段请求数据
#coding = utf-8 import json import requests """ 目标数据分两段 每次使用多次取回 注意:每次写入数据的时候,设置光标的位置,防止文件损坏 """ url = "https://readthedocs.org/projects/python-guide/downloads/pdf/latest/" file_name = 'C:\\Users\\Downloads\\python\\python1.pdf' file = open(file_name, 'wb') def download_size(start, end): #按照文件大小下载 headers = { "Range": f'bytes={start}-{end}' } r = requests.get(url, stream=True, headers=headers) print(r.headers) pos = start for i in r.iter_content(chunk_size=1024): if i: file.seek(pos) file.write(i) pos += 1024 def download_line(): #按照文件行数下载 r = requests.get(url, stream=True) lines = r.iter_lines() for line in lines: if line: file.write(line) #获取资源大小 r2 = requests.get(url, stream=True) max = r2.headers['content-length'] #分两段来下载download_size(0, 1024000)download_size(1024000, int(max)) # download_line() file.close()
4、下载多个文件(并行/批量下载)
即多线程下载,代码如下
#coding = utf-8 import json import threading import requests """ 目标数据分两段 每次使用多次取回 注意:每次写入数据的时候,设置光标的位置,防止文件损坏 """ url = "https://readthedocs.org/projects/python-guide/downloads/pdf/latest/" file_name = 'C:\\Users\\Downloads\\python\\python1.pdf' file = open(file_name, 'wb') def download_size(start, end): print("start", start) print("end", end) headers = { "Range": f'bytes={start}-{end}' } r = requests.get(url, stream=True, headers=headers) # print(r.headers) pos = start for i in r.iter_content(chunk_size=1024):#指定文件大小 if i: file.seek(pos) #可以将文件游标移动到文件的任意位置 file.write(i) pos += 1024#获取资源大小 r2 = requests.get(url, stream=True) size = int(r2.headers['content-length']) #分两段来下载 download_size(0, 1024000) download_size(1024000, int(size)) thread_num = 4 for i in range(thread_num): if i == thread_num-1: t1 = threading.Thread(target=download_size, args=(i * (size//thread_num), size)) t1.start() else: t1 = threading.Thread(target=download_size, args=(i * (size//thread_num), (i + 1) * (size//thread_num))) t1.start() #file.close()
报错1
TypeError: unsupported operand type(s) for //: 'str' and 'int'
通过打印发现size是str类型的,做了类型转换后正常
size = int(r2.headers['content-length'])
报错2
Exception in thread Thread-4 (download_size): Traceback (most recent call last): File "C:\Users\caobaoling\Python310\lib\threading.py", line 1016, in _bootstrap_inner self.run() File "C:\Users\caobaoling\Python310\lib\threading.py", line 953, in run self._target(*self._args, **self._kwargs) File "C:\Users\caobaoling\PycharmProjects\myProject\requests_stream.py", line 27, in download_size file.seek(pos) #可以将文件游标移动到文件的任意位置 ValueError: seek of closed file
查看代码,file文件被close掉了,注释后正常
5、下载重定向的文件
若要下载的文件,会被重定向到另一个带有一个.pdf文件的URL,如:https://readthedocs.org/projects/python-guide/downloads/pdf/latest/
同第一种下载文件的方式相同,在get方法中添加参数allow_redirects并设置为True,重定向后的内容将被分配给变量myfile。
最后,我们打开一个文件来写入获取的内容。
#coding = utf-8
import requests
url = "https://readthedocs.org/projects/python-guide/downloads/pdf/latest/"
file = requests.get(url, allow_redirects=True)
open('C:\\Users\\Downloads\\python\\python.pdf', 'wb').write(file.content)
下载完成
参考:https://blog.csdn.net/tscaxx/article/details/123219346
https://blog.csdn.net/weixin_39626927/article/details/110515317https://www.jb51.net/article/237260.htm

浙公网安备 33010602011771号