什么是Requests库?
requests库github地址:https://github.com/requests/requests
Reqyests库主要用来准备Request和处理Response。
为什么要学习Requests库?
web开发和爬虫都需要学习的东西,在服务端编程中理解好Requests库可以更好的编写Restful API的程序,还是自动化测试的工具箱。
安装Requests库
pip install requests
这个是安装requests库的
gunicorn是一个python Wsgi http server,只支持在Unix系统上运行,来源于Ruby的unicorn项目。
pip install httpbin
httpbin是一个http库的测试工具
gunicorn httpbin:app
通过gunicorn启动httpbin,可以通过127.0.0.1/8000访问
简单了解http协议
http协议:HyperText Transfer Protocl 超文本传输协议.
http协议是应用层上的一个无状态的协议,是一种为分布式,协作式,多媒体信息服务的协议。
Request:
第一行:分别是方法:GET,地址:/,协议:HTTP/1.1。
二三四行以key:value的形式组成headers。
< HTTP/1.1 200 OK
< Server: nginx
< Date: Sun, 16 Sep 2018 14:36:46 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 249314
< Connection: keep-alive
< Vary: Accept-Encoding
< Vary: Accept-Encoding
< X-Varnish: 636943726 641514266
< Age: 20
< Via: 1.1 varnish (Varnish/6.0)
< X-Cache: HIT from CS42
< Accept-Ranges: bytes
Response:
start line:状态码,具体解释
后面的也是组成一个headers,告诉浏览器怎么具体解析
慕课网-程序员的梦工厂Message Body
urllib
urllib和urllib2是相互独立的模块,在使用的时候需要两个结合使用
requests库使用了urllib3,urllib3则多了一些功能,比如多次请求重复使用一个socket,提升效率。
# _*_ coding: utf-8 _*_
import urllib2
import urllib
URL_IP = 'http://127.0.0.1:8000/ip'
URL_GET = 'http://127.0.0.1:8000/get'
def use_simple_urllib2():
response = urllib2.urlopen(URL_IP)
print '>>>>Response Headers:'
print response.info()
print '>>>>Response Body:'
print ''.join([line for line in response.readlines()])
def use_params_urllib2():
#构建请求参数
params = urllib.urlencode({'param1':'hello', 'param2':'world'})
print 'Request Params:'
print params
#发送请求
response = urllib2.urlopen('?'.join([URL_GET, '%s'])%params)
#处理响应
print '>>>>Response Headers:'
print response.info()
print '>>>>Status Code:'
print response.getcode()
print '>>>>Response Body:'
print ''.join([line for line in response.readlines()])
if __name__ == '__main__':
print '>>>>Use simple urllib2:'
use_simple_urllib2()
print '>>>>Use params urllib2:'
use_params_urllib2()
先启动gunicorn,然后运行上面的程序,
>>>>Use simple urllib2:
>>>>Response Headers:
Server: gunicorn/19.9.0
Date: Mon, 17 Sep 2018 03:18:04 GMT
Connection: close
Content-Type: application/json
Content-Length: 23
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
>>>>Response Body:
{"origin":"127.0.0.1"}
>>>>Use params urllib2:
Request Params:
param2=world¶m1=hello
>>>>Response Headers:
Server: gunicorn/19.9.0
Date: Mon, 17 Sep 2018 03:18:04 GMT
Connection: close
Content-Type: application/json
Content-Length: 245
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
>>>>Status Code:
>>>>Response Body:
{"args":{"param1":"hello","param2":"world"},"headers":{"Accept-Encoding":"identity","Connection":"close","Host":"127.0.0.1:8000","User-Agent":"Python-urllib/2.7"},"origin":"127.0.0.1","url":"http://127.0.0.1:8000/get?param2=world¶m1=hello"}
View result
可以得到上面的结果
urllib提供了一系列功能可以对URL进行操作,利用程序去执行各种http请求
简单使用requests
View Code
下面的是结果
>>>>Use simple requests:
>>>>Response Headers:
{'Content-Length': '216', 'Server': 'gunicorn/19.9.0', 'Connection': 'close', 'Access-Control-Allow-Credentials': 'true', 'Date': 'Mon, 17 Sep 2018 07:34:49 GMT', 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'}
>>>>Response Body:
{"args":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Connection":"keep-alive","Host":"127.0.0.1:8000","User-Agent":"python-requests/2.19.1"},"origin":"127.0.0.1","url":"http://127.0.0.1:8000/get"}
>>>>Use params requests
>>>>Response Headers:
{'Content-Length': '275', 'Server': 'gunicorn/19.9.0', 'Connection': 'close', 'Access-Control-Allow-Credentials': 'true', 'Date': 'Mon, 17 Sep 2018 07:34:49 GMT', 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'}
>>>>Status Code:
200
>>>>Response Body:
{u'origin': u'127.0.0.1', u'headers': {u'Connection': u'keep-alive', u'Host': u'127.0.0.1:8000', u'Accept-Encoding': u'gzip, deflate', u'Accept': u'*/*', u'User-Agent': u'python-requests/2.19.1'}, u'args': {u'param2': u'world', u'param1': u'hello'}, u'url': u'http://127.0.0.1:8000/get?param2=world¶m1=hello'}
以上就是一个简单的使用
requests库是用python实现的一个http库,使用起来要比urllib简单很多
对比requests和urllib的header可以发现,urllib的connection的状态是close,而requests的则是keep-alive,这是因为requests使用了urllib3,可以保持住连接,多次请求时可以减少资源的消耗,而urllib则是获取到消息后就关闭连接,再次需要获取时还需要再次建立,requests还支持更多的encoding格式
请求方法
GET:查看资源
POST:增加资源
PUT:修改资源
PATCH:更新部分资源
DELETE:删除资源
HEAD:查看响应头
OPTIONS:查看可用请求方法
使用方法:requests.[method](url)
带参数的请求
1.URL参数
使用方法:requests.get(url,params={'key1':'value1})
2.表单参数提交
Content-Type:application.x-www-form-urlencoded (表单默认的提交数据格式)
内容:key1=value1&key2=value2
requests.post(url,data={'key1':'value1','key2':'value2'})
3.json参数提交
Content-Type: appliction/json (json数据格式)
内容:'{"key":"value1","key2":"value2"}'
requests.post(url,json={'key1':'value1','key2':'value2'})
请求异常处理
requests库将常见的http错误打了一个包,就是exceptions,通过使用exceptions可以处理项目中各种异常
RequestException:
HTTPError(RequestException)
UnrewindableBodyError(RequestException)
RetryError(RequestException)
ConnectionError(RequestException) ProxyError(ConnectionError)
SSLError(ConnectionError)
ConnectTimeout(ConnectionError, Timeout)
Timeout(RequestException) ReadTimeout
URLRequired(RequestException)
TooManyRedirects(RequestException)
MissingSchema(RequestException, ValueError)
InvalidSchema(RequestException,ValueError)
InvalidURL(RequestException,ValueError)
InvalidHeader(RequestException,ValueError)
ChunkedEncodingError(RequestException)
StreamConsumedError(RequestException,TypeError)
ContentDecodingError(RequestException,BaseHTTPError)
常见的异常处理如上:
自定义Request
Session:包括代理信息(proxy),超时信息(timeout),验证信息等
PreparedRequest:在session中定义的另一个对象,包括消息主体(body),消息头部(headers),认证信息(auth)
Response:Request对象发出后,会获得一个Response对象,包括text,json等信息
处理响应
http状态码:
1xx:消息
100 Continue:客户端应当继续发送请求。这个临时响应是用来通知客户端它的部分请求已经被服务器接收,且仍未被拒绝。客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应。服务器必须在请求完成后向客户端发送一个最终响应。
2xx:成功
200 OK:请求已成功,请求所希望的响应头或数据体将随此响应返回。
202 Accepted:服务器已接受请求,但尚未处理。正如它可能被拒绝一样,最终该请求可能会也可能不会被执行。在异步操作的场合下,没有比发送这个状态码更方便的做法了。
返回202状态码的响应的目的是允许服务器接受其他过程的请求(例如某个每天只执行一次的基于批处理的操作),而不必让客户端一直保持与服务器的连接直到批处理操作全部完成。在接受请求处理并返回202状态码的响应应当在返回的实体中包含一些指示处理当前状态的信息,以及指向处理状态监视器或状态预测的指针,以便用户能够估计操作是否已经完成。
3xx:重定向
301 Moved Permanently:被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个URI之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。新的永久性的URI应当在响应的Location域中返回。除非这是一个HEAD请求,否则响应的实体中应当包含指向新的URI的超链接及简短说明。如果这不是一个GET或者HEAD请求,因此浏览器禁止自动进行重定向,除非得到用户的确认,因为请求的条件可能因此发生变化。
注意:对于某些使用HTTP/1.0协议的浏览器,当它们发送的POST请求得到了一个301响应的话,接下来的重定向请求将会变成GET方式。
4xx:客户端错误
403 Forbidden:服务器已经理解请求,但是拒绝执行它。与401响应不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交。如果这不是一个HEAD请求,而且服务器希望能够讲清楚为何请求不能被执行,那么就应该在实体内描述拒绝的原因。当然服务器也可以返回一个404响应,假如它不希望让客户端获得任何信息。
404 Not Found:请求失败,请求所希望得到的资源未被在服务器上发现。没有信息能够告诉用户这个状况到底是暂时的还是永久的。假如服务器知道情况的话,应当使用410状态码来告知旧资源因为某些内部的配置机制问题,已经永久的不可用,而且没有任何可以跳转的地址。404这个状态码被广泛应用于当服务器不想揭示到底为何请求被拒绝或者没有其他适合的响应可用的情况下。
5xx:服务器错误
500 Internal Server Error:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器的程序码出错时出现。
Response对象api:status_code(状态码),reason(状态码信息),headers(消息头部信息),url(来自的url),history(查看历史状况,从哪里跳转到哪里),elapsed(请求耗费的时间)。
ecoding(编码格式),raw(直接读取原始的response对象),content(string格式),text(这个是转换过的,unicode格式),json(方便获取信息)。
下载图片
利用简单的爬虫下载目标图片
View Code
流程是首先要模拟浏览器,通过开发者工具中User-Agent模拟,然后构建一个request对象,再读取流data,最后新建文件存入数据
事件钩子(Event Hooks)
Requests库线性处理
先发出一个IO请求,如GET,POST等,和服务器交互后返回,事件钩子会将Response塞入到回调处理中
View Code
运行结果:
application/json; charset=utf-8
HTTP认证
比较简单的认证:客户端发送一个requests要获取一个被保护的资源,Server端要求客户端提供账号和密码,客户端接着发送用户名和密码,服务端验证用户名和密码验证通过返回需要的资源
View Code
{"login":"imoocdemo","id":20262371,"node_id":"MDQ6VXNlcjIwMjYyMzcx","avatar_url":"https://avatars0.githubusercontent.com/u/20262371?v=4","gravatar_id":"","url":"https://api.github.com/users/imoocdemo","html_url":"https://github.com/imoocdemo","followers_url":"https://api.github.com/users/imoocdemo/followers","following_url":"https://api.github.com/users/imoocdemo/following{/other_user}","gists_url":"https://api.github.com/users/imoocdemo/gists{/gist_id}","starred_url":"https://api.github.com/users/imoocdemo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/imoocdemo/subscriptions","organizations_url":"https://api.github.com/users/imoocdemo/orgs","repos_url":"https://api.github.com/users/imoocdemo/repos","events_url":"https://api.github.com/users/imoocdemo/events{/privacy}","received_events_url":"https://api.github.com/users/imoocdemo/received_events","type":"User","site_admin":false,"name":"babymooc2","company":"尖峰科技","blog":"http://2333.org","location":"aufe-xx","email":null,"hireable":true,"bio":"future is now","public_repos":1,"public_gists":0,"followers":1,"following":1,"created_at":"2016-07-03T03:12:42Z","updated_at":"2018-08-24T08:12:37Z","private_gists":1,"total_private_repos":0,"owned_private_repos":0,"disk_usage":0,"collaborators":0,"two_factor_authentication":false,"plan":{"name":"free","space":976562499,"collaborators":0,"private_repos":0}}
{'Authorization': 'Basic aW1vb2NkZW1vOmltb29jZGVtbzEyMw==', 'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.19.1'}
OAUTH认证:用户打开客户端页面,客户端请求用户的授权,用户确认以后会向客户端返回一个含有code的url,客户端会截取其中的code,向获取授权的服务器发起一个POST请求,要求获取access_token,授权服务器认证以后,会返回一个access_token,然后客户端会用这个access_token向资源服务器获取资源,资源服务器返回受保护的资源.这个过程客户端是一直没有接触到用户的用户名和密码的,比较安全。
代理Proxy
代理就是一个中间人,客户端和proxy(充当服务端)建立连接,proxy就负责将客户端请求发送到外网,再将返回的信息发送给客户端
Session和Cookie
Session是保存在服务端的用户信息,cookie是保存在浏览器的用户信息。
浏览器向服务器发出一个http请求(是无cookie的),服务器认证后会发回一个http响应(set cookie),服务这时是可以设置cookie有效期,权限范围等。浏览器获取cookie后会解析并保存再本地,之后浏览器的http请求都会带上cookie,服务器则直接解析cookie,识别地址,确认后http响应。
浏览器向服务器发出一个http请求(是无cookie的),服务器认证后会建立一个会话,存储session,接着发回一个http响应(set cookie-session-id),客户端接收http响应,解析cookie保存再本地,这个解析出来的东西很小,只有一个session-id,浏览器发起带cookie的http请求,服务器收到后解析获取到其中的session-id,然后在存储中查对应的用户信息权限等,然后再传回一个http响应。