httplib2,一個第三方的開源庫,它比http.client更完整的實現了http協議,同時比urllib.request提供了更好的抽象。 api
#coding=utf8 import httplib2 #獲取HTTP對象 h =httplib2.Http() #發出同步請求,並獲取內容 resp, content = h.request("http://www.weirdbird.net/") print resp print content
一旦你有了Http對象, 獲取數據很是簡單,以你要的數據的地址做爲參數調用request()方法就能夠了。這會對該url執行一個http GET請求 緩存
request() 方法返回兩個值。第一個是一個httplib2.Response對象,其中包含了服務器返回的全部http頭。好比, status爲200 表示請求成功。 服務器
content 變量包含了http服務器返回的實際數據。數據以bytes對象返回,不是字符串。 若是你須要一個字符串,你須要肯定字符編碼並本身進行轉換 網絡
#coding=utf8 import httplib2 #獲取HTTP對象 h =httplib2.Http('.cache') #發出同步請求,並獲取內容 resp, content = h.request("http://www.weirdbird.net/sitemap.xml") print resp # print content print("......"*3) httplib2.debuglevel = 1 h1 = httplib2.Http('.cache') resp,content = h1.request('http://www.weirdbird.net/sitemap.xml') print(resp) print('debug',resp.fromcache)
此時debug 是true ,說明 是從 本地的.cache 進行讀取,沒通過原網站,若我不讀緩存怎麼辦? head 上加: app
resp,content = h1.request('http://www.weirdbird.net/sitemap.xml',headers={'cache-control':'no-cache' })
httplib2 容許你添加任意的http頭部到發出的請求裏。爲了跳過全部緩存(不單單是你本地的磁盤緩存,也包括任何處於你和遠程服務器之間的緩存代理服務器), 在headers字典裏面加入no-cache頭就能夠了。 ide
故名思議, 這個是當服務器的資源改變了,若本地的緩存還有,進行更新的 網站
http 爲這種目的定義了Last-Modified和Etag頭。 這些頭被稱爲驗證器(validators)。若是本地緩存已經不是新鮮的,客戶端能夠在下一個請求的時候發送驗證器來檢查數據實際上有沒有改變。若是數據沒有改變,服務器返回304狀態碼,但不返回數據。 因此雖然還會在網絡上有一個來回,可是你最終能夠少下載一點字節。 google
這可能會讓人有些困惑。這裏實際上有兩個 狀態碼 — 304 (服務器此次返回的, 致使httplib2查看它的緩存), 和 200 (服務器上次返回的, 並和頁面數據一塊兒保存在httplib2的緩存裏)。response.status返回緩存裏的那個 編碼
每一次httplib2 發送請求,它包含了Accept-Encoding頭來告訴服務器它可以處理deflate 或者 gzip壓縮。 url
當request()方法返回的時候,httplib2就已經解壓縮了響應的體(body)並將其放在 content變量裏。若是你想知道響應是否壓縮過, 你能夠檢查response['-content-encoding']; 不然,不用擔憂了.
302臨時重定向
調用request()方法返回的response是最終url的響應 ttplib2 會將最終的 url以 content-location加入到 response字典中。這不是服務器返回的頭,而是httplib2 特色的特徵
response.previous屬性持有前一個響應對象的引用,httplib2跟隨那個響應得到了當前的響應對象。
response 和 response.previous 都是 httplib2.Response 對象。
這意味着你能夠經過response.previous.previous 來反向跟蹤重定向鏈到更前的請求。(場景: 一個url 重定向到第二個url,它又重定向到第三個url。這可能發生!) 在這例子裏,咱們已經到達了重定向鏈的開頭,全部這個屬性是None.
咱們再次請求同一個url 發現變回了第一次 那樣的返回
301 永久重定向
一旦 httplib2跟隨了一個永久重定向, 全部後續的對這個url的請求會被透明的重寫到目標url 而不會接觸網絡來訪問原始的url。 記住, 調試還開着, 但沒有任何網絡活動的輸出。
POST 請求同GET 請求不一樣,由於是要提交到服務器的, 這個api方法必須的參數是status, 而且它應該是url編碼過的。 這是一種很簡單的序列化格式,將一組鍵值對(好比字典)轉化爲一個字符串。
POST 構造數據發送
from urllib.parse import urlencode import httplib2 httplib2.debuglevel = 1 h = httplib2.Http('.cache') data = {'status': 'Test update from Python 3'} h.add_credentials('diveintomark', 'MY_SECRET_PASSWORD', 'identi.ca') resp, content = h.request('https://identi.ca/api/statuses/update.xml', 'POST', urlencode(data), headers={'Content-Type': 'application/x-www-form-urlencoded'})
add_credentials()方法的第三個參數是該證書有效的域名。你應該老是指定這個參數! 若是你省略了這個參數,而且以後重用這個httplib2.Http對象訪問另外一個須要認證的站點,可能會致使httplib2將一個站點的用戶名密碼泄漏給其餘站點。
記住, httplib2返回的數據老是字節串(bytes), 不是字符串。爲了將其轉化爲字符串,你須要用合適的字符編碼進行解碼 好比:
print(content.decode('utf-8'))
from xml.etree import ElementTree as etree tree = etree.fromstring(content) status_id = tree.findtext('id') url = 'https://identi.ca/api/statuses/destroy/{0}.xml'.format(status_id) resp, deleted_content = h.request(url, 'DELETE')