高级用法
在之前的文章我们了解过requests库的基本用法,如基本的GET、POST请求以及Response对象。本文介绍requests库的一些高级用法,如文件上传、Cookies设置、代理设置等。
1.文件上传
requests可以模拟提交一些数据,假如有的网站需要上传文件,我们也可以用它来实现,这非常简单。
实例展示:
import requests
files = {'file':open("favicon.ico",'rb')}
r = requests.post("http://httpbin.org/post",files=files)
print(r.text)
输出结果:
上一篇文章中,我们获取了一个github的图标文件favicon.ico,这里用它来模拟文件上传的过程,注意上传的文件需要和当前脚本在同一目录下,如果有其他文件,当然也可以使用其他文件来上传,更改下代码即可。
2.Cookies
使用requests库可以一步完成获取和设置Cookies,相对于urllib库十分简便。
实例展示:
import requests
r = requests.get("http://www.baidu.com")
print(r.cookies)
print(r.cookies.items())
for key,value in r.cookies.items():
print(key + '='+value)
输出结果:
上面代码中,我们首先调用cookies属性即可成功获取网页的Cookies,它是一个RequestCookieJar类型。然后用items()方法,将其转化为元组组成的列表,用for循环,遍历输出每一个Cookie的名称和值。
我们还可以直接用Cookie来维持登陆状态,下面以知乎为例说明,首先登陆知乎,用开发者工具将Headers中的Cookie和User-Agent内容复制下来。
接下来,将其设置到Headers里面(自己试的时候换成自己的Cookie),然后发送请求。
示例如下:
import requests
headers = {
'cookie':'你的Cookie',
'user-agent':'你的user-agent'
}
r = requests.get("https://www.zhihu.com",headers=headers)
print(r.text)
输出结果:
还有一种方法,可以通过cookies参数来设置,不过这样需要构造RequestsCookieJar对象,而且需要分割一下cookies,相对繁琐。
示例如下:
cookies = '你的Cookie'
jar = requests.cookies.RequestsCookieJar()
headers = {
'user-agent':'你的user-agent'
}
for cookie in cookies.split(';'):
key,value = cookie.split('=',1)
jar.set(key,value)
r = requests.get("https://www.zhihu.com",cookies=jar,headers=headers)
print(r.text)
输出结果:
3.会话维持
在requests中,如果直接利用get()或post()等方法,的确可以做到模拟网页的请求,但这实际上是不同的会话,相当于用两个浏览器打开了不同页面。
设想一个场景,第一次请求利用POST方法登陆了某个网站,第二次想获取成功登陆后的自己的个人信息,你又用了一个get()方法去请求个人信息页面,实际上着相当于打开了两个浏览器、是两个完全不相关的会话,不能成功获取个人信息。
要解决这个问题,主要的方法是维持同一个会话,相当于打开一个新的浏览器选项卡,而不是新开一个浏览器,但我又不想每次都设置cookies,这会比较繁琐。Session对象可以解决这个问题。
实例展示:
import requests
requests.get("http://httpbin.org/cookies/set/number/123456789")
r = requests.get("http://httpbin.org/cookies")
print(r.text)
输出结果:
这里我们请求了一个测试网站:"http://httpbin.org/cookies/set/number/123456789"。请求这个网站时,可以设置一个cookie,名称叫做number,内容是123456789,随后又请求了"http://httpbin.org/cookies",此网址可以获取当前的Cookies。
从输出结果,我们发现并没有成功获得Cookies
下面我们通过构建Session对象再试试
import requests
s = requests.Session()#构建Session对象
s.get("http://httpbin.org/cookies/set/number/123456789")
r = s.get("http://httpbin.org/cookies")
print(r.text)
输出结果:
这一次成功获取了Cookies,利用Session,可以做到模拟同一个会话而不用担心Cookies的问题。它通常用于模拟登陆成功之后再进行下一步的操作。
session的用使用范围非常广泛,可以用于模拟在一个浏览器中打开同一站点的不同页面,后面会有专门的章节来讲解这部分内容。
4.SSL证书验证
requests还提供证书验证功能,当发送HTTP请求的时候,它会检查SSL证书,我们可以使用verify参数控制是否检查此证书。 verify参数默认是True,会自动验证。
原来12306的证书没有被官方CA机构信任,会出现证书验证错误结果(现在已经没有这个问题了)
我们还是以它举例,如果要跳过SSL验证的话,只需要把verify参数设置为False即可
示例如下:
import requests
r = requests.get("https://www.12306.cn",verify = False)
print(r.status_code)
输出结果:
输出结果中,带有警告,可以通过以下两种方法来屏蔽或忽略警告。
【1】设置忽略警告
import requests
from requests.packages import urllib3
urllib3.disable_warnings()
r = requests.get("https://www.12306.cn",verify = False)
print(r.status_code)
输出结果:
【2】捕获警告到日志
import requests
import logging
logging.captureWarnings(True)
r = requests.get("https://www.12306.cn",verify = False)
print(r.status_code)
输出结果:
还可以指定一个本地证书作为客户端证书,这里我们就不详细讲了。
5.代理设置
对于某些网站,在测试的时候请求几次,就能正常获取内容。但一旦开始大规模爬取,对于大规模且频繁的请求,网站可能会弹出验证码,或者跳转到登陆验证页面,更有甚者可能会直接封禁客户端IP,导致一段时间无法访问。
所以为了防止单个ip频繁访问,导致弹出验证或封禁,我们需要设置代理IP来解决这个问题,这里需要用到proxies参数。
设置如下:
import requests
proxies = {
"http":"183.195.106.118:8118"
}
requests.get("https://www.taobao.com",proxies = proxies)
上面的代码不能直接运行,因为里面的代理可能是无效的,可以换成自己的有效代理试试。
如果代理需要使用到HTTP Basic Auth,可以使用类似http://user:password@host:port这样的语法来设置代理:
import requests
proxies = {
"http":"http://user:password@183.195.106.118:8118"
}
requests.get("https://www.taobao.com",proxies = proxies)
除了基本的HTTP代理外,requests还支持SOCKS协议的代理。
首先,需要安装socks这个库:
pip3 install requests[socks]
然后就可以使用SOCKS协议代理了,示例如下:
import requests
proxies = {
"http":"socks5://user:password@host:port"
}
requests.get("https://www.taobao.com",proxies = proxies)
6.超时设置
前面在urllib讲过,在网络状态不好等原因下,可能长时间无法获得响应,应该设置一个超时时间,超过这个时间没有得到响应就报错,也就是借助timeout参数。
示例如下:
import requests
r=requests.get("https://www.taobao.com",timeout= 1)
print(r.text)
通过上述设置,我们可以将超时时间设置为1秒,如果1秒中没有响应,就抛出异常,当然实际过程中可以根据需求设置。
实际上,请求分为两个阶段,即连接(connect)和读取(read)
timeout=设置的是两者时间的总和,如果要分别指定,可以传入一个元组。
示例如下:
import requests
r=requests.get("https://www.taobao.com",timeout= (3,3))
print(r.text)
如果想永久等待,timeout默认为None,直接不设置即可。
7.身份验证
在访问网站时,如果遇到需要进行身份验证,可以采用以下的简便方法
示例:
import requests
r=requests.get("http://localhost:5000/",auth=('username','password'))
print(r.text)
8.Prepared Request
在urllib中,我们可以将请求表示为数据结构,各参数通过Request对象来表示,在requests里同样可以做到,这个数据结构叫Prepared Request。
实例展示:
from requests import Request,Session
url = "http://httpbin.org/post"
data ={
'name':'germey'
}
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3314.0 Safari/537.36 SE 2.X MetaSr 1.0'
}
s=Session()
req = Request('POST',url,data=data,headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)
这里我们引入了Request,然后用url、data、headers参数构造了一个Requset对象,这时需要调用Session的prepare_request()方法将其转换为一个Prepared Request对象,然后调用send()方法发送即可。
输出结果:
从结果可以看到,我们成功获取了POST请求。
更多的用法或者问题,可以参考requests的官方文档:(https://requests.readthedocs.io/zh_CN/latest/user/advanced.html)
本文总结参考《Python3网络爬虫开发实战》