超文本传输协议(Hypertext Transfer Protocol,HTTP)是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。当您在浏览器中输入网址时,其开头的http便表示HTTP协议。
HTTP是基于客户/服务器模式,且面向连接的。典型的HTTP事务处理有如下的过程:
客户端(常常是浏览器)与服务器之间的HTTP连接是一种一次性连接,它限制每次连接只处理一个请求,当服务器返回本次请求的应答后便立即关闭连接,下次请求再重新建立连接。
HTTP协议一般运行在80端口之上。当你输入以http开头的网址而未指定端口时,默认访问80端口。
HTTP规范定义了9种请求方法,每种请求方法规定了客户和服务器之间不同的信息交换方式,服务器将根据客户请求完成相应操作,并以应答块形式返回给客户,最后关闭连接,如下表所示:
| 方法 | 说明 | 出现的HTTP版本 |
|---|---|---|
| GET | 获取资源 | 1.0 |
| POST | 传输实体主体 | 1.0 |
| HEAD | 获得报文首部 | 1.0 |
| PUT | 传输文件 | 1.1 |
| DELETE | 删除文件 | 1.1 |
| OPTIONS | 询问支持的方法 | 1.1 |
| TRACE | 追踪路径 | 1.1 |
| CONNECT | 要求用隧道协议链接代理 | 1.1 |
| LINK | 建立和资源之间的联系 | 1.1 |
| UNLINE | 断开连接关系 | 1.1 |
实际上,常用的请求方法只有GET和POST。
HTTP请求的格式如下:
\n结尾;\n分隔。空行(单独一个\n)表示报头部分的结束;一个典型的URL为:
http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#anchor
http:// 表示http协议,常见的还有https, ftp等;www.example.com 表示域名,其中example.com的部分为主体域名;80 表示端口号,80端口即默认http端口,可以省略;/path/to/myfile.html 表示资源路径,用于定位到程序管理的资源;?key1=value1&key2=value2 表示查询字符串,以?开头,可以包含多个键值对,每个键值对以键=值的形式表示,用&分割;#anchor表示片段标识,以#开头,用于页面内部定位。GET请求通常用于客户端向服务器请求指定的页面信息,并返回实体内容。一个典型的GET请求如下:
GET /signin?next=%2F HTTP/2
Host: www.zhihu.com
User-Agent: Mozilla/5.0
Accept: */*
Accept-Language: zh-CN
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
TE: trailers
Cookie: uuid=1234567890; something=xxx
(这里有一个空行)
通常地,GET请求没有请求体,只有请求头。GET请求的请求参数以查询字符串的形式出现。 常见参数的解释如下:
Host表示请求的主机;User-Agent表示浏览器/操作系统的属性,简称UA;Referer表示是从哪个页面跳转过来的;Cookie本质上是浏览器给网页提供的本地存储数据的机制。网页默认是不被允许访问计算机的硬盘的,但是浏览器又需要在本地存储一些东西(比如用户登录状态等等),Cookie就是用来完成这项功能的。POST请求通常用于客户端向服务器发送信息(例如提交表单、登录等)。一个典型的POST请求如下:
POST /login HTTP/1.1
Host: 127.0.0.1:8888
User-Agent: Mozilla/5.0
Accept: */*
Accept-Language: zh-CN
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
Connection: keep-alive
username=root&password=123456
POST请求具有请求体,亦即body部分。放在请求体内的请求参数以`key=value`的形式传递,参数与参数之间使用`&`进行连接,同GET请求中的查询字符串一致。
常见参数的解释如下:
Content-Type指示body部分的数据类型;Content-Length指示body部分的数据长度(以字节为单位)。当客户端给出请求时,服务端会给出响应,格式如下:
\n结尾;\n分隔。空行(单独一个\n)表示报头部分的结束;HTTP/1.1 200 OK
Content-Type:text/plain;charset=UTF-8
Content-Length:31
Date:Wed, 19 Jan 2022 11:37:00 GMT
Keep-Alive:timeout=60
Connection:keep-alive
post request is ok,param = post
响应代码的含义如下:
| 代码系列 | 含义 | 解释 |
|---|---|---|
| 1xx | 临时响应信息 | 服务器收到请求,需要请求者继续执行操作 |
| 2xx | 成功 | 操作被成功接收并处理 |
| 3xx | 重定向 | 需要进一步的操作以完成请求 |
| 4xx | 客户端错误 | 请求包含语法错误或无法完成请求 |
| 5xx | 服务器错误 | 服务器在处理请求的过程中发生了错误 |
例如:200 OK表示访问成功,404 Not Found表示没有找到要访问的资源,404 Forbidden表示禁止访问(例如没有权限)等,500 Internal Server Error表示服务器内部错误。
在Python中,通常使用requests库来实现HTTP请求。该库同时也支持HTTPS(即加密通信的HTTP)。
可以在命令行中输入以下命令安装requests库:
pip install requests
使用范例如下:
import requests
res=requests.get("https://www.baidu.com") #向百度网站发送GET请求
print(res.text) #输出HTTP响应的正文
res=requests.get("https://www.baidu.com", verify=False) #向百度网站发送GET请求,并且不验证SSL证书的有效性,用于阻止某些SSL错误发生
res=requests.get("https://www.baidu.com",cookie={"user":"username"}) #指定请求的Cookie
url = "http://httpbin.org/post"
data = {
"name": "Tom",
"age": 20,
}
res=requests.post(url, data=data) #向httpbin.org/post发送POST请求
print(res.text) #输出HTTP响应的正文
有的时候,我们需要维持访问会话(例如有些请求对于是否登录的返回有差别,需要维持cookie),这时候需要使用session功能:
import requests
session = requests.session()
print("会话初始cookie:",dict(session.cookies))
res = session.get("https://postman-echo.com/get")
print("响应头中set-cookie:",res.headers.get("set-cookie"))
print("会话现有cookie:",dict(session.cookies))
HTTP响应通常是服务端的任务。在Python中,常用的服务端开发程序是Flask。由于Flask内容繁多,这里不再详细介绍。