最近在忙综设的爬虫程序,没时间及时写博客,就当成是复习一下内容吧~
上次讲到了使用urllib库,接下来来说说requests库吧。
3.2.1 requests库的一些基本用法
requests调用get方法,返回一个requests.models.Response对象
之后可以调用方法来获取类型、状态码、网页内容、cookie等信息~
r = requests.get('https://www.baidu.com/')
print(type(r))
print(r.status_code)
print(type(r.text))
print(r.text)
print(r.cookies)
更方便之处不在以上内容,在于其他的请求类型也可以使用一句话来完成,就像get一样呢~比如:
r = requests.post('https://www.httpbin.org/post')
对于put delete head等等请求类型,也是一样通过一句话来完成~
1、get请求
基本实例
r = requests.get('https://www.baidu.com/')
print(r.text)
r.text返回请求的内容~
那么对于请求中的额外信息要怎么添加呢?
可以写个参数,之后在get方法传入参数就可以啦~
data = {
'name' : 'germey',
'age' : 22
}
r = requests.get('http://httpbin.org/get', params=data)
print(r.text)
网页的返回类型实际上是str类型,但是它很特殊,是JSON格式。
所以呢,如果想要直接解析返回结果,得到一个字典格式的话,那么可以直接调用json()方法。
抓取网页
headers = {
'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
}
r = requests.get('https://www.zhihu.com/explore',headers= headers)
pattern = re.compile('explore-feed.*?question_link.*?>(.*?)</a>',re.S)
titles = re.findall(pattern,r.text)
print(titles)
如果请求普通的网页,则肯定是可以获得相应的内容。
这里我们加入了User-Agent字段信息,也就是浏览器标识的信息。如果不加这个,知乎会禁止抓取网页~
抓取二进制数据
上面的例子,我们抓取的是知乎的一个页面,返回的是一个HTML文档。如果想要抓取图片,视频,音频等文件,那么本质上就是拿到他们的***二进制码***~~
r = requests.get('https://github.com/favicon.ico')
with open('favicon.ico', 'wb') as f:
f.write(r.content)
这段代码是抓取github中小图标,并且将其保存在favicon.ico的文件里。
4、POST请求
就是调用requests库的post方法~
5、相应
headers = {
'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
}
r = requests.get("http://jianshu.com",headers)
exit() if not r.status_code == requests.codes.ok else print("Request Successfully")
print(type(r.status_code), r.status_code)
print(type(r.headers), r.headers)
print(type(r.cookies),r.cookies)
print(type(r.url), r.url)
print(type(r.history), r.history)
这里可以调用上述的方法,来获取状态码、响应头、Cookies等等~
6、高级用法
文件上传
我们可以了解到,requests可以提交一些数据。假如有些网站需要上传文件,我们可以用它来实现~
files = {'file' : open('favicon.ico','rb')}
r = requests.post("http://httpbin.org/post", files= files)
print(r.text)
注意:favicon.ico需要与当前脚本在同一个目录下~
Cookies
使用requests来获取和设置Cookies只需要一步即可完成~
获取Cookies的过程:
r = requests.get("https://www.baidu.com")
print(r.cookies)
for key, value in r.cookies.items():
print(key + " =" + value)
这里首先调用cookies属性即可成功得到Cookies,可以发现这是一个RequestCookieJar类型,然后使用items()方法将其转化成元组组成的列表,遍历输出每一个Cookie的名称和值~
Cookie可以用来维持登录状态,下面不加赘述~
会话维持
在requests中,如果直接利用get()或者post()等方法是可以做到模拟网页的请求,但是这实际上是属于两种不同的对话,也就是相当于使用了两个不同的浏览器打开了不同的页面~
比如:第一个请求使用了post()方法登录了某个网站,第二次想获取成功登录后的自己的个人信息,又使用了一次get()方法去请求个人信息页面。实际上,相当于打开了两个浏览器,是两个完全不相同的会话,无法成功获取个人信息的哦~~
当然,我们在两次请求时,全都设置一样的cookies也可以,但是看起来很繁琐呀!我们为啥不用更好的解决方法呢?
解决这个问题的关键就是维持同一个会话,相当于打开一个浏览器选项卡而不是新开一个浏览器——我们可以使用Session对象。
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
这个网站可以获取当前cookie
运行上面那段代码:
{
"cookies": {}
}
那么使用Session呢??
看看下面的代码哦~
s = requests.Session()
s.get("http://httpbin.org/cookies/set/number/123456789")
r = s.get("http://httpbin.org/cookies")
print(r.text)
运行结果如下:
{
"cookies": {
"number": "123456789"
}
}
一个对话和两个对话差别还是很大的哈哈哈
利用Session可以做到模拟同一个对话而不用担心Cookies的问题~
Session平常用的十分广泛,可以用于模拟一个浏览器中打开同一站点的不同页面。
SSL证书认证
requests还提供了证书认证的功能,当发送HTTP请求的时候,它会检测SSL证书,我们可以在请求的时候使用verify参数来控制是否检查此证书,如果不加verify参数,那么会默认verify的值为True,会自动验证~
response = requests.get('https://12306.cn',verify=False)
print(response.status_code)
代理设置
对于某些网站,在测试的时候请求几次,还能够正常获取内容,但是一旦开始大规模爬取时,对于大规模并且频繁的请求,网站可能会跳出验证码,或者跳转到登录验证的页面,更甚者会直接封禁客户端的IP,导致在一定时间段内无法访问~~
那么为了防止这种情况发生,我们需要设置代理来解决这个问题,这就需要proxies参数,可以用这种方式来设置:
proxies = {
"http" : "http://user:password@10.10.1.10:3128/",
}
requests.get("https://www.taobao.com",proxies)
出了基本的HTTP代理之外,requests还支持SOCKS协议的代理~
超时设置
可以在get()方法中设置:timeout参数
timeout参数由两个部分组成——连接和读取
timeout本身的值为连接和读取的和
在参数设置的时候,可以设置为元组或者单个数
身份验证
可以使用requests自带的身份验证功能:
r = requests.get("http://localhost:5000",auth=('username', 'password'))
print(r.status_code)
Prepared Request
在requests中也可以像urllib一样,通过一个对象将参数传入~
这就是Prepared Request对象
from requests import Request, Session
url = 'http://httpbin.org/post'
data = {
'name' : 'germey',
}
headers = {
'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36',
'Connection': 'close'
}
s = Session()
req = Request('POST', url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)
这里先用Request构造一个Request对象,之后再用prepare_request构造出Prepared Request对象,之后在调用send方法发送即可~
可以看出达到了和POST同样的请求结果~