使用 python urllib 模块发出 Web 请求。
urllib模块是内置于Python标准库中的标准模块,允许用户使用URL(统一资源定位器)。可以用它做很多简洁的事情,例如访问API资源,发出不同类型的HTTP请求,如GET,POST,PUT,DELETE等。
如何使用 urllib 模块来访问 API 资源。使用 JsonPlaceholder进行虚拟的 REST API 调用,这是一个非常简洁的工具。
import urllib.request
向 google.com 提出请求,看看得到了什么。
import urllib.request
with urllib.request.urlopen("https://www.google.com/") as url:
print(url.read(300))
在这里,使用了一个上下文管理器,它可以优雅地处理 url 的打开和关闭。urlopen() 函数返回一个字节对象,打印它的前 300 个字节。
b'<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en-IN"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script nonce="j2RUvuN1fVmpA'
[Finished in 7.3s]
如果知道字节对象的编码,可以打印字符串结果。在上述输出的元标记中可以清楚地看到编码是utf-8。
import urllib.request
with urllib.request.urlopen("https://www.google.com/") as url:
print(url.read(300).decode("utf-8"))
上面的代码现在将一个 utf-8 解码字节对象作为字符串返回,如果我们需要对它做一些事情,可以稍后解析它。
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en-IN"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script nonce="MnpsG49CZsHqd
[Finished in 2.0s]
获取请求。
GET 请求用于从 URL 终结点检索特定资源。让向 JsonPlaceholder API 发出一个 GET 请求来获取一些待办事项。
import urllib.request
req = urllib.request.Request(url = 'https://jsonplaceholder.typicode.com/todos/1')
with urllib.request.urlopen(req) as resp:
print(resp.read().decode('utf-8'))
在这里,将 url 参数传递给 urllib.request 上定义的 Request 方法。读取响应对象并对其进行解码。如果仔细检查代码,由于我们不指定任何数据参数(这基本上意味着它是 None),因此该方法默认为 GET。
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
}
[Finished in 4.5s]
这里的输出实际上看起来像一个带有键值对的 python 字典,但现实是它只是一个字符串。可以通过将解码的响应对象包装在 type() 中来验证它,并查看其类型为 string。
如果需要访问此响应对象的各种键值对,需要使用 json.loads() 方法解析它,需要 json 模块
import json
import urllib.request
# We can now control the number of todos we want to be returned.
num_of_todos = 1
req = urllib.request.Request(url=f'https://jsonplaceholder.typicode.com/todos/{num_of_todos}')
with urllib.request.urlopen(req) as resp:
data = json.loads(resp.read().decode("utf-8"))
print(data)
print(type(data))
print(data["title"])
现在返回的数据确实是一个python字典,可以像往常一样访问键值对。
{'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False}
<class 'dict'>
delectus aut autem
[Finished in 1.7s]
开机自检请求。
将一些数据发送到服务器以创建或更新资源时,使用 POST 方法。
import json
import urllib.request
# This is our Todo
data = {
"userId": 101,
"id": 100,
"title": "This is a POST request",
"completed": True
}
# Dump the todo object as a json string
data = json.dumps(data)
req = urllib.request.Request(url = 'https://jsonplaceholder.typicode.com/todos/', data = bytes(data.encode("utf-8")), method = "POST")
# Add the appropriate header.
req.add_header("Content-type", "application/json; charset=UTF-8")
with urllib.request.urlopen(req) as resp:
response_data = json.loads(resp.read().decode("utf-8"))
print(response_data)
一个包含必要键值对的 python 字典。将其转储为 JSON 字符串。将数据作为字节对象传递给 Request 方法的数据参数。 将 Content-type 标头添加为 application/json,这表示希望发布的数据是 JSON 对象。读取和解码响应对象并打印它。
{'userId': 101, 'id': 201, 'title': 'This is a POST request', 'completed': True}
[Finished in 2.0s]
放置请求。
需要修改服务器上的某个资源, 使用 PUT 请求。
import json
import urllib.request
# This is our Todo
data = {
"userId": 1,
"id": 1,
"title": "This is a PUT request",
"completed": False
}
# Dump the todo object as a json string
data = json.dumps(data)
req = urllib.request.Request(url = 'https://jsonplaceholder.typicode.com/todos/1', data = bytes(data.encode("utf-8")), method = "PUT")
# Add the appropriate header.
req.add_header("Content-type", "application/json; charset=UTF-8")
with urllib.request.urlopen(req) as resp:
response_data = json.loads(resp.read().decode("utf-8"))
print(response_data)
大部分代码保持不变。唯一的区别是 将方法指定为 PUT
{'userId': 1, 'id': 1, 'title': 'This is a PUT request', 'completed': False}
[Finished in 2.0s]
删除请求
删除服务器上的特定资源, 使用 DELETE 请求。
import json
import urllib.request
req = urllib.request.Request(url = 'https://jsonplaceholder.typicode.com/todos/1', method = "DELETE")
with urllib.request.urlopen(req) as resp:
response_data = json.loads(resp.read().decode("utf-8"))
print(response_data)
只需将方法指定为 DELETE 要删除的待办事项(即 /todos/1)。
{}
[Finished in 2.6s]
响应是一个空对象, 已经成功删除了待办事项。