python requests庫學習筆記(下)

来源:http://www.cnblogs.com/ailiailan/archive/2017/11/25/7412945.html
-Advertisement-
Play Games

1.請求異常處理 請求異常類型: 請求超時處理(timeout): 實現代碼: import requestsfrom requests import exceptions #引入exceptions A:請求超時 def timeout_request(): try: response = req ...


1.請求異常處理

請求異常類型:

 請求超時處理(timeout):

實現代碼:

import requests
from requests import exceptions        #引入exceptions

A:請求超時

def timeout_request():
    try:
        response = requests.get(build_uri('user/emails'), timeout=0.1)
    except exceptions.Timeout as e:
        print e.message

返回數據:HTTPSConnectionPool(host='api.github.com', port=443): Max retries exceeded with url: /user/emails (Caused by ConnectTimeoutError(<urllib3.connection.VerifiedHTTPSConnection object at 0x02BDEC50>, 'Connection to api.github.com timed out. (connect timeout=0.1)'))

B:未認證時訪問,報HTTPError

代碼:

def timeout_request():
    response = requests.get(build_uri('user/emails'), timeout=10)
    print response.text
    print response.status_code

返回數據:

{"message":"Requires authentication","documentation_url":"https://developer.github.com/v3"}
401

C:拋出HTTPError異常信息

def timeout_request():
    try:
        response = requests.get(build_uri('user/emails'), timeout=10)
        response.raise_for_status()
    except exceptions.HTTPError as e:
        print e.message

返回數據:

401 Client Error: Unauthorized for url: https://api.github.com/user/emails     #401客戶端錯誤,沒有認證的情況下訪問url;

註意:以上的兩個小程式,通過使用try.....except機制,就合理的處理了發送請求時的各種各樣的“攔路虎”,依靠except分支可以幫助我們來處理異常,特別是在調用第三方服務的時候。

2.自定義Requests

requests庫進階部分官方功能變數名稱:http://www.python-requests.org/en/master/user/advanced/

翻譯上圖中紅色框中的內容:

會話對象允許你在發送請求的時候保留某些參數,它也能夠保留會話過程中發送請求的cookie,並且使用urllib3進程池,所以如果你向同一個功能變數名稱發送多個請求時,底層的TCP鏈接會被重用,由此會帶來一個很明顯的性能提高(參見HTTP持久鏈接)。

Session模塊的組成:

代碼實現:

def hard_requests():
   '''構造請求

'''

    from requests import Request, Session     #引入Request  Session
    s = Session()
    headers = {'User-Agent': 'fake1.3.4'}
    req = Request('GET', build_uri('user/emails'), auth=('caolanmiao', 'key########'), headers=headers)
    prepped = req.prepare()                      #使用prepare()方法準備url
    print prepped.body
    print prepped.headers

只有以上的代碼時的返回結果:

None
{'Authorization': 'Basic aW1vb2NkZW1vOmltb29jZGVtbzEyMw==', 'User-Agent': 'fake1.3.4'}

可見,請求還沒有發送出去

'''發送請求

'''
    resp = s.send(prepped, timeout=5)         #發送請求,使用send()方法
    print resp.status_code
    print resp.request.headers
    print resp.text

加上以上代碼後的返回結果:

None
{'Authorization': 'Basic aW1vb2NkZW1vOmltb29jZGVtbzEyMw==', 'User-Agent': 'fake1.3.4'}
200
{'Authorization': 'Basic aW1vb2NkZW1vOmltb29jZGVtbzEyMw==', 'User-Agent': 'fake1.3.4'}
[{"email":"[email protected]","primary":true,"verified":false,"visibility":"private"},{"email":"[email protected]","primary":false,"verified":false,"visibility":null},

可見,此時請求才發送成功。

通過上面的代碼可以看出,使用自定義的方法構造請求,可以隨時控制請求的發送時機。

3.處理響應

響應基本API:

 

代碼舉例:

# -*- coding: utf-8 -*-
import requests

response = requests.get('https://api.github.com')
print "狀態碼,具體解釋"
print response.status_code, response.reason
print "頭部信息"
print response.headers
print "URL 信息"
print response.url
print "redirect 信息"
print response.history
print "耗費時長"
print response.elapsed
print "request 信息"
print response.request.method
print "編碼信息"
print response.encoding
print "消息主體內容: byte"
print response.content, type(response.content)
print "消息主體內容: 解析"
print response.text, type(response.text)
print "消息主體內容"
print response.json(), type(response.json())

有關HTTP狀態碼(status_code)的功能變數名稱,可以關註維基百科:https://zh.wikipedia.org/zh/HTTP%E7%8A%B6%E6%80%81%E7%A0%81

常見的status_codereason:

2xx成功:這一類型的狀態碼,代表請求已成功被伺服器接收、理解、並接受。

200 OK    請求已成功,請求所希望的響應頭或數據體將隨此響應返回

201 Created     請求已經被實現,而且有一個新的資源已經依據請求的需要而建立

202 Accepted    伺服器已接受請求,但尚未處理

204 No Content    伺服器成功處理了請求,沒有返回任何內容

3xx重定向:這類狀態碼代表需要客戶端採取進一步的操作才能完成請求。通常,這些狀態碼用來重定向,後續的請求地址(重定向目標)在本次響應的Location域中指明

301 Moved Permanently   被請求的資源已永久移動到新位置,並且將來任何對此資源的引用都應該使用本響應返回的若幹個URI之一。如果可能,擁有鏈接編輯功能的客戶端應當自動把請求的地址修改為從伺服器反饋回來的地址。除非額外指定,否則這個響應也是可緩存的

302 Found 要求客戶端執行臨時重定向(原始描述短語為“Moved Temporarily”)。由於這樣的重定向是臨時的,客戶端應當繼續向原有地址發送以後的請求。只有在Cache-Control或Expires中進行了指定的情況下,這個響應才是可緩存的

304 Not Modified 表示資源未被修改,因為請求頭指定的版本If-Modified-Since或If-None-Match。在這種情況下,由於客戶端仍然具有以前下載的副本,因此不需要重新傳輸資源

4xx客戶端錯誤:這類的狀態碼代表了客戶端看起來可能發生了錯誤,妨礙了伺服器的處理。除非響應的是一個HEAD請求,否則伺服器就應該返回一個解釋當前錯誤狀況的實體,以及這是臨時的還是永久性的狀況。這些狀態碼適用於任何請求方法。瀏覽器應當向用戶顯示任何包含在此類錯誤響應中的實體內容。

400 Bad Request 由於明顯的客戶端錯誤(例如,格式錯誤的請求語法,太大的大小,無效的請求消息或欺騙性路由請求),伺服器不能或不會處理該請求

401 Unauthorized  類似於403 Forbidden,401語義即“未認證”,即用戶沒有必要的憑據

403 Forbidden  沒有許可權;伺服器已經理解請求,但是拒絕執行它。與401不同的是,身份驗證並不能提供任何幫助,而且這個請求也不應該被重覆提交

404  Not Found  請求失敗,請求所希望得到的資源未被在伺服器上發現,但允許用戶的後續請求

5XX:伺服器錯誤,表示伺服器無法完成明顯有效的請求

500 Internal Server Error  通用錯誤消息,伺服器遇到了一個未曾預料的狀況,導致了它無法完成對請求的處理。沒有給出具體錯誤信息

502 Bad Gateway   作為網關或者代理工作的伺服器嘗試執行請求時,從上游伺服器接收到無效的響應

503 Service Unavailable   由於臨時的伺服器維護或者過載,伺服器當前無法處理請求。這個狀況是暫時的,並且將在一段時間以後恢復

通過dir(response),可以查看response的全部API。

4.下載圖片/文件

舉例:通過下麵代碼實現下載圖片(百度“github”圖片中的第一個),下圖是實現流程圖

# -*- coding: utf -*-
import requests

def download_image():
    """demo: 下載圖片, 文件
    """
    # 偽造headers信息

    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36'}   #獲取許可權,使用Firefox瀏覽器

    # 限定url
    url = "http://img3.imgtn.bdimg.com/it/u=2228635891,3833788938&fm=21&gp=0.jpg"
    response = requests.get(url, headers=headers, stream=True)       #stream=True  流傳輸
    # 打開文件

     with open('demo.jpg', 'wb') as fd:

     # 每128寫入一次
        for chunk in response.iter_content(128):
            fd.write(chunk)

def download_image_improved():
    """demo: 下載圖片
    """
    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36'}
    url = "http://img3.imgtn.bdimg.com/it/u=2228635891,3833788938&fm=21&gp=0.jpg"
    response = requests.get(url, headers=headers, stream=True)
    from contextlib import closing
    with closing(requests.get(url, headers=headers, stream=True)) as response:      #把打開的流stream關閉,以節省資源
       with open('demo1.jpg', 'wb') as fd:
            for chunk in response.iter_content(128):
                fd.write(chunk)

download_image_improved()

 如下圖,demo.jpg文件已經成功下載到本地了

5.事件鉤子

事件鉤子(event hooks)模型

 

# -*- coding: utf-8 -*-
import requests

def get_key_info(response, *args, **kwargs):
    """回調函數
    """
    print response.headers['Content-Type']

def main():
    """主程式
    """
    requests.get('https://api.github.com', hooks=dict(response=get_key_info))


main()

返回數據:

application/json; charset=utf-8
利用事件鉤子的方法可以使得request和response分開,特別是當代碼很多的時候,方便管理。

6.Request庫--HTTP認證

前面所講的發送一個請求,得到響應,其實有一個簡單的假設,就是通過HTTP通訊,我們訪問的所有資源都是可見的,實際上很多時候,為了提高安全性,服務端要驗證請求的來源,只有通過驗證的請求,服務端才會響應。最簡單基本認證的模式,如下圖:

對於受保護的服務,在發送請求的時候就要加上一個requests庫里的認證參數:auth

實驗代碼:

# -*- coding: utf-8 -*-
import requests

BASE_URL='https://api.github.com'

def construct_url(end_point):
    return '/'.join([BASE_URL,end_point])

def basic_auth():
    """基本認證
    """
    response=requests.get(construct_url('user'),auth=('caolanmiao','key######'))      #添加auth參數,完成認證
    print response.text
    print response.request.headers
    
basic_auth()

返回數據:

{"login":"caolanmiao","id":22490616,"avatar_url":"https://avatars0.githubusercontent.com/u/22490616?v=4","gravatar_id":"","url":"https://api.github.com/users/caolanmiao","html_url":"https://github.com/caolanmiao","followers_url":"https://api.github.com/users/caolanmiao/followers","following_url":"https://api.github.com/users/caolanmiao/following{/other_user}","gists_url":"https://api.github.com/users/caolanmiao/gists{/gist_id}","starred_url":"https://api.github.com/users/caolanmiao/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/caolanmiao/subscriptions","organizations_url":"https://api.github.com/users/caolanmiao/orgs","repos_url":"https://api.github.com/users/caolanmiao/repos","events_url":"https://api.github.com/users/caolanmiao/events{/privacy}","received_events_url":"https://api.github.com/users/caolanmiao/received_events","type":"User","site_admin":false,"name":"Yannan.Jia","company":null,"blog":"","location":"Pecking","email":"[email protected]","hireable":null,"bio":"Software QA Engineer","public_repos":1,"public_gists":0,"followers":0,"following":1,"created_at":"2016-09-28T06:00:27Z","updated_at":"2017-08-19T09:27:39Z","private_gists":0,

"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 Y2FvbGFubWlhbzpqaWEyMjE1NDkw', 'Connection': 'keep-alive', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.18.3'}

返回的數據中,可以看到,添加auth參數後,在request的headers中加了一串Authorization,Basic後面的這一串碼“Y2FvbGFubWlhbzpqaWEyMjE1NDkw”是什麼呢?

其實這一串碼是base64格式的,解碼後就是我的用戶名和密碼('caolanmiao','key######')。

所以這種基本形式的認證是把用戶名和密碼放在request的headers中,使用任何語言(比如python)都可以對已經編碼後的用戶名和密碼進行解碼,可見,具備一定的安全性,但是安全性並不夠強。

另一種安全性更強的認證---OAUTH認證

比如一個app在登錄的時候,提供了通過github賬號來快速登錄的入口,那麼完成登錄的流程就如下圖所示:

實驗代碼:

# -*- coding:utf-8 -*-
import requests

BASE_URL='https://api.github.com'

def construct_url(end_point):
    return '/'.join([BASE_URL,end_point])

def basic_oauth():
    headers={'Authorization':'token dd6322fa6c57a548268453dc245cbcdc352a7811'}     #通過token完成認證
    # user/emails
    response=requests.get(construct_url('user/emails'),headers=headers)    
    print response.request.headers
    print response.text
    print response.status_code

7.Request庫--Proxy(代理)

Heroku這個伺服器(相當於國內的“阿裡雲”)對於國外的資源是可見的,比如是可以直接訪問facebook的;Socks服務是一種在會話層的協議,類似於HTTP協議;

實現代碼:

import requests

proxies={'http':'socks5://127.0.0.1080','https':'socks5://127.0.0.1080'}     #定義代理

url='https://www.facebook.com'

response=requests.get(url,proxies=proxies,timeout=10)      #添加代理

8.Request庫--Session和Cookie

大家都知道http協議的請求和下一個請求之間是獨立的、沒有關係的。但是經常有些時候我們需要使得請求和上一個請求有關係,比如“在購物的情景中,已經登錄了賬戶,把商品加入購物車中,不能出現發出一個新請求後,購物車中的商品清空了的情況”。

簡而言之,session是存儲在伺服器端的,來保存登錄信息;cookie是保存在瀏覽器中來存儲的。

cookie存儲的方式如圖1:

cookie存儲的方式缺點:1.每次發送請求都帶著cookie,造成了帶寬特別大,特別占用網路請求;2.cookie如果在瀏覽器端是明文存儲的話,容易解析時,是可以偽造的,很不安全。

那麼鑒於cookie存儲方式的不足,session存儲的方式應運而生。

session存儲的方式如圖2:

 

session存儲的方式優點:1. 伺服器返回的cookie-session-id相比於整個cookie是很小的,節省帶寬,減少了網路傳輸的壓力;2.伺服器把session存儲在資料庫或者radis(記憶體)中,實現了本地化,相比於cookie存儲方式的每次在網路中發送整個cookie更安全。

看到的同學也可以利用github上的api自己試試。

尊重博客園原創精神,請勿轉載!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本人學習.Net開發已有很長一段時間了,但平時疏於對知識系統化的歸納和總結,多次面試中屢屢碰壁。所以痛定思痛,決心把一些知識整理到博客中,以便自己瀏覽學習。園子中有很多好文和技術大牛分享的經驗。我會抄錄一些內容到我的博客,並標明出處。先謝過各位了。 ...
  • 通過ADO.NET技術,我們可以高效的完成客戶端同資料庫之間的數據訪問操作,便於我們在客戶端程式簡便高效的訪問以及獲取資料庫中的有用數據,同時也可以對資料庫中的數據進行更新,即可以完成客戶端與資料庫之間的雙向操作。本文簡單介紹如何在客戶端程式中利用ADO.NET技術來訪問以及使用資料庫中的數據。 A ...
  • 返回總目錄 本小節目錄 Introduce Foreign Method(引入外加函數) Introduce Local Extension(引入本地擴展) Introduce Foreign Method(引入外加函數) Introduce Local Extension(引入本地擴展) 7Int ...
  • 學習java之後,到企業的崗位 技術:java軟體開發工程師(中初級):技術一般; 高級工程師:技術高等; 技術架構師;技術頂級; 管理:項目經理;產品經理; 質詢:質詢顧問;銷售經理; 學會之後可以根據個人的愛好去從事相關的職位,但是不管是做哪一個都是需要技術的底子。希望能幫到你們。在這裡我也提醒 ...
  • 兩種用法介紹如下:1.range([start], stop[, step])返回等差數列。構建等差數列,起點是start,終點是stop,但不包含stop,公差是step。start和step是可選項,沒給出start時,從0開始;沒給出step時,預設公差為1。例如: 2.xrange([sta ...
  • 設計模式是對問題行之有效的解決方案,它其實是一種思想。 單例設計模式: 解決的問題:可以保證一個類在記憶體中只能有一個對象。(比如多個程式使用相同的配置信息對象時,就需要保證對象的唯一性) 如何保證唯一性:1、不允許其他程式用new創建類對象 2、在該類中創建一個本類實例 3、對外提供一個方法讓其他程 ...
  • ecto 簡介 ecto 相當於 elixir 的 ORM,但是得益於 elixir 語言,和傳統的 ORM 相比,更加簡潔和強大。 ecto 主要分為 4 部分: 1. Repo: 這是和真正資料庫交互的部分 2. Schema: 相當於是資料庫中表的定義,但不僅僅是定義 3. Changeset ...
  • 題目如下: 這題我剛開始被示例給迷惑了,是將key和value分開輸入的,類似於cin>>key>>value,這裡應該是要講每行字元串連接成一個新的字元串,然後遍歷整個字元串,遇到:表示key錄入完畢,遇到,和},要先判斷,的情況,確定,前面沒有},這是才表示value錄入完畢。再就是首碼的問題, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...