Python学习之——HTTP协议的一些概念以及Python库Requests
1 HTTP的概述
当客户端使用web页面时,浏览器会向页面所在的服务器发送HTTP请求。服务器试图在默认情况下找到所需的资源。如果您的请求成功,服务器将以一个HTTP响应的形式发送对象到客户端; 这包括资源的类型、资源的长度和其他信息。
下图代表了这个过程;左边的圆圈代表客户端,右边的圆圈代表Web服务器。Web服务器下面的表表示存储在Web服务器中的资源列表。此处为HTML文件、png图像和txt文件。
HTTP协议允许您通过web发送和接收信息,包括网页、图像和其他web资源。
1.1 URL:Uniform Resource Locator统一资源定位符
统一资源定位符(Uniform resource locator, URL)是在web上查找资源的最常用方法。我们可以将URL分成三部分。
- 体现协议的种类,本实验中是 http://
- Internet地址或者基础URL,用于查找位置。例如:www.ibm.com、www.gitlab.com
- web服务器上的路由位置,例如:/images/IDSNlogo.png
注: (1)关于URI(uniform resource identifier)。URL是URIs的子集。
(2)endpoint。这个词指代Web服务器提供的操作的URL。
1.2 Request:请求
下面的图部分显示出了使用get方法的请求。在开始行,我们有GET方法,这是一个HTTP协议的方法。还有资源/index.html的位置和HTTP版本。Request头还可以在一个HTTP请求中传递额外的信息:
当发出一个HTTP请求时,会发送一个HTTP方法,这告诉服务器要执行什么操作。下面显示了几个HTTP方法的列表。
HTTP METHODS | 描述 |
---|---|
GET | 在服务器中检索数据 |
POST | 向服务器提交数据 |
PUT | 更新服务器中已有的数据 |
DELETE | 从服务器中删除数据 |
1.3 Response:响应
下图表示响应;响应开始行包含版本号HTTP/1.0,一个状态码(200)表示成功,后面跟着一个描述性短语(OK)。响应头包含有用的信息。最后,我们有包含请求文件的响应体(一个HTML文档)。需要注意的是,有些请求有报头。
下面是一些常见的状态码,前缀表示状态的类别
1XX | 信息、报告(informational) |
---|---|
2xx | 成功(Success) |
200 | OK |
3xx | 重定位(Redirection) |
300 | 多重选择(Multiple Choices) |
4xx | 客户端错误(Client Error) |
401 | 未授权(Unauthorized) |
403 | 被禁止(Forbidden) |
404 | 未找到(Not Found) |
2 Python库:Requests
首先引入相应的库,requests。使用这个库可以很方便地发送HTTP/1.1协议。
import requests
下面还会用到的其他的库:
import os
from PIL import Image
from IPython.display import IFrame
- 使用get()方法,可以进行GET类的请求
url='https://www.ibm.com/'
r=requests.get(url)
上面的r就是响应对象(response object)。r有关于请求request的相应信息,例如请求的状态。可以通过属性status_code来查看请求的状态码:
r.status_code
输出:
200
- 可以查看请求的报头
print(r.request.headers)
输出:
- 可以查看请求主体。因为get请求没有主体,所以我们得到一个None:
print("request body:", r.request.body)
输出:
request body: None
- 可以通过r的属性headers查看HTTP响应头response header。这将返回一个包含http响应头的python字典。
header=r.headers
print(r.headers)
输出:
* 使用HTTP响应头(上面的header)的键**“date”**获取到请求发送的时间:
header['date']
输出:
‘Fri, 15 Jan 2021 05:51:10 GMT’
- header 的键值**‘Content-Type’**可以查看到获取到的数据的类型:
header['Content-Type']
输出:
‘text/html; charset=UTF-8’
- 使用响应对象r的属性‘encoding’可以查看到相应的数据编码方式:
r.encoding
输出:
‘UTF-8’
- 因为上面获知,Content-Type是“text/html”,所以我们可以查看响应对象r的属性text来展示部分请求的HTML。例如查看html的前100个字符。
r.text[0:100]
输出:
‘\n\n \n \n
- 对于非文本请求,你可以加载其他类型的数据,比如图片,比如下面图片的URL:
# Use single quotation marks for defining string
url='https://gitlab.com/ibm/skills-network/courses/placeholder101/-/raw/master/labs/module%201/images/IDSNlogo.png'
r=requests.get(url)
print(r.headers)
输出:
查看‘Content-Type’
r.headers['Content-Type']
输出:
‘image/png’
图像是一个响应对象,它以**字节类对象(bytes-like-object)**的形式包含图像。因此,我们必须使用file对象来保存它。首先,我们指定文件路径和名称。
path=os.path.join(os.getcwd(),'image.png') # os.getcwd() 方法用于返回当前工作目录。
path
输出:
‘/resources/labs/PY0101EN/image.png’
我们保存文件,为了访问响应体,我们使用属性content,然后使用open函数和write方法保存它:
with open(path,'wb') as f:
f.write(r.content)
注: ‘wb’表示以二进制写方式打开,只能写文件, 如果文件不存在,创建该文件;如果文件已存在,则覆盖写。
现在可以查看该图片:
2.1 获取带有URL参数的请求
您可以使用GET方法修改查询的结果,例如从API检索数据。我们向服务器发送一个GET请求。除去基础URL以外,我们需要在路由中添加“/get”,这表明我们想要执行GET请求。下表显示了响应的操作:
基础URL是“http://httpbin.org/ ”。
带有get参数的url在python中表示如下:
url_get='http://httpbin.org/get'
- **查询字符串(query string)**是URL的一部分,它将其他信息发送到web服务器。查询字符串的开头是?,后面是一系列的参数和值 对儿,如下表所示。
第一个参数名为name,取值为Joseph。第二个参数名为ID,取值为123。每一对参数和值用等号“=”分开。对儿的序列由&符号分隔。
若要创建查询字符串,**以字典的形式添加。**键是参数名,值是查询字符串的值。
payload={"name":"Joseph","ID":"123"}
然后将字典payload作为get方法的参数params的值传递给get方法:
r=requests.get(url_get,params=payload)
可以打印出此时的url
r.url
输出:
‘http://httpbin.org/get?name=Joseph&ID=123’
没有请求主体:
print("request body:", r.request.body)
输出:
request body: None
查看状态码:
print(r.status_code)
输出:
200
我们可以查看文本形式的响应:
print(r.text)
输出:
查看‘Content-Type’。
r.headers['Content-Type']
输出:
‘application/json’
因为内容类型是“JSON”,可以使用方法json(),返回一个python字典.
r.json()
输出:
上面返回的python字典的键值‘args’包含参数名和对应的值。
r.json()['args']
{‘ID’: ‘123’, ‘name’: ‘Joseph’}
2.2 Post请求
POST请求被用来向服务器发送数据,POST请求在请求体中发送数据。为了在Python中发送POST请求,将url路由中的‘/get’改为‘/post’.
url_post='http://httpbin.org/post'
这个endpoint将期望数据以文件或表单的形式发送,form(表单)是一个方便的来配置一个HTTP请求发送数据到服务器的方式。
使用post()方法来进行POST请求,变量payload被传递给参数data:
r_post=requests.post(url_post,data=payload)
- 比较GET和POST请求的响应对象的URL,我们看到POST请求没有名称或值对。
print("POST request URL:",r_post.url )
print("GET request URL:",r.url)
输出:
POST request URL: http://httpbin.org/post
GET request URL: http://httpbin.org/get?name=Joseph&ID=123
我们可以比较POST和GET请求主体,我们看到只有POST请求有一个主体:
print("POST request body:",r_post.request.body)
print("GET request body:",r.request.body)
输出:
POST request body: name=Joseph&ID=123
GET request body: None
我们也可以查看这个表单:
r_post.json()['form']
输出
{‘ID’: ‘123’, ‘name’: ‘Joseph’}