进入浏览器的开发者模式下的 Network 监听组件,访问百度 https://www.baidu.com/,输入该 URL 后回车,观察这个过程中发生了怎样的网络请求:
请求,由客户端向服务端发出,可以分为 4 部分内容:请求方法(Request Method)
、请求的网址(Request URL)
、请求头(Request Headers)
、请求体(Request Body)
。
常见的请求方法有两种:GET
和 POST
。
在浏览器中直接输入 URL 并回车,这便发起了一个 GET 请求,请求的参数会直接包含到 URL 里。例如,在百度中搜索 Python,这就是一个 GET 请求,链接为 https://www.baidu.com/s?wd=Python,其中 URL 中包含了请求的参数信息,这里参数 wd 表示要搜寻的关键字。POST 请求大多在表单提交时发起。比如,对于一个登录表单,输入用户名和密码后,点击 “登录” 按钮,这通常会发起一个 POST 请求,其数据通常以表单的形式传输,而不会体现在 URL 中。
GET 和 POST 请求方法有如下区别:
GET
请求中的参数包含在 URL 里面,数据可以在 URL 中看到,而 POST
请求的 URL 不会包含这些数据,数据都是通过表单形式传输的,会包含在请求体中。GET
请求提交的数据最多只有 1024 字节,而 POST
请求没有限制。请求头,用来说明服务器要使用的附加信息,比较重要的信息有 Cookie、Referer、User-Agent 等。下面简要说明一些常用的头信息。
因此,请求头是请求的重要组成部分,在写爬虫时,大部分情况下都需要设定请求头。
请求体一般承载的内容是 POST 请求中的表单数据,而对于 GET 请求,请求体则为空。
登录之前,我们填写了用户名和密码信息,提交时这些内容就会以表单数据的形式提交给服务器,此时需要注意 Request Headers 中指定 Content-Type 为 application/x-www-form-urlencoded。只有设置 Content-Type 为 application/x-www-form-urlencoded,才会以表单数据的形式提交。另外,我们也可以将 Content-Type 设置为 application/json 来提交 JSON 数据,或者设置为 multipart/form-data 来上传文件。
表格中列出了 Content-Type 和 POST 提交数据方式的关系:
在爬虫中,如果要构造 POST 请求,需要使用正确的 Content-Type,并了解各种请求库的各个参数设置时使用的是哪种 Content-Type,不然可能会导致 POST 提交后无法正常响应。
响应,由服务端返回给客户端,可以分为三部分:响应状态码(Response Status Code)、响应头(Response Headers)和响应体(Response Body)。
响应状态码表示服务器的响应状态,如 200 代表服务器正常响应,404 代表页面未找到,500 代表服务器内部发生错误。
状态码 | 说明 | 详情 |
---|---|---|
200 | 响应成功 | 服务器已经成功处理了请求 |
301 | 永久重定向 | 服务器通过回传状态码 301 来下达给客户端,让客户端完成跳转 |
302 | 临时重定向 | 请求的网页暂时跳转到其他页面 |
403 | 禁止访问 | 没有权限去访问服务器的资源,或者请求的 IP 地址被封掉了 |
404 | 未找到 | 服务器找不到客户端请求的资源 |
500 | 服务器内部错误 | 服务器端的网页程序出错 |
响应头包含了服务器对请求的应答信息,如 Content-Type、Server、Set-Cookie 等。下面简要说明一些常用的响应头信息:
在了解 Session 和 Cookies 之前,我们还需要了解 HTTP 的一个特点,叫作无状态。
HTTP 的无状态是指 HTTP 协议对事务处理是没有记忆能力的,也就是说服务器不知道客户端是什么状态。
这时两个用于保持 HTTP 连接状态的技术就出现了,它们分别是 Session 和 Cookies。Session 在服务端,也就是网站的服务器,用来保存用户的 Session 信息;Cookies 在客户端,也可以理解为浏览器端,有了 Cookies,浏览器在下次访问网页时会自动附带上它发送给服务器,服务器通过识别 Cookies 并鉴定出是哪个用户,然后再判断用户是否是登录状态,进而返回对应的响应。
而在 Web 中,Session(会话)对象用来存储特定用户 Session 所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户 Session 中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有 Session,则 Web 服务器将自动创建一个 Session 对象。当 Session 过期或被放弃后,服务器将终止该 Session。
Cookies 指某些网站为了辨别用户身份、进行 Session 跟踪而存储在用户客户端上的数据。
那么,我们怎样利用 Cookies 保持状态呢?当客户端第一次请求服务器时,服务器会返回一个响应头中带有 Set-Cookie 字段的响应给客户端,用来标记是哪一个用户,客户端浏览器会把 Cookies 保存起来。当浏览器下一次再请求该网站时,浏览器会把此 Cookies 放到请求头一起提交给服务器,Cookies 携带了 Session ID 信息,服务器检查该 Cookies 即可找到对应的 Session 是什么,然后再判断 Session 来以此来辨认用户状态。
所以,Cookies 和 Session 需要配合,一个处于客户端,一个处于服务端,二者共同协作,就实现了登录 Session 控制。
以知乎为例,在浏览器开发者工具中打开 Application 选项卡,然后在左侧会有一个 Storage 部分,最后一项即为 Cookies,将其点开,如图所示,这些就是 Cookies。
可以看到,这里有很多条目,其中每个条目可以称为 Cookie。
会话 Cookie 就是把 Cookie 放在浏览器内存里,浏览器在关闭之后该 Cookie 即失效;持久 Cookie 则会保存到客户端的硬盘中,下次还可以继续使用,用于长久保持用户登录状态。
其实严格来说,没有会话 Cookie 和持久 Cookie 之 分,只是由 Cookie 的 Max Age 或 Expires 字段决定了过期的时间。
因此,一些持久化登录的网站其实就是把 Cookie 的有效时间和 Session 有效期设置得比较长,下次我们再访问页面时仍然携带之前的 Cookie,就可以直接保持登录状态。
需要注意的是,Session 和 Cookies 的存在与否,跟用户是否关闭浏览器无关。
由于大部分网站都使用会话 Cookie 来保存 Session ID 信息,而关闭浏览器后 Cookies 就消失了,再次连接服务器时,也就无法找到原来的 Session 了。而关闭浏览器的行为不会被服务器获知。
如果把 Cookies 保存到硬盘上,或者使用某种手段改写浏览器发出的 HTTP 请求头,把原来的 Cookies 发送给服务器,则再次打开浏览器,仍然能够找到原来的 Session ID,依旧还是可以保持登录状态的。
Session 的生存时间由服务器端设置的失效时间决定,当距离客户端上一次使用 Session 的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把 Session 删除以节省存储空间。