在学习用python写爬虫的时候用到了Requests这个Http网络库,这个库简单好用而且功能强大,彻底能够代替python的标准库urllib2。在学习的同时把个人学习笔记记录下来,资料基本上都是从Requests官网翻译过来的,欢迎指出有错误或者有表述的不许确的地方。html
1.介绍
Requests: HTTP for Humans
一句话:为地球人准备的网络库python
python的标准库urllib2已经提供了大部分你所须要的HTTP功能了,为何还须要Requests库来提供相同的功能呢?由于urllib2的API比较零散,它们编写的时间和网络环境都不同,利用它(urllib2)完成简单的任务须要作大量的工做。nginx
2.安装
安装也很简单,用easy_install命令: easy_install requests
git
用pip命令:pip install requests
github
源代码在这里githubweb
3.例子
使用Requests:json
>>> r = requests.get('https://api.github.com/user', auth=('user', 'pass')) >>> r.status_code 200 >>> r.headers['content-type'] 'application/json; charset=utf8' >>> r.encoding 'utf-8' >>> r.text u'{"type":"User"...' >>> r.json() {u'private_gists': 419, u'total_private_repos': 77, ...}'
使用urllib2:api
#!/usr/bin/env python # -*- coding: utf-8 -*- import urllib2 gh_url = 'https://api.github.com' req = urllib2.Request(gh_url) password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() password_manager.add_password(None, gh_url, 'user', 'pass') auth_manager = urllib2.HTTPBasicAuthHandler(password_manager) opener = urllib2.build_opener(auth_manager) urllib2.install_opener(opener) handler = urllib2.urlopen(req) print handler.getcode() print handler.headers.getheader('content-type')' # ------ # 200 # 'application/json'
爬虫的入门能够参考42区的一个小爬虫 。服务器
4.功能介绍cookie
>>> r = requests.post("http://httpbin.org/post") >>> r = requests.put("http://httpbin.org/put") >>> r = requests.delete("http://httpbin.org/delete") >>> r = requests.head("http://httpbin.org/get") >>> r = requests.options("http://httpbin.org/get")
想在请求URL中带参数,例如这样httpbin.org/get?key=val
,Requests容许你提供一个字典做为这些参数:
>>> payload = {'key1': 'value1', 'key2': 'value2'} >>> r = requests.get("http://httpbin.org/get", params=payload)
你能够看到输出的URL已经通过正确的编码:
>>> print r.url u'http://httpbin.org/get?key2=value2&key1=value1'
请求发送后,咱们能够读取服务器返回的内容,看刚刚的例子:
>>> import requests >>> r = requests.get('https://github.com/timeline.json') >>> r.text '[{"repository":{"open_issues":0,"url":"https://github.com/...
Requests会自动decode服务器返回的内容,大部分unicode的字符均可以顺利的decode。
当访问r.text
时,Requests会根据response的Http标头信息使用相应的文本编码输出信息,能够查看Requests使用的是什么类型的编码并改变它:
>>> r.encoding 'utf-8' >>> r.encoding = 'ISO-8859-1'
若是改变了编码类型,当调用r.text
的时候,Requests会使用你设置的编码类型输出信息。
对于非文本的请求,也能够把返回的响应内容做为字节类型输出:
>>> r.content b'[{"repository":{"open_issues":0,"url":"https://github.com/...
gzip和deflate编码会为你自动解码,
例如想把一个请求返回的二进制数据装换成图像,能够这样写:
>>> from PIL import Image >>> from StringIO import StringIO >>> i = Image.open(StringIO(r.content))
Requests还提供了一个json的decoder,能够方便的处理json格式的数据
>>> import requests >>> r = requests.get('https://github.com/timeline.json') >>> r.json() [{u'repository': {u'open_issues': 0, u'url': 'https://github.com/...
调用r.json()
方法时,若是请求的内容不是json格式,会致使json解码失败,抛出异常。
如过想从服务器返回的响应中获取原始的套接字响应,能够调用r.raw
方法,在调用前须要在请求中设置stream=True
,例如:
>>> r = requests.get('https:/github.com/timeline.json', stream=True) >>> r.raw <requests.packages.urllib3.response.HTTPResponse object at 0x101194810> >>> r.raw.read(10) '\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
若是想在请求时添加一个Http标头,能够在请求时添加一个字典类型的参数,例如:
>>> import json >>> url = 'https://api.github.com/some/endpoint' >>> payload = {'some': 'data'} >>> headers = {'content-type': 'application/json'} >>> r = requests.post(url, data=json.dumps(payload), headers=headers)
一般,若是想要发送一些表单类型的数据(像Html表单这样的数据),在这里,只须要把Html的表单数据构形成一个字典类型的参数附带在请求中便可。
>>> payload = {'key1': 'value1', 'key2': 'value2'} >>> r = requests.post("http://httpbin.org/post", data=payload) >>> print r.text { ... "form": { "key2": "value2", "key1": "value1" }, ... }
不少时候咱们发送的数据并非表单类型的数据,就像咱们想传递一个字符串类型而不是字典类型的数据时,数据会被直接的发送出去:
>>> import json >>> url = 'https://api.github.com/some/endpoint' >>> payload = {'some': 'data'} >>> r = requests.post(url, data=json.dumps(payload))
Requests提供简单的方式去发送Multipart-Encoded文件:
>>> url = 'http://httpbin.org/post' >>> files = {'file': open('report.xls', 'rb')} >>> r = requests.post(url, files=files) >>> r.text { ... "files": { "file": "<censored...binary...data>" }, ... }
还能够设定文件名:
>>> url = 'http://httpbin.org/post' >>> files = {'file': ('report.xls', open('report.xls', 'rb'))} >>> r = requests.post(url, files=files) >>> r.text { ... "files": { "file": "<censored...binary...data>" }, ... }
若是你想,你还能够发送字符串做为接受的文件:
>>> url = 'http://httpbin.org/post' >>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')} >>> r = requests.post(url, files=files) >>> r.text { ... "files": { "file": "some,data,to,send\\nanother,row,to,send\\n" }, ... }
咱们能够查看响应的状态码
>>> r = requests.get('http://httpbin.org/get') >>> r.status_code 200
为了方便参考,Requests还配备了一个内置的状态码对象
>>> r.status_code == requests.codes.ok True
若是咱们的请求是一个失败的请求(非200的status code),咱们能够调用Response.raise_for_status()
方法将异常抛出:
>>> bad_r = requests.get('http://httpbin.org/status/404') >>> bad_r.status_code 404 >>> bad_r.raise_for_status() Traceback (most recent call last): File "requests/models.py", line 832, in raise_for_status raise http_error requests.exceptions.HTTPError: 404 Client Error
可是,若是咱们的Response的status_code是200,当咱们调用raise_for_status()
时:
>>> r.raise_for_status() None
返回的就是None,All is well.
咱们能够以python字典类型的格式查看服务器返回的响应报头
>>> r.headers { 'status': '200 OK', 'content-encoding': 'gzip', 'transfer-encoding': 'chunked', 'connection': 'close', 'server': 'nginx/1.0.4', 'x-runtime': '148ms', 'etag': '"e1ca502697e5c9317743dc078f67693f"', 'content-type': 'application/json; charset=utf-8' }
咱们知道dictionary的key值是大小写敏感的,但这里的dictionary有点特殊,它只是用来保存Http的标头信息,根据RFC 2616,HTTP标头是不区分大小写的。
因此咱们能够使用任意大小写获取标头属性的值:
>>> r.headers['Content-Type'] 'application/json; charset=utf-8' >>> r.headers.get('content-type') 'application/json; charset=utf-8'
若是访问头文件不存在的属性,默认返回一个None:
>>> r.headers['X-Random'] None
若是一个response包含Cookies信息,你能够很快速的访问它们:
>>> url = 'http://httpbin.org/cookies/set/requests-is/awesome' >>> r = requests.get(url) >>> r.cookies['requests-is'] 'awesome'
你能够设置本身的cookies利用cookies
这个参数发送到服务器:
>>> url = 'http://httpbin.org/cookies' >>> cookies = dict(cookies_are='working') >>> r = requests.get(url, cookies=cookies) >>> r.text '{"cookies": {"cookies_are": "working"}}'
当使用GET和OPTIONS请求类型时,Requests会帮你自动重定向。
GitHub会重定向全部HTTP请求到HTTPS,咱们能够调用response的history
方法跟踪重定向:
>>> r = requests.get('http://github.com') >>> r.url 'https://github.com/' >>> r.status_code 200 >>> r.history [<Response [301]>]
调用response.history返回的列表包含了一系列为了完成请求而建立的对象,这个列表按照从最开始的请求到最后的请求进行排序。
若是使用GET和OPTION请求类型,能够设置allow_redirects
这个参数来关闭自动重定向:
>>> r = requests.get('http://github.com', allow_redirects=False) >>> r.status_code 301 >>> r.history []
若是使用的是POST, PUT, PATCH, DELETE或者HEAD,你也能够打开重定向功能:
>>> r = requests.post('http://github.com', allow_redirects=True) >>> r.url 'https://github.com/' >>> r.history [<Response [301]>]
你能够设置timeout
参数的值,让请求在到达指定的时间后中止等待服务器的响应。
>>> requests.get('http://github.com', timeout=0.001) Traceback (most recent call last): File "<stdin>", line 1, in <module> requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
注意:timeout
的设置只是影响请求的链接过程,不影响下载的response body。
在发生网络问题时(如DNS失败、拒绝链接,等等)Requests会抛出一个ConnectionError
的异常。
接收到Http无效的响应时,Requests会抛出一个HTTPError
的异常。
若是请求超时了,会抛出一个请求超时的异常。
若是一个请求超过了配置的重定向次数,会抛出TooManyRedirects
异常。
全部Requests的异常都显示的继承自requests.exceptions.RequestException
.
(完)