当前位置:   article > 正文

requests 模块_requests模块

requests模块

requests

基本概念

简介

requests 模块是 python 基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTTP 测试需求。Requests 的哲学是以 PEP 20 的习语为中心开发的,所以它比 urllib 更加 Pythoner

获取

通过 pip install requests 安装 requests 库

导包:import requests

http 协议

超文本传输协议,是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法,HTTP是一种基于"请求与响应"模式的、无状态的应用层协议。HTTP协议采用URL作为定位网络资源的的标识符

  • URL

统一资源定位符是互联网上标准资源地址。互联网上的每一个文件都有一个唯一的 URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它

URL 的一般语法格式为:

protocol://host[:port]/path/[?query]#fragment
http://www.itcast.cn/index.html?name=andy&age=18#link
  • 1
  • 2
组成说明
protocol通信协议,常用:http、https 等
host主机(域名)
port端口号,可选,省略时候使用方案的默认端口,如:http的默认端口为80
path路径,由零或多个 ‘/’ 符号隔开的字符串,一般用来表示主机上的一个目录或文件地址
query参数,以键值对的形式通过 & 来连接
fragment片段,# 后面内容常见于链接 锚点

url是通过HTTP协议存取资源的的Internet路径,一个URL对应一个数据资源

  • 常用 http 请求方法
方法说明
GET请求获取URL位置的资源
HEAD请求获取URL位置资源的响应消息报告,即获得资源的头部信息
POST请求向URL位置的资源后附加新的消息
PUT请求向URL位置存储一个资源,覆盖原URL位置的资源
PATCH请求局部更新URL位置的资源,即改变该处资源的部分内容
DELETE请求删除URL位置存储的资源

GET,HEAD是从服务器获取信息到本地,PUT,POST,PATCH,DELETE是从本地向服务器提交信息。通过URL和命令管理资源,操作独立无状态,网络通道及服务器成了黑盒子

常用方法

基本语法

requests 库中的方法
方法说明
requests.requst()构造一个请求,最基本的方法,是下面方法的支撑
requests.get()获取网页,对应HTTP中的GET方法
requests.post()向网页提交信息,对应HTTP中的POST方法
requests.head()获取html网页的头信息,对应HTTP中的HEAD方法
requests.put()向html提交put方法,对应HTTP中的PUT方法
requests.patch()向html网页提交局部请求修改的的请求,对应HTTP中的PATCH方法
requests.delete()向html提交删除请求,对应HTTP中的DELETE方法

最常用的方法为get()和post()分别用于发送Get请求和Post请求

response对象的常用属性
属性或方法描述
response.status_code响应状态码
response.content把response对象转换为二进制数据
response.text把response对象转换为字符串数据
response.encoding定义response对象的编码
response.cookie获取请求后的cookie
response.url获取请求网址
response.json()内置的JSON解码器
Response.headers以字典对象存储服务器响应头,字典键不区分大小写

具体使用

response = requests.request(method, url,
                            params=None, data=None, headers=None, cookies=None, files=None,
                            auth=None, timeout=None, allow_redirects=True, proxies=None,
                            stream=None, verify=None, cert=None, json=None)
  • 1
  • 2
  • 3
  • 4

response 是一个Response对象,一个包含服务器资源的对象

参数说明

  • method----接口请求方式,值分别对应以下四个方法名称,例如:请求方式为get,则method=‘get’
  • url----接口请求的url地址
get
  • 基本语法
response = requests.get(url='http://', params=None, **kwargs)
  • 1
  • 常用参数
参数类型作用
params字典url为基准的url地址,不包含查询参数;该方法会自动对params字典编码,然后和url拼接
url字符串requests 发起请求的地址
headers字典请求头,发送请求的过程中请求的附加内容携带着一些必要的参数
cookies字典携带登录状态
proxies字典用来设置代理 ip 服务器
timeout整型用于设定超时时间, 单位为秒
post
  • 基本语法
response = requests.post(url='http://', data=None, json=None, **kwargs)
  • 1
  • 常用参数
参数类型作用
data字典作为向服务器提供或提交资源时提交,主要用于 post 请求
json字典json格式的数据, json合适在相关的html

注意:

  • data 和 params 的区别是: data提交的数据并不放在url链接里, 而是放在url链接对应位置的地方作为数据来存储
  • data 和 json 的作用类似,适用方法相同
  • get 里面的参数大部分也适用
put

其语法和 post 请求的语法类似

response = requests.put(url='http://', data=None, **kwargs)
  • 1

put 和 post 区别:

  • 新建一条记录的话就用post
  • POST 方法被用于请求源服务器接受请求中的实体作为请求资源的一个新的从属物
  • 更新一条记录的话就用put
  • PUT方法请求服务器去把请求里的实体存储在请求URI标识下
delete

其语法和 get 请求的语法类似

response = requests.delete(url='http://', **kwargs)
  • 1

高级操作

重定向

重定向就是网络请求被重新定个方向转到了其它位置

常见状态码

状态码内容
200请求成功,服务器已经将请求的响应头和数据返回
201请求成功,服务器已经创建新的资源,并将数据返回
202请求成功,但是服务器尚未处理
301请求成功,服务器将请求资源永久转移到新的位置,并且下次会自动转移到新的位置
302请求成功,服务器将请求资源临时转移到新的位置,但是下次访问请求者会访问原来的位置
304请求成功,但是服务器不会做任何的修改,也不会返回任何响应内容
401服务器需要验证身份才能相应
403服务器收到请求,但是拒绝返回信息
404请求失败,服务器没有找到任何关于响应的内容
501服务器无法完成对请求的处理
503服务器无法完成对请求的处理,也许是过载的问题,但是一会儿就会恢复

重定向状态码:

  • 301 redirect: 301 代表永久性转移(Permanently Moved)
  • 302 redirect: 302 代表暂时性转移(Temporarily Moved )

禁止重定向( allow_redirects=False ,默认是True)

import requests


# allow_redirects= False 这里设置不允许跳转
# 实际url:'https://www.jd.com'
response = requests.get(url='http://jd.com/', allow_redirects=False)

print(response.headers)
print(response.status_code)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述

看结果 返回response header 中有一个属性 Location ,代表重定向了 'Location': 'https://www.jd.com'

在浏览器中 chrome network 面板 ,抓包观察。 注意把 preserve log 这个选项勾选上。

从浏览器的response header 中 我们可以看到 Location, 从 General 我们可以看到 status code 301 ,发生了跳转

在这里插入图片描述

重定向获取真实的URL

  • 直接从response header,获取 Location
import requests


# allow_redirects= False 这里设置不允许跳转
# 实际url:'https://www.jd.com'
response = requests.get(url='http://jd.com/', allow_redirects=False)
print(response.headers['Location'])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 访问URL, 获取response.url
import requests


# 默认allow_redirects= Ture 这里设置允许跳转
# 实际url:'https://www.jd.com'
response = requests.get(url='http://jd.com/')
print(response.url)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

追踪重定向

import requests

response = requests.get(url='http://jd.com/')
print(response.history)  # history追踪页面重定向历史
  • 1
  • 2
  • 3
  • 4
文件上传

使用 Requests 模块上传文件,文件的类型会自动进行处理:

import requests

#  直接通过open函数打开文件并将文件对象存在字典中
files = {'file': open('D:/pycharm_mm/Framework_request/a.txt', 'rb')}
response = requests.post("http://httpbin.org/post", files=files)
print(response.text)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
代理设置

在进行爬虫爬取时,有时候爬虫会被服务器给屏蔽掉,这时采用的方法主要有降低访问时间,通过代理ip访问,网站面对多个不同的ip地址,就没有办法屏蔽。

  • 代理的基本原理

在这里插入图片描述

  • 正向代理与反向代理

正向代理:浏览器明确知道要访问的是什么服务器,只不过目前无法达到,需要通过代理来帮助完成这个请求操作。

反向代理:浏览器不知道任何关于要请求的服务器的信息,需要通过Nginx请求。

![在这里插入图片描述](https://img-blog.csdnimg.cn/f67878097a354a03a2f8ef9b2017c347.png

代理设置不同python版本有不同的写法

1. python3.8以下版本:
        proxies{' 要请求网站的协议类型 ' , ' 代理服务器ip : 端口 '}


2. python3.8以上版本:
        proxies{' 要请求网站的协议类型 ' , ' "代理服务器类型(http/https/socks5)://代理服务器ip : 端口 '}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
import requests

proxies = {
    "http": "http://10.10.1.10:3128",
    "https": "http://10.10.1.10:1080"
}

try:
    response = requests.get("http://example.org", proxies=proxies)
    print(response.text)
except requests.exceptions.ConnectionError as e:
    print('Error:', e.args)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
超时设置

访问有些网站时可能会超时,这时设置好timeout就可以解决这个问题

import requests
from requests.exceptions import ReadTimeout

try:
     response = requests.get("http://httpbin.org/get", timeout = 0.5)
     print(response.status_code)
except ReadTimeout:
     print('Timeout')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
获取 cookie

cookie是一段不超过4KB的小型 文本 数据,由一个名称(Name)、一个值(Value)和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。

  • cookie 是 开发工程师,针对 http请求 无状态、无连接 特性,设计的技术。

  • cookie 看做一个容器。默认 4k。数据存储在 浏览器端。支持的数据类型,受浏览器限制。

  • 只能存储 少量、不敏感的 用户信息,方便访问 服务器。

  • cookie 中的 数据,可以十分方便获取到。

import requests

response = requests.get("https://www.baidu.com/")
print(response.cookies)

for key, value in response.cookies.items():
    print(key + '=' + value)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
会话 session

session 由服务端创建,当一个请求发送到服务端时,服务器会检索该请求里面有没有包含 sessionId 标识,如果包含了 sessionId,则代表服务端已经和客户端创建过 session,然后就通过这个 sessionId 去查找真正的 session,如果没找到,则为客户端创建一个新的 session,并生成一个新的 sessionId 与 session 对应,然后在响应的时候将 sessionId 给客户端,通常是存储在 cookie 中。如果在请求中找到了真正的 session,验证通过,正常处理该请求。Session用于存储用户的信息。

  • session位于服务器端。大小直接使用服务器存储空间

  • session中的数据,不能随意被访问,安全性较高

  • Session中存储的数据类型,受服务器影响,几乎能支持所有的数据类型

因为Cookie中的数据,都是Session传递的,因此,Session 可以直接自动管理cookie地

会话维持:

import requests

# 创建一个Session 实例
session = requests.session()

# 使用Session实例, 发送获取验证码请求(不需要获取cookie)
verify_url = "http://hmshop-test.itheima.net/index.php?m=Home&c=User&a=verify"
verify_resp = session.get(url=verify_url)

# 使用同一个Session实例,调用post方法,发送登录请求
login_url = "http://hmshop-test.itheima.net/index.php?m=Home&c=User&a=do_login"
login_header = {"Content-Type": "application/x-www-form-urlencoded"}
login_data = {"username": "13012345678", "password": "123456", "verify_code": "8888"}
login_resp = session.post(url=login_url, headers=login_header, data=login_data)

# 使用同一个Session实例,调用get方法,发送 查看我的订单请求
order_url = "http://hmshop-test.itheima.net/home/Order/order_list.html"
order_resp = session.get(url=order_url)
print(order_resp.headers)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
session、cookie、token的区别

为什么会有它们?

都知道 HTTP 协议是无状态的,所谓的无状态就是客户端每次想要与服务端通信,都必须重新与服务端链接,意味着请求一次客户端和服务端就连接一次,下一次请求与上一次请求是没有关系的。

这种无状态的方式就会存在一个问题:如何判断两次请求的是同一个人?就好比用户在页面 A 发起请求获取个人信息,然后在另一个页面同样发起请求获取个人信息,我们如何确定这俩个请求是同一个人发的呢?

为了解决这种问题,我们就迫切需要一种方式知道发起请求的客户端是谁?此时,cookie、token、session 就出现了,它们就可以解决客户端标识的问题,在扩大一点就是解决权限问题。

它们就好比让每个客户端或者说登录用户有了自己的身份证,我们可以通过这个身份证确定发请求的是谁!

什么是 cookie?

cookie 是保存在客户端或者说浏览器中的一小块数据,大小限制大致在 4KB 左右,在以前很多开发人员通常用 cookie 来存储各种数据,后来随着更多浏览器存储方案的出现,cookie 存储数据这种方式逐渐被取代,主要原因有如下:

  • cookie 有存储大小限制,4KB 左右。
  • 浏览器每次请求会携带 cookie 在请求头中。
  • 字符编码为 Unicode,不支持直接存储中文。
  • 数据可以被轻易查看。

cookie 主要有以下属性:

属性名称属性含义
namecookie 的名称
valuecookie 的值
commentcookie 的描述信息
domain可以访问该 cookie 的域名
expirescookie 的过期时间,具体某一时间
maxAgecookie 的过期时间,比如多少秒后 cookie 过期。
pathcookie 的使用路径
securecookie 是否使用安全协议传输,比如 SSL 等
versioncookie 使用的版本号
isHttpOnly指定该 Cookie 无法通过 JavaScript 脚本拿到,比如 Document.cookie 属性、XMLHttpRequest 对象和 Request API 都拿不到该属性。这样就防止了该 Cookie 被脚本读到,只有浏览器发出 HTTP 请求时,才会带上该 Cookie

那么我们是如何通过 cookie 来实现用户确定或者权限的确定呢?

我们就以一个普通网站的用户登录操作以及后续操作为例,主要过程可以简单用下图表示:

在这里插入图片描述

从上图中可以看到使用 cookie 进行用户确认流程是比较简单的,大致分为以下几步:

​ 1.客户端发送请求到服务端(比如登录请求)。

​ 2.服务端收到请求后生成一个 session 会话。

​ 3.服务端响应客户端,并在响应头中设置 Set-Cookie。Set-Cookie 里面包含了 sessionId,它的格式如下:

​ Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]。其中 sessionId 就是用来标识客户端的,类似于去饭店里面,服务 员给你一个号牌,后续上菜通过这个号牌来判断上菜到哪里。

​ 4.客户端收到该请求后,如果服务器给了 Set-Cookie,那么下次浏览器就会在请求头中自动携带 cookie。

​ 5.客户端发送其它请求,自动携带了 cookie,cookie 中携带有用户信息等。

​ 6.服务端接收到请求,验证 cookie 信息,比如通过 sessionId 来判断是否存在会话,存在则正常响应。

cookie 主要有以下特点:

  • cookie 存储在客户端
  • cookie 不可跨域,但是在如果设置了 domain,那么它们是可以在一级域名和二级域名之间共享的。

什么是 session?

在上一节中,我们通过 Cookie 来实现了用户权限的确认,在其中我们提到了一个词:session。顾名思义它就是会话的意思,session 主要由服务端创建,主要作用就是保存 sessionId,用户与服务端之间的权限确认主要就是通过这个 sessionId。

简单描述下 session:

session 由服务端创建,当一个请求发送到服务端时,服务器会检索该请求里面有没有包含 sessionId 标识,如果包含了 sessionId,则代表服务端已经和客户端创建过 session,然后就通过这个 sessionId 去查找真正的 session,如果没找到,则为客户端创建一个新的 session,并生成一个新的 sessionId 与 session 对应,然后在响应的时候将 sessionId 给客户端,通常是存储在 cookie 中。如果在请求中找到了真正的 session,验证通过,正常处理该请求。
  • 1

总之每一个客户端与服务端连接,服务端都会为该客户端创建一个 session,并将 session 的唯一标识 sessionId 通过设置 Set-Cookie 头的方式响应给客户端,客户端将 sessionId 存到 cookie 中。

通常情况下,我们 cookie 和 session 都是结合着来用,当然你也可以单独只使用 cookie 或者单独只使用 session,这里我们就将 cookie 和 session 结合着来用。

我们可以在修改一下整个请求过程图,如下所示:

在这里插入图片描述

cookie 和 session 的区别?

前面两节我们介绍了 cookie 和 session,它们两者之间主要是通过 sessionId 关联起来的,所以我们总结出:sessionId 是 cookie 和 session 之间的桥梁。我们日常的系统中如果在鉴权方面如果使用的是 cookie 方式,那么大部分的原理就和我们前面说的一样。

或者我们可以换个说法,session 是基于 cookie 实现的,它们两个主要有以下特点:

  • session 比 cookie 更加安全,因为它是存在服务端的,cookie 是存在客户端的。
  • cookie 只支持存储字符串数据,session 可以存储任意数据。
  • cookie 的有效期可以设置较长时间,session 有效期都比较短。
  • session 存储空间很大,cookie 有限制。

系统想要实现鉴权,可以单独使用 cookie,也可以单独使用 session,但是建议结合两者使用。

token 是什么?

前面我们说的 sessionId 可以叫做令牌,令牌顾名思义就是确认身份的意思,服务端可以通过令牌来确认身份。

cookie+session 是实现认证的一种非常好的方式,但是凡事都有两面性,它们实现的认证主要有以下缺点:

  • 增加请求体积,浪费性能,因为每次请求都会携带 cookie。
  • 增加服务端资源消耗,因为每个客户端连接进来都需要生成 session,会占用服务端资源的。
  • 容易遭受 CSRF 攻击,即跨站域请求伪造。

那么为了避免这些缺点,token 方式的鉴权出现了,它可以说是一个民间的认证方式,但是不得不说它带来了非常多的好处。

token 的组成:

token 其实就是一串字符串而已,只不过它是被加密后的字符串,它通常使用 uid(用户唯一标识)、时间戳、签名以及一些其它参数加密而成。我们将 token 进行解密就可以拿到诸如 uid 这类的信息,然后通过 uid 来进行接下来的鉴权操作。
  • 1

token 是如何生成的:

前面我们说 cookie 是服务端设置了 set-cookie 响应头之后,浏览器会自动保存 cookie,然后下一次发送请求的时候会自动把 cookie 携带上。但是我们说 cookie 算是一种民间的实现方式,所以说浏览器自然不会对它进行成么处理。token 主要是由服务器生成,然后返回给客户端,客户端手动把 token 存下来,比如利用 localstorage 或者直接存到 cookie 当中也行。

token 认证流程:

​ 1.客户端发起登录请求,比如用户输入用户名和密码后登录。

​ 2.服务端校验用户名和密码后,将用户 id 和一些其它信息进行加密,生成 token。

​ 3.服务端将 token 响应给客户端。

​ 4.客户端收到响应后将 token 存储下来。

​ 5.下一次发送请求后需要将 token 携带上,比如放在请求头中或者其它地方。

​ 6.服务端 token 后校验,校验通过则正常返回数据。

在这里插入图片描述

总结

虽然前面解释 cookie、session、token 用了不少口舌,但是归根结底啊,它们的目的都是一样的:鉴权和认证。

鉴权认证方式特点优点缺点
cookie1.存储在客户端。2.请求自动携带 cookie。3.存储大小 4KB。1.兼容性好,因为是比较老的技术。2.很容易实现,因为 cookie 会自动携带和存储。1.需要单独解决跨域携带问题,比如多台服务器如何共享 cookie。2.会遭受 CSRF 攻击。3.存储在客户端,不够安全。
session1.存储在服务端。2.存储大小无限制。1.查询速度快,因为是个会话,相当于是在内存中操作。2.结合 cookie 后很容易实现鉴权。3.安全,因为存储在服务端。1.耗费服务器资源,因为每个客户端都会创建 session。2.占据存储空间,session 相当于存储了一个完整的用户信息。
token1.体积很小。2.自由操作存储在哪里。1.安全,因为 token 一般只有用户 id,就算被截取了也没什么用。2.无需消耗服务器内存资源,它相当于只存了用户 id,session 相当于存储了用户的所有信息。3.跨域处理较为方便,比如多台服务器之间可以共用一个 token。1.查询速度慢,因为 token 只存了用户 id,每次需要去查询数据库。

总结下来就是:session 是空间换时间,token 是时间换空间。

SSL 证书(HTTPS请求)

最新的requests库是支持https请求的,但是一般写脚本时候,会用抓包工具fiddler,这时候会报SSLError错误

import requests

# 正常情况能够直接支持https请求
response = requests.get('https://www.12306.cn')
print(response)
  • 1
  • 2
  • 3
  • 4
  • 5

原因:

  • fiddler默认是启动作为系统代理的,然后requests默认是开启ssl验证的,fiddler配置抓取https时,就会导致两处ssl证书各种问题。
fiddler作为中间人获取了网站的公钥和客户端的密钥,然后伪装成客户端和服务端通信(使用网站公钥和自己的密钥),再伪装成服务端把收到的信息发送给客户端(使用自己的公钥和客户端的密钥)。fiddler的公钥不是ca认证的,所以requests就无法通过内置的ca公钥解密,验证就会失败。所以要不不验证,要不指定和特定的证书进行对比验证,就能解决问题。
  • 1

解决方案:

  • 关闭 fiddler

  • 去掉requests的ssl验证SSL证书认证参数 verify默认为True

    • requests.get(url, verify=False)  # 发送https请求时,加入verify=False,忽略证书验证
      
      • 1

      但是依然会出现两行Warning,使用urllib3.disable_warnings()解决

      import urllib3
      import requests
      
      urllib3.disable_warnings() # 将这段代码放到调用https的代码段中,避免其他模块调用时仍报该错
      response = requests.get('https://www.12306.cn', verify=False)
      print(response)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
  • 保持fiddler和requests的证书一致

错误与异常

所有Requests显式抛出的异常都继承自 requests.exceptions.RequestException

异常说明
request.exceptions.ConnectTimeout连接超时
requests.exceptions.ConnectionError网络连接错误异常,如DNS查询失败、拒绝连接等
requests.exceptions.ProxyError代理服务器拒绝建立连接,端口拒绝连接或未开放
requests.exceptions.HTTPErrorHTTP错误异常
requests.exceptions.TooManyRedirects超过做大重定向次数,产生重定向异常
requests.exceptions.Timeout请求URL超时,产生超时异常
Response.raise_for_status()如果不是200,产生异常requests.HTTPError
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/259781
推荐阅读
相关标签
  

闽ICP备14008679号