>>> from env_helper import info; info()
页面更新时间: 2023-04-15 22:00:06
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-7-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

4.2. requests 模块从Web下载文件

requests 模块让你很容易从Web下载文件, 不必担心一些复杂的问题,诸如网络错误、 连接问题和数据压缩。 requests 模块不是 Python自带的,所以必须先安装。通过命令行, 运行 pip install requests (附录A详细介绍了如何安装第三方模块)。

编写 requests 模块是因为Python的 urllib2 模块用起来太复杂。实际上,请拿一支记号笔涂黑这一段。 忘记我曾提到 urllib2 。如果你需要从Web下载东西, 使用 requests 模块就好了。

接下来,做一个简单的测试,确保 requests 模块 已经正确安装。在交互式环境中输入以下代码:

>>> import requests

如果没有错误信息显示, requests 模块就已经安装成功了。

4.2.1. requests.get() 函数下载一个网页

requests.get() 函数接受一个要下载的URL字符串。 通过在 requests.get() 的返回值上调用 type() 你可以看到它返回一个 Response 对象, 其中包含了Web服务器对你的请求做出的响应。 稍后我将更详细地解释 Response 对象,但现在请在交互式环境中输入以下代码,并保持计算机与因特网的连接:

>>> import requests
>>> res = requests.get('http://www.gutenberg.org/cache/epub/1112/pg1112.txt')
>>> type(res)
requests.models.Response
>>> res.status_code == requests.codes.ok
True
>>> len(res.text)
179380
>>> print(res.text[ :250])
The Project Gutenberg EBook of Romeo and Juliet, by William Shakespeare


***************************************************************
THIS EBOOK WAS ONE OF PROJECT GUTENBERG'S EARLY FILES PRODUCED AT A
TIME WHEN PROOFING METHODS AND TOO

该 URL 指向一个文本页面,其中包含整部罗密欧与朱丽叶, 它是由古登堡计划提供的。 通过检查 Response 对象的 status_code 属性,你可以了解对这个网页的请求是否 成功。如果该值等于 requests.codes.ok ,那么一切都好 (顺便说一下,HTTP协议中“OK”的状态码是200。你可能 已经熟悉404状态码,它表示“没找到”)。

如果请求成功,下载的页面就作为一个字符串,保存在 Response 对象的 text 变量中。这个变量保存了 包含整部戏剧的一个大字符串,调用 len(res.text) 表明, 它的长度超过178000个字符。最后, 调用 print(res.text[:250])显示前250个字符。

4.2.2. 检查错误

正如你看到的, Response 对象有一个 status_code 属性,可以检查它是否等于 requests.codes.ok ,了解下载是否成功。 检查成功有一种简单的方法,就是在 *Response 对象上调用 raise_for_status() 方法。如果下载 文件出错,这将抛出异常。如果下载成功,就什么 也不做。 在交互式环境中输入以下代码:

>>> res = requests.get('http://inventwithpython.com/page_that_does_not_exist')
>>> res.raise_for_status()
---------------------------------------------------------------------------

HTTPError                                 Traceback (most recent call last)

Cell In [7], line 2
      1 res = requests.get('http://inventwithpython.com/page_that_does_not_exist')
----> 2 res.raise_for_status()


File /usr/lib/python3/dist-packages/requests/models.py:1021, in Response.raise_for_status(self)
   1016     http_error_msg = (
   1017         f"{self.status_code} Server Error: {reason} for url: {self.url}"
   1018     )
   1020 if http_error_msg:
-> 1021     raise HTTPError(http_error_msg, response=self)


HTTPError: 404 Client Error: Not Found for url: http://inventwithpython.com/page_that_does_not_exist

raise_for_status() 方法是一种很好的方式,确保程序在下载失败时停止。 这是一件好事:你希望程序在发生未预期的错误时,马上停止。 如果下载失败对程序来说不够严重,可以用 tryexcept 语句将 raise_for_status() 代码行包裹起来, 处理这一错误,不让程序崩溃。

>>> res = requests.get('http://inventwithpython.com/page_that_does_not_exist')
>>> try:
>>>     res.raise_for_status()
>>> except Exception as exc:
>>>     print('There was a problem: %s' % (exc))
There was a problem: 404 Client Error: Not Found for url: http://inventwithpython.com/page_that_does_not_exist

这次 raise_for_status() 方法调用导致程序输出以上内容。

总是在调用 requests.get() 之后再调用 raise_for_status() 。 你希望确保下载确实成功,然后再让程序继续。