咱們可使用Python內置的urllib包來請求網絡資源。但它用起來比較麻煩,並且缺乏不少實用的高級功能。本文咱們將會介紹一個更加方便的Python第三方庫——Requests的使用。html
要安裝Requests
,只要在終端中運行這個簡單命令便可:python
pip install -i https://pypi.douban.com/simple requests
安裝好Requests
後,就能夠開始嘗試使用它啦!nginx
使用Requests
發送網絡請求很是簡單。導入Requests
模塊:git
import requests
而後獲取某個網頁。咱們來獲取Github的公共時間線:github
r = requests.get('https://api.github.com/events')
如今,有了一個名爲r
的Response
的對象。咱們能夠從這個對象中獲取全部咱們想要的信息。json
咱們可能會想用URL的查詢字符串傳遞某種數據。若是是手動構建URL,那麼數據會以鍵值對的形式置於URL中,跟在一個問號的後面。例如,http://httpbin.org/get?key=val
。Requests
容許咱們使用params
關鍵字參數,以一個字符串字典來提供這些參數。舉例來講,若是想傳遞key1=value1
和key2=value2
到http://httpbin.org/get
,那麼可使用以下代碼:api
import requests payload = {'name':'viljw', 'cat':'ruby'} r = requests.get('http://httpbin.org/get', params=payload)
打印輸出該URL,能看到URL已被正確編碼:ruby
print(r.url) # http://httpbin.org/get?name=viljw&cat=ruby
咱們能讀取服務器響應內容。舉個例子:服務器
import requests r = requests.get("http://httpbin.org/get") print(r.text)
輸出內容以下:cookie
Requests
會自動節碼來自服務器的內容。大多數unicode字符集都能被無縫地解碼。
請求發出後,Requests
會基於HTTP頭部對響應的編碼做出有根據的推測。當訪問r.text
時,Requests
會使用其推測的文本編碼。咱們能夠找出Requests
使用了什麼編碼,而且可以使用r.encoding
屬性來改變它:
import requests r = requests.get("http://httpbin.org/get") print(r.encoding) r.encoding = 'utf-8' print(r.encoding)
若是改變了編碼,每當訪問r.text
,Requests
都將會使用r.encoding
的新值。
對於非文本請求,也能以字節的方式訪問請求響應體。例如,以請求返回的二進制數據建立一張圖片,可使用以下代碼:
import requests from PIL import Image from io import BytesIO r = requests.get("https://github.com/fluidicon.png") im = Image.open(BytesIO(r.content)) im.show()
Requests
中有一個內置的JSON解碼器,幫助咱們處理JSON數據:
import requests from pprint import pprint payload = {'name':"viljw", 'cat':'ruby'} r = requests.get("http://httpbin.org/get", params=payload) pprint(r.json())
若是想爲請求添加HTTP頭部,只要簡單地傳遞一個dict
給headers
參數就可。
import requests from pprint import pprint headers = {'User-Agent': 'viljw-agent'} r = requests.get("http://httpbin.org/get", headers=headers) pprint(r.json())
以下圖所示,User-Agent
字段的值已被更改成viljw-agent
。
一般,咱們會想要發送一些編碼爲表單形式的數據——很是像一個HTML表單。要實現這個,只須要簡單地傳遞一個字典給data
參數。字典數據在發出請求時會自動編碼爲表單形式:
import requests payload = {"name":"viljw", "actor":"peter"} r = requests.post("http://httpbin.org/post", data=payload) print(r.text)
還能夠給data
參數傳入一個元組列表。在表單中多個元素使用同一key的時候,這種方式頗有用:
import requests payload = [("name","viljw"), ("actor","peter"),("actor",'marry')] r = requests.post("http://httpbin.org/post", data=payload) print(r.text)
咱們能夠查看響應狀態碼:
import requests r = requests.get("http://httpbin.org/get") print(r.status_code) # 200
爲了方便使用,Requests
附帶了也給內置的狀態碼查詢對象:
r.status_code == requests.codes.ok # True
若是發送了一個錯誤請求(一個4XX客戶端錯誤,或5XX服務器錯誤響應),咱們能夠經過Response.raise_for_status()
來拋出異常:
In [1]: import requests In [2]: bad_r = requests.get('http://httpbin.org/status/404') In [3]: bad_r.status_code Out[3]: 404 In [4]: bad_r.raise_for_status() --------------------------------------------------------------------------- HTTPError Traceback (most recent call last) <ipython-input-4-cdf6910f7d4c> in <module>() ----> 1 bad_r.raise_for_status() c:\python\lib\site-packages\requests\models.py in raise_for_status(self) 927 928 if http_error_msg: --> 929 raise HTTPError(http_error_msg, response=self) 930 931 def close(self): HTTPError: 404 Client Error: NOT FOUND for url: http://httpbin.org/status/404
但因爲咱們的例子中r
的status_code
是200,當咱們調用raise_for_status()
時,獲得的是:
In [6]: r.raise_for_status() # None
咱們能夠查看以字典形式的服務器響應頭:
In [7]: r.headers Out[7]: {'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', 'Content-Encoding': 'gzip', 'Content-Type': 'application/json', 'Date': 'Thu, 03 Oct 2019 07:11:16 GMT', 'Referrer-Policy': 'no-referrer-when-downgrade', 'Server': 'nginx', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', 'X-XSS-Protection': '1; mode=block', 'Content-Length': '184', 'Connection': 'keep-alive'}
若是某個響應中包含一些cookie,能夠快速訪問它們:
In [19]: r = requests.get('https://www.baidu.com') In [20]: r.cookies Out[20]: <RequestsCookieJar[Cookie(version=0, name='BDORZ', value='27315', port=None, port_specified=False, domain='.baidu.com', domain_specified=True, domain_initial_dot=True, path='/', path_specified=True, secure=False, expires=1570173564, discard=False, comment=None, comment_url=None, rest={}, rfc2109=False)]> In [21]: r.cookies['BDORZ'] Out[21]: '27315'
要想發送cookies到服務器,可使用cookies
參數:
In [27]: url = 'http://httpbin.org/cookies' In [28]: cookies = dict(cookies_are="working") In [29]: r = requests.get(url, cookies=cookies) In [30]: r.json() Out[30]: {'cookies': {'cookies_are': 'working'}}
能夠告訴Requests
在通過以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)
遇到網絡問題(如:DNS查詢失敗、拒絕鏈接等)時,Requests
會拋出一個ConnectionError
異常。
若是HTTP請求返回了不成功的狀態碼, Response.raise_for_status()
會拋出一個HTTPError
異常。
若請求超時,則拋出一個Timeout
異常。
若請求超過了設定的最大重定向次數,則會拋出一個TooManyRedirects
異常。
全部Requests
顯式拋出的異常都繼承自 requests.exceptions.RequestException
。
若是須要使用代理,能夠經過任意請求方法提供proxies
參數來配置單個請求:
import requests proxies = { 'https': 'https://127.0.0.1:1080' } r = requests.get('https://www.google.com', proxies=proxies) print(r.status_code) # 200
也能夠經過環境變量HTTP_PROXY
和HTTPS_PROXY
來配置代理。
$ export HTTP_PROXY="http://10.10.1.10:3128" $ export HTTPS_PROXY="http://10.10.1.10:1080" $ python >>> import requests >>> requests.get("http://example.org")