在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ Requests 庫(kù)的使用
基礎(chǔ)
itertools
HTTP 服務(wù)
hashlib
閉包
文件和目錄
類(lèi)
單元測(cè)試
使用 @property
標(biāo)準(zhǔn)模塊
陌生的 metaclass
Base64
進(jìn)程、線(xiàn)程和協(xié)程
讀寫(xiě)二進(jìn)制文件
匿名函數(shù)
輸入和輸出
Click
元組
字符編碼
partial 函數(shù)
參考資料
collections
協(xié)程
類(lèi)和實(shí)例
Python 之旅
定制類(lèi)和魔法方法
常用數(shù)據(jù)類(lèi)型
繼承和多態(tài)
ThreadLocal
HTTP 協(xié)議簡(jiǎn)介
Requests 庫(kù)的使用
讀寫(xiě)文本文件
列表
os 模塊
迭代器 (Iterator)
正則表達(dá)式
集合
上下文管理器
異常處理
你不知道的 super
定義函數(shù)
datetime
資源推薦
字典
slots 魔法
hmac
第三方模塊
進(jìn)程
類(lèi)方法和靜態(tài)方法
函數(shù)參數(shù)
高階函數(shù)
函數(shù)
re 模塊
高級(jí)特性
線(xiàn)程
argparse
生成器
結(jié)束語(yǔ)
字符串
map/reduce/filter
函數(shù)式編程
Celery
裝飾器

Requests 庫(kù)的使用

Python 的標(biāo)準(zhǔn)庫(kù) urllib 提供了大部分 HTTP 功能,但使用起來(lái)較繁瑣。通常,我們會(huì)使用另外一個(gè)優(yōu)秀的第三方庫(kù):Requests,它的標(biāo)語(yǔ)是:Requests: HTTP for Humans

Requests 提供了很多功能特性,幾乎涵蓋了當(dāng)今 Web 服務(wù)的需求,比如:

  • 瀏覽器式的 SSL 驗(yàn)證
  • 身份認(rèn)證
  • Keep-Alive & 連接池
  • 帶持久 Cookie 的會(huì)話(huà)
  • 流下載
  • 文件分塊上傳

下面,我們將從以下幾個(gè)方面介紹 Requests 庫(kù):

  • HTTP 請(qǐng)求
  • HTTP 響應(yīng)
  • cookie
  • 會(huì)話(huà)對(duì)象
  • 代理
  • 身份認(rèn)證

HTTP 請(qǐng)求

我們知道,一個(gè) HTTP 請(qǐng)求由三部分構(gòu)成:

  • 請(qǐng)求行:包含請(qǐng)求方法(比如 GET, POST)、請(qǐng)求地址和 HTTP 協(xié)議版本
  • 請(qǐng)求頭:包含一系列的鍵值對(duì)
  • 請(qǐng)求正文(可選)

如圖所示:

Requests 提供了幾乎所有 HTTP 動(dòng)詞的功能:GET、OPTIONS、HEAD、POST、PUT、PATCH、DELETE,另外,它提供了 headers 參數(shù)讓我們根據(jù)需求定制請(qǐng)求頭。

使用 Requests 發(fā)送一個(gè)請(qǐng)求很方便,比如:

import requests

r = requests.get("http://httpbin.org/get")
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")

下面,我們重點(diǎn)講一下 GET 請(qǐng)求,POST 請(qǐng)求和定制請(qǐng)求頭。

GET 請(qǐng)求

使用 Requests 發(fā)送 GET 請(qǐng)求非常簡(jiǎn)單,如下:

import requests

r = requests.get("http://httpbin.org/get")

在有些情況下,URL 會(huì)帶參數(shù),比如 https://segmentfault.com/blogs?page=2,這個(gè) URL 有一個(gè)參數(shù) page,值為 2。Requests 提供了 params 關(guān)鍵字參數(shù),允許我們以一個(gè)字典來(lái)提供這些參數(shù),比如:

import requests

payload = {'page': '1', 'per_page': '10'}
r = requests.get("http://httpbin.org/get", params=payload)

通過(guò)打印該 URL,我們可以看到 URL 已被正確編碼:

>>> print r.url
http://httpbin.org/get?per_page=10&page=1

需要注意的是字典里值為 None 的鍵不會(huì)被添加到 URL 的查詢(xún)字符串中。

POST 請(qǐng)求

使用 Requests 發(fā)送 POST 請(qǐng)求也很簡(jiǎn)單,如下:

import requests

r = requests.post("http://httpbin.org/post")

通常,我們?cè)诎l(fā)送 POST 請(qǐng)求時(shí)還會(huì)附上數(shù)據(jù),比如發(fā)送編碼為表單形式的數(shù)據(jù)或編碼為 JSON 形式的數(shù)據(jù),這時(shí),我們可以使用 Requests 提供的 data 參數(shù)。

  • 發(fā)送編碼為表單形式的數(shù)據(jù)

通過(guò)給 data 參數(shù)傳遞一個(gè) dict,我們的數(shù)據(jù)字典在發(fā)出請(qǐng)求時(shí)會(huì)被自動(dòng)編碼為表單形式,比如:

import requests

payload = {'page': 1, 'per_page': 10}
r = requests.post("http://httpbin.org/post", data=payload)

看看返回的內(nèi)容(省略了部分?jǐn)?shù)據(jù)):

>>> print r.text
{
  ...
  "form": {
    "page": "1", 
    "per_page": "10"
  }, 
  ...
}
  • 發(fā)送編碼為 JSON 形式的數(shù)據(jù)

如果給 data 參數(shù)傳遞一個(gè) string,我們的數(shù)據(jù)會(huì)被直接發(fā)布出去,比如:

import json
import requests

payload = {'page': 1, 'per_page': 10}
r = requests.post("http://httpbin.org/post", data=json.dumps(payload))

看看返回:

>>> print r.text
{
  "args": {}, 
  "data": "{\"per_page\": 10, \"page\": 1}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "27", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.9.1"
  }, 
  "json": {
    "page": 1, 
    "per_page": 10
  }, 
  "origin": "13.75.42.240", 
  "url": "http://httpbin.org/post"
}

在上面,我們自行對(duì) dict 進(jìn)行了編碼,這種方式等價(jià)于使用 json 參數(shù),而給它傳遞 dict,如下:

import requests

payload = {'page': 1, 'per_page': 10}
r = requests.post("http://httpbin.org/post", json=payload)

這種做法跟上面的做法是等價(jià)的,數(shù)據(jù)在發(fā)出時(shí)會(huì)被自動(dòng)編碼。

請(qǐng)求頭

有時(shí),我們需要為請(qǐng)求添加 HTTP 頭部,我們可以通過(guò)傳遞一個(gè) dictheaders 參數(shù)來(lái)實(shí)現(xiàn)。比如:

import requests

url = 'http://httpbin.org/post'
payload = {'page': 1, 'per_page': 10}
headers = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}

r = requests.post("http://httpbin.org/post", json=payload, headers=headers)

發(fā)送到服務(wù)器的請(qǐng)求的頭部可以通過(guò) r.request.headers 訪(fǎng)問(wèn):

>>> print r.request.headers
{'Content-Length': '27', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)', 'Connection': 'keep-alive', 'Content-Type': 'application/json'}

服務(wù)器返回給我們的響應(yīng)頭部信息可以通過(guò) r.headers 訪(fǎng)問(wèn):

>>> print r.headers
{'Content-Length': '462', 'Server': 'nginx', 'Connection': 'close', 'Access-Control-Allow-Credentials': 'true', 'Date': 'Mon, 05 Dec 2016 15:41:05 GMT', 'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'}

HTTP 響應(yīng)

HTTP 響應(yīng)與 HTTP 請(qǐng)求相似,由三部分組成:

  • 狀態(tài)行:包含 HTTP 協(xié)議版本、狀態(tài)碼和狀態(tài)描述,以空格分隔
  • 響應(yīng)頭:包含一系列的鍵值對(duì)
  • 響應(yīng)正文

如圖所示:

當(dāng)我們使用 requests.* 發(fā)送請(qǐng)求時(shí),Requests 做了兩件事:

  • 構(gòu)建一個(gè) Request 對(duì)象,該對(duì)象會(huì)根據(jù)請(qǐng)求方法或相關(guān)參數(shù)發(fā)起 HTTP 請(qǐng)求
  • 一旦服務(wù)器返回響應(yīng),就會(huì)產(chǎn)生一個(gè) Response 對(duì)象,該響應(yīng)對(duì)象包含服務(wù)器返回的所有信息,也包含你原來(lái)創(chuàng)建的 Request 對(duì)象

對(duì)于響應(yīng)狀態(tài)碼,我們可以訪(fǎng)問(wèn)響應(yīng)對(duì)象的 status_code 屬性:

import requests

r = requests.get("http://httpbin.org/get")
print r.status_code

# 輸出
200

對(duì)于響應(yīng)正文,我們可以通過(guò)多種方式讀取,比如:

  • 普通響應(yīng),使用 r.text 獲取
  • JSON 響應(yīng),使用 r.json() 獲取
  • 二進(jìn)制響應(yīng),使用 r.content 獲取
  • 原始響應(yīng),使用 r.raw 獲取

普通響應(yīng)

我們可以使用 r.text 來(lái)讀取 unicode 形式的響應(yīng),看看例子:

import requests

r = requests.get("https://github.com/timeline.json")
print r.text
print r.encoding

# 輸出
{"message":"Hello there, wayfaring stranger. If you’re reading this then you probably didn’t see our blog post a couple of years back announcing that this API would go away: http://git.io/17AROg Fear not, you should be able to get what you need from the shiny new Events API instead.","documentation_url":"https://developer.github.com/v3/activity/events/#list-public-events"}
utf-8

Requests 會(huì)自動(dòng)解碼來(lái)自服務(wù)器的內(nèi)容,大多數(shù) unicode 字符集都能被正確解碼。

JSON 響應(yīng)

對(duì)于 JSON 響應(yīng)的內(nèi)容,我們可以使用 json() 方法把返回的數(shù)據(jù)解析成 Python 對(duì)象。

看看例子:

import requests

r = requests.get("https://github.com/timeline.json")

if r.status_code == 200:
    print r.headers.get('content-type')
    print r.json()

# 輸出
application/json; charset=utf-8
{u'documentation_url': u'https://developer.github.com/v3/activity/events/#list-public-events', u'message': u'Hello there, wayfaring stranger. If you\u2019re reading this then you probably didn\u2019t see our blog post a couple of years back announcing that this API would go away: http://git.io/17AROg Fear not, you should be able to get what you need from the shiny new Events API instead.'}

如果 JSON 解碼失敗,r.json() 就會(huì)拋出異常,比如:

import requests

r = requests.get("https://www.baidu.com")

if r.status_code == 200:
    print r.headers.get('content-type')
    print r.json()

# 輸出
text/html
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-9216431f0e2d> in <module>()
      1 if r.status_code == 200:
      2     print r.headers.get('content-type')
----> 3     print r.json()
      4
....
....
ValueError: No JSON object could be decoded

二進(jìn)制響應(yīng)

我們也可以以字節(jié)的方式訪(fǎng)問(wèn)響應(yīng)正文,訪(fǎng)問(wèn) content 屬性可以獲取二進(jìn)制數(shù)據(jù),比如用返回的二進(jìn)制數(shù)據(jù)創(chuàng)建一張圖片:

import requests

url = 'https://github.com/reactjs/redux/blob/master/logo/logo.png?raw=true'
r = requests.get(url)
image_data = r.content   # 獲取二進(jìn)制數(shù)據(jù)

with open('/Users/Ethan/Downloads/redux.png', 'wb') as fout:
    fout.write(image_data)

原始響應(yīng)

在少數(shù)情況下,我們可能想獲取來(lái)自服務(wù)器的原始套接字響應(yīng),這可以通過(guò)訪(fǎng)問(wèn)響應(yīng)對(duì)象的 raw 屬性來(lái)實(shí)現(xiàn),但要確保在初始請(qǐng)求中設(shè)置了 stream=True,比如:

import requests

url = 'https://github.com/reactjs/redux/blob/master/logo/logo.png?raw=true'
r = requests.get(url, stream=True)
print r.raw
r.raw.read(10)

# 輸出
<requests.packages.urllib3.response.HTTPResponse object at 0x1113b0a90>
'\x89PNG\r\n\x1a\n\x00\x00'

重定向

默認(rèn)情況下,除了 HEAD,Requests 會(huì)自動(dòng)處理所有重定向。我們可以使用響應(yīng)對(duì)象的 history 屬性來(lái)追蹤重定向,Response.history 是一個(gè) Response 對(duì)象的列表,這個(gè)對(duì)象列表按照從最老到最近的請(qǐng)求進(jìn)行排序。

比如,點(diǎn)擊某些網(wǎng)站的鏈接,它會(huì)將頁(yè)面重定向到其他網(wǎng)站:

>>> import requests

>>> headers = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}
>>> r = requests.get('https://toutiao.io/k/c32y51', headers=headers)

>>> r.status_code
200

>>> r.url   # 發(fā)生了重定向,響應(yīng)對(duì)象的 url,跟請(qǐng)求對(duì)象不一樣
u'http://www.jianshu.com/p/490441391db6?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io'

>>> r.history
[<Response [302]>]

>>> r.history[0].text
u'<html><body>You are being <a 

可以看到,我們?cè)L問(wèn)網(wǎng)址 https://toutiao.io/k/c32y51 被重定向到了下面的鏈接:

http://www.jianshu.com/p/490441391db6?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io'

我們還看到 r.history 包含了一個(gè) Response 對(duì)象列表,我們可以用它來(lái)追蹤重定向。

如果請(qǐng)求方法是 GET、POST、PUT、OPTIONS、PATCH 或 DELETE,我們可以通過(guò) all_redirects 參數(shù)禁止重定向:

>>> import requests

>>> headers = {'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}
>>> r = requests.get('https://toutiao.io/k/c32y51', headers=headers, allow_redirects=False)
>>> r.url    # 禁止重定向,響應(yīng)對(duì)象的 url 跟請(qǐng)求對(duì)象一致
u'https://toutiao.io/k/c32y51'
>>> r.history
[]
>>> r.text
u'<html><body>You are being <a 

Cookie

  • 如果某個(gè)響應(yīng)包含一些 cookie,我們可以直接訪(fǎng)問(wèn)它們,比如:
>>> import requests

>>> url = 'http://exmaple.com/some/cookie/setting/url'
>>> r = requests.get(url)

>>> r.cookies['some_key']
'some_value'
  • 發(fā)送 cookies 到服務(wù)器,可以使用 cookies 參數(shù):
>>> import requests

>>> url = 'http://httpbin.org/cookies'
>>> cookies = dict(key1='value1')

>>> r = requests.get(url, cookies=cookies)
>>> r.text
u'{\n  "cookies": {\n    "key1": "value1"\n  }\n}\n'
>>> print r.text
{
  "cookies": {
    "key1": "value1"
  }
}

會(huì)話(huà)對(duì)象

我們知道,HTTP 協(xié)議是無(wú)狀態(tài)的,這意味著每個(gè)請(qǐng)求都是獨(dú)立的,如果后續(xù)的處理需要用到前面的信息,則數(shù)據(jù)需要重傳,為了解決這個(gè)問(wèn)題,我們可以使用 Cookie 或 Session 來(lái)存儲(chǔ)某些特定的信息,比如用戶(hù)名、密碼等,這樣,當(dāng)用戶(hù)在不同 Web 頁(yè)面跳轉(zhuǎn)或再次登錄網(wǎng)站時(shí),就不用重新輸入用戶(hù)名和密碼(當(dāng)然,如果 Cookie 被刪除和 Session 過(guò)期則需要重新輸入)。

Requests 提供了會(huì)話(huà)對(duì)象讓我們能夠跨請(qǐng)求保持某些參數(shù),也可以在同一個(gè) Session 實(shí)例發(fā)出的所有請(qǐng)求之間保持 Cookie。

下面,我們看看會(huì)話(huà)對(duì)象的使用。

下面是一個(gè)跨請(qǐng)求保持 Cookie 的例子:

>>> import requests
>>> s = requests.Session()
>>> s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
<Response [200]>
>>> r = s.get("http://httpbin.org/cookies")
>>> print r.text
{
  "cookies": {
    "sessioncookie": "123456789"
  }
}

會(huì)話(huà)還可用來(lái)為請(qǐng)求方法提供缺省數(shù)據(jù),通過(guò)設(shè)置會(huì)話(huà)對(duì)象的屬性來(lái)實(shí)現(xiàn):

import requests

s = requests.Session()
s.auth = ('user', 'pass')
s.headers.update({'x-test': 'true'})

# x-test 和 x-test2 都會(huì)被發(fā)送
s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})

代理

Requests 支持基本的 HTTP 代理 和 SOCKS 代理(2.10.0 新增功能)。

HTTP 代理

如果需要使用 HTTP 代理,我們可以為任意請(qǐng)求方法提供 proxies 參數(shù),如下:

import requests

proxies = {
  "http": "http://10.10.1.10:3128",
  "https": "http://10.10.1.10:1080",
}

requests.get("http://example.org", proxies=proxies)

我們也可以通過(guò)設(shè)置環(huán)境變量 HTTP_PROXYHTTPS_PROXY 來(lái)配置代理:

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

SOCKS 代理

Requests 自 2.10.0 版起,開(kāi)始支持 SOCKS 協(xié)議的代理,如果要使用,我們還需安裝一個(gè)第三方庫(kù):

$ pip install requests[socks]

SOCKS 代理的使用和 HTTP 代理類(lèi)似:

import requests

proxies = {
  "http": "socks5://user:pass@host:port",
  "https": "socks5://user:pass@host:port",
}

requests.get("http://example.org", proxies=proxies)

身份認(rèn)證

大部分 Web 服務(wù)都需要身份認(rèn)證,并且有多種不同的認(rèn)證類(lèi)型,比如:

  • 基本身份認(rèn)證
  • 摘要式身份認(rèn)證
  • OAuth 認(rèn)證

下面介紹一下基本身份認(rèn)證和 OAuth 認(rèn)證。

基本身份認(rèn)證

基本身份認(rèn)證(HTTP Basic Auth)是最簡(jiǎn)單的一種身份認(rèn)證,一般需要身份認(rèn)證的 Web 服務(wù)也都接受 HTTP Basic Auth,Requests 提供了非常簡(jiǎn)單的形式讓我們使用 HTTP Basic Auth:

>>> from requests.auth import HTTPBasicAuth
>>> requests.get('https://api.github.com/user', auth=HTTPBasicAuth('user', 'pass'))

由于 HTTP Basic Auth 非常常見(jiàn),Requests 提供了一種簡(jiǎn)寫(xiě)的形式:

requests.get('https://api.github.com/user', auth=('user', 'pass'))

OAuth 2 認(rèn)證

OAuth 是一種常見(jiàn)的 Web API 認(rèn)證方式,目前的版本是 2.0。Requests 并不直接支持 OAuth 認(rèn)證,而是要配合另外一個(gè)庫(kù)一起使用,該庫(kù)是 requests-oauthlib

下面以 GitHub 為例,介紹一下 OAuth 2 認(rèn)證。

>>> # Credentials you get from registering a new application
>>> client_id = '<the id you get from github>'
>>> client_secret = '<the secret you get from github>'

>>> # OAuth endpoints given in the GitHub API documentation
>>> authorization_base_url = 'https://github.com/login/oauth/authorize'
>>> token_url = 'https://github.com/login/oauth/access_token'

>>> from requests_oauthlib import OAuth2Session
>>> github = OAuth2Session(client_id)

>>> # Redirect user to GitHub for authorization
>>> authorization_url, state = github.authorization_url(authorization_base_url)
>>> print 'Please go here and authorize,', authorization_url

>>> # Get the authorization verifier code from the callback url
>>> redirect_response = raw_input('Paste the full redirect URL here:')

>>> # Fetch the access token
>>> github.fetch_token(token_url, client_secret=client_secret,
>>>         authorization_response=redirect_response)

>>> # Fetch a protected resource, i.e. user profile
>>> r = github.get('https://api.github.com/user')
>>> print r.content

更多關(guān)于 OAuth 工作流程的信息,可以參考 OAuth 官方網(wǎng)站,關(guān)于 requests-oauthlib 庫(kù)的使用,可以參考官方文檔。

小結(jié)

  • 任何時(shí)候調(diào)用 requests.*() 你都在做兩件主要的事情。其一,你在構(gòu)建一個(gè) Request 對(duì)象, 該對(duì)象將被發(fā)送到某個(gè)服務(wù)器請(qǐng)求或查詢(xún)一些資源。其二,一旦 requests 得到一個(gè)從 服務(wù)器返回的響應(yīng)就會(huì)產(chǎn)生一個(gè) Response 對(duì)象。該響應(yīng)對(duì)象包含服務(wù)器返回的所有信息,也包含你原來(lái)創(chuàng)建的 Request 對(duì)象。

參考資料

上一篇:os 模塊下一篇:繼承和多態(tài)