使用Python进行HTTP请求的5种方法

252 阅读6分钟

当涉及到软件开发时,几乎总是有几种不同的方法来实现相同的结果。在评估一系列第三方软件包时也是如此。例如,在Python生态系统中,有成千上万个与发出HTTP 请求有关的软件包。你应该使用哪一个呢?

在这个基于实验的教程中,我们将通过简短的代码片断,展示如何使用5个Python最流行的请求相关软件包来进行简单的GET请求。我们将使用 NASA 的 Astronomy Photo of the Day API(在本教程的其余部分简称APOD)并在我们的网络浏览器中打开今天的照片。

前提条件

找到 NASA 的演示 API 密钥

导航到api.nasa.gov/。你会在认证部分看到,你不需要一个独特的API密钥来探索NASA的数据集。如果你想创建一个,请按照网页上的指示,使用你得到的API密钥,而不是我们将要使用的DEMO_KEY。

DEMO**_KEY的速率限制是每小时30个请求,每天50个请求,在同一网页的DEMO_KEY速率限制**部分有解释。在跟随我们的HTTP请求实验时,你应该能够很好地保持在这些限制之内。NASA网页的这一部分还指出,字符串 "DEMO_KEY "可以用来代替真正的API密钥值,所以这就是我们在本教程中要使用的。

找到APOD API的URL端点

我们要发送HTTP请求的URL是api.nasa.gov/planetary/a…你可以通过向下滚动到api.nasa.gov/网页的浏览API部分并打开APOD的下拉菜单来找到它。

A screenshot of NASA's APOD detail page

如果你阅读APOD下拉菜单中显示的简要信息,你会发现这个端点只接受GET方式。这一点很重要,因为我们需要为我们要发送的5个不同的HTTP请求中的每一个都专门向端点发出一个GET请求。

创建 Python 虚拟环境

在你的计算机上的一个合适的位置为这个项目创建一个名为python-http/ 的新目录,然后导航到这个新目录。在这个例子中,我们将使用 MacBook 的桌面,并从命令行创建文件:

$ cd ~/Desktop
$ mkdir python-http
$ cd python-http

为这个项目创建一个新的虚拟环境,这样我们需要安装的依赖项就不会干扰到你电脑上的全局设置。要创建一个名为 "env "的新环境,在命令行上运行以下命令:

$ python3 -m venv env 
$ source env/bin/activate

在你为虚拟环境提供源码之后,你会看到你的命令提示符的输入行以环境的名称 ("env") 开始。Python 在*python-http/目录下创建了一个名为env/*的新文件夹,你可以通过在命令提示符下运行 ls 命令来看到它。

python-http/目录中也创建一个名为.gitignore的文件。如果你在 Mac 上使用命令行来创建该文件,这将是一个命令:

(env) $ touch .gitignore

在你选择的文本编辑器中打开.gitignore文件,然后在.gitignore文件的内容中加入env/文件夹。在这里,我们还将为我们将在下一节中创建的.env*文件添加一行:

env/
.env

注意,Python 为虚拟环境创建的env/文件夹与为存储 API 密钥和环境变量等秘密而创建的.env文件不是一回事。

安全地存储环境变量

API密钥是敏感信息,应该被保护起来。因此,将API密钥保存为环境变量,而不是将其硬编码到你的应用程序中,这被认为是一种最佳做法。即使NASA的演示API密钥值("DEMO_KEY")是公开的,我们也要遵循这一最佳实践。

要做到这一点,我们可以将API密钥存储在一个*.env文件中,并在我们的.gitignore文件中列出.env文件(我们已经在上面做了),这样git就不会跟踪它。当有环境变量需要提供给你的操作系统时,就会用到.env*文件。

首先,创建*.env*文件。这是在Mac的命令行上运行的命令:

(env) $ touch .env

接下来,在你喜欢的文本编辑器中打开*.env*文件,并添加以下一行:

export NASA_API_KEY=DEMO_KEY

源化*.env*文件,使其对你的操作系统可用,然后将环境变量值打印到你的控制台,以确认它被成功地源化了:

(env) $ source .env
(env) $ echo $NASA_API_KEY

安装Python依赖项

除了包含在Python标准库中的urllib 模块外,我们将在HTTP请求实验中使用的第三方Python包是:

  • requests- 很容易成为使用 Python 进行请求的最流行的软件包
  • urllib3- 不要与urllib 相混淆,它是 Python 标准库的一部分。
  • httplib2- 填补了其他库留下的一些空白
  • httpx- 一个较新的软件包,提供HTTP/2和异步请求。

Python 项目所需的依赖性通常被列在一个叫做requirements.txt 的文件中。在python-http/项目目录下创建一个requirements.txt文件:

(env) $ touch requirements.txt

使用你喜欢的文本编辑器将这个 Python 包的列表复制并粘贴到你的requirements.txt文件中:

requests
urllib3
httplib2
httpx

用下面的命令安装所有的依赖项,确保你仍然有你的虚拟环境 ("env") 的资源:

(env) $ pip install -r requirements.txt

创建Python文件

现在是写代码的时候了!让我们首先为我们要实验的每个模块或包创建一个 Python 文件:

(env) $ touch use_requests.py
(env) $ touch use_urllib3.py
(env) $ touch use_httplib2.py
(env) $ touch use_httpx.py
(env) $ touch use_urllib.py

下面提供了我们创建的5个不同文件的代码例子。你也可以在这个GitHub资源库中查看整个项目的情况。

为了使例子更加健壮和有用,我们将使用两个内置的Python模块,叫做jsonwebbrowser,这样我们就可以在web浏览器中打开当天的天文图片了。

探索用Python进行HTTP请求的5种流行方式

5之1:请求

用于Python的requests包是如此受欢迎,以至于它目前是100多万个GitHub仓库的需求,而且多年来它的代码库已经有近600个贡献者!它是一个非常受欢迎的包。这个包的清晰简洁的文档几乎可以肯定是它被广泛使用的原因。

复制并粘贴这个代码片段到use_requests.py文件中:

import json
import os
import webbrowser

import requests


nasa_api_key = os.environ.get('NASA_API_KEY')
api_url = 'https://api.nasa.gov/planetary/apod?api_key={}'.format(nasa_api_key)

def use_requests(api_url):

    response = requests.get(api_url)
    json_response = json.loads(response.text)
    photo_url = json_response['url']
    webbrowser.open_new_tab(photo_url)

    return

use_requests(api_url)

在上面的示例代码中,我们首先导入所有我们需要的模块和包。然后,我们检索我们存储在*.env*文件中的API密钥(第8行),并将其插入我们要发送GET请求的URL中(第9行)。第13行是我们使用Requests库的地方,你可以看到其语法是多么简单。从API的响应中分离出照片的URL后,我们在第16行在网络浏览器中打开它。

因为在文件的底部包含了一个函数调用,你可以运行这个文件,照片应该会自动在你的网络浏览器中打开在你的命令行中运行该文件,自己试试吧:

(env) $ python3 use_requests.py

2 of 5: urllib3

尽管名字相似,urllib3是一个第三方软件包,与 urllib 完全不同,后者是 Python 标准库的一部分。有超过65万个GitHub资源库将urllib3列为需求,这使得它成为Requests库的一个大规模的替代方案。

复制并粘贴这段代码到use_urllib3.py文件:

import json
import os
import webbrowser

import urllib3


nasa_api_key = os.environ.get('NASA_API_KEY')
api_url = 'https://api.nasa.gov/planetary/apod?api_key={}'.format(nasa_api_key)

def use_urllib3(api_url):

    http = urllib3.PoolManager()
    response = http.request('GET', api_url)
    json_response = json.loads(response.data)
    photo_url = json_response['url']
    webbrowser.open_new_tab(photo_url)

    return

use_urllib3(api_url)

在上面的示例代码中,我们首先导入我们需要的所有模块和包。然后,我们检索存储在*.env*文件中的API密钥(第8行),并将其插入我们要发送GET请求的URL中(第9行)。在第13行和第14行,我们利用urllib3包,然后处理响应以提取照片的URL并在网络浏览器中显示。

因为文件的底部包含了一个函数调用,你可以运行这个文件,并确保它的工作。

提示:如果你在尝试运行该文件时遇到类似[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate 的错误,请按照StackOverflow线程的步骤来解决:

(env) $ python3 use_urllib3.py

5之3:httplib2

httplib2包是86,000个GitHub存储库的要求。httplib2的使用远远落后于Requests和urllib3包,但httplib2填补了这两个更广泛使用的替代品所留下的一些空白。例如,httplib2支持持久化连接和缓存。

下面是一个简单的例子,说明你如何在你的项目中使用httplib2。复制并粘贴以下代码到use_httplib2.py

import json
import os
import webbrowser

import httplib2


nasa_api_key = os.environ.get('NASA_API_KEY')
api_url = 'https://api.nasa.gov/planetary/apod?api_key={}'.format(nasa_api_key)

def use_httplib2(api_url):

    http = httplib2.Http()

    # The response is sent as a 2-item tuple, with the content at index 1
    response = http.request(api_url)
    json_response = json.loads(response[1])
    photo_url = json_response['url']
    webbrowser.open_new_tab(photo_url)

    return

use_httplib2(api_url)

在上面的示例代码中,我们首先导入所有我们需要的模块和包。然后,我们检索我们存储在*.env*文件中的API密钥(第8行),并将其插入我们要发送GET请求的URL中(第9行)。在第13行和第16行,我们利用httplib2包,然后处理响应以提取照片的URL并在网络浏览器中显示。

因为在文件的底部包含了一个函数调用,所以你可以运行这个文件并确保它的工作:

(env) $ python3 use_httplib2.py

4 of 5: httpx

httpxPython包是我们列表中最新的一个。除了标准的同步HTTP/1协议外,它还支持HTTP/2协议异步请求。它的构建非常 "类似于Requests",反映了Requests包(我们涉及的第一个包)中的许多代码模式。

要尝试一下httpx,请复制并粘贴以下代码到use_httpx.py文件:

import json
import os
import webbrowser

import httpx


nasa_api_key = os.environ.get('NASA_API_KEY')
api_url = 'https://api.nasa.gov/planetary/apod?api_key={}'.format(nasa_api_key)

def use_httpx(api_url):

    request = httpx.get(api_url)
    json_request = request.json()
    photo_url = json_request['url']
    webbrowser.open_new_tab(photo_url)

    return

use_httpx(api_url)

在上面的示例代码中,我们首先导入所有我们需要的模块和包。然后,我们检索我们存储在*.env*文件中的API密钥(第8行),并将其插入我们要发送GET请求的URL中(第9行)。第13行是我们使用httpx库的地方,你可以看到语法是多么简单。从API的响应中分离出照片的URL后,我们在第16行的网页浏览器中打开它。

因为在文件的底部包含了一个函数调用,你可以运行这个文件,照片应该会自动在你的网络浏览器中打开!在你的CLI中运行该文件,自己试试:

(env) $ python3 use_httpx.py

5的5:urllib

与上面一节中使用 Requests 包进行 HTTP 请求的简单程度相比,使用 Python 内置的urllib模块要复杂一些。它需要使用一个上下文管理器以及对响应进行解码--当使用我们教程中的一个包时,这两件事通常会被开发者抽象出来。

复制并粘贴此示例代码到use_urllib.py文件中:

import json
import os
import urllib.request
import webbrowser


nasa_api_key = os.environ.get('NASA_API_KEY')
api_url = 'https://api.nasa.gov/planetary/apod?api_key={}'.format(nasa_api_key)

def use_urllib(api_url):

    request = urllib.request.Request(api_url)
    with urllib.request.urlopen(request) as response:
        data = json.loads(response.read().decode("utf-8"))
        photo_url = data['url']
        webbrowser.open_new_tab(photo_url)

    return

use_urllib(api_url)

在上面的示例代码中,我们首先导入我们需要的所有模块和包。然后,我们检索我们存储在*.env*文件中的API密钥(第7行),并将其插入我们要发送GET请求的URL中(第8行)。在第12行,我们使用urllib模块创建Request对象,在第13行,我们使用一个上下文管理器(with...)来发送请求到APOD端点并保存响应。在第14行,我们对响应进行解码并将其转换为JSON,然后在第15和16行提取照片的URL并在浏览器中打开它。

因为文件的底部包含了一个函数调用,你可以运行这个文件,并确保它的工作:

(env) $ python3 use_urllib.py

祝贺你!

在本教程中做得很好!你刚刚学会了如何:

  • 在*.env*文件中安全地存储API密钥和其他机密信息
  • 以5种不同的方式向API端点发出GET请求
  • 在网络浏览器中打开Python脚本中的图片