Requests:Python HTTP Module學習筆記(一)(轉)

Requests:Python HTTP Module學習筆記(一)

在學習用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 requestsgit

用pip命令:
pip install requestsgithub

源代碼在這裏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

Requests支持全部的Http請求類型,例如:

>>> 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中傳遞參數(Passing Parameters In URLs)

想在請求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'

響應內容(Response Content)

請求發送後,咱們能夠讀取服務器返回的內容,看剛剛的例子:

>>> 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會使用你設置的編碼類型輸出信息。

二進制的相應內容(Binary Response Content)

對於非文本的請求,也能夠把返回的響應內容做爲字節類型輸出:

>>> 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))

以json格式返回響應內容(JSON Response 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解碼失敗,拋出異常。

原始的響應內容(Raw Response Content)

如過想從服務器返回的響應中獲取原始的套接字響應,能夠調用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'

自定義頭文件(Custom Headers)

若是想在請求時添加一個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)

更復雜的post請求(More complicated POST requests)

一般,若是想要發送一些表單類型的數據(像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))

上傳Multipart-Encoded的文件(POST a Multipart-Encoded File)

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"
   },
   ...
}

響應的狀態代碼(Response Status Codes)

咱們能夠查看響應的狀態碼

>>> 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.

響應報頭(Response Headers)

咱們能夠以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

Cookies

若是一個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"}}'

重定向和歷史(Redirection and History)

當使用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]>]

超時(Timeouts)

你能夠設置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。

錯誤和異常(Errors and Exceptions)

  • 在發生網絡問題時(如DNS失敗、拒絕鏈接,等等)Requests會拋出一個ConnectionError的異常。

  • 接收到Http無效的響應時,Requests會拋出一個HTTPError的異常。

  • 若是請求超時了,會拋出一個請求超時的異常。

  • 若是一個請求超過了配置的重定向次數,會拋出TooManyRedirects異常。

  • 全部Requests的異常都顯示的繼承自requests.exceptions.RequestException.

對Requests庫的入門介紹先到這樣,在下一篇日誌,我會繼續介紹它的一些高級特性。

(完)

相關文章
相關標籤/搜索