在系列文章的第一篇中介紹了 HTTP 協議,Python 提供了不少模塊來基於 HTTP 協議的網絡編程,urllib、urllib二、urllib三、httplib、httplib2,都是和 HTTP 相關的模塊,看名字以爲很反人類,更糟糕的是這些模塊在 Python2 與 Python3 中有很大的差別,若是業務代碼要同時兼容 2 和 3,寫起來會讓人崩潰。javascript

幸運地是,繁榮的 Python 社區給開發者帶來了一個很是驚豔的 HTTP 庫 requests,一個真正給人用的HTTP庫。它是 GitHUb 關注數最多的 Python 項目之一,requests 的做者是 Kenneth Reitz 大神。html

requests 實現了 HTTP 協議中絕大部分功能,它提供的功能包括 Keep-Alive、鏈接池、Cookie持久化、內容自動解壓、HTTP代理、SSL認證、鏈接超時、Session等不少特性,最重要的是它同時兼容 python2 和 python3。java

快速入門

requests 的安裝能夠直接使用 pip 方法:pip install requestspython

>>> import requests # GET 請求 >>> response = requests.get("https://foofish.net")

返回的時 Response 對象,Response 對象是 對 HTTP 協議中服務端返回給瀏覽器的響應數據的封裝,響應的中的主要元素包括:狀態碼、緣由短語、響應首部、響應體等等,這些屬性都封裝在Response 對象中。nginx

# 狀態碼 >>> response.status_code 200 # 緣由短語 >>> response.reason 'OK' # 響應首部 >>> for name,value in response.headers.items(): ... print("%s:%s" % (name, value)) ... Content-Encoding:gzip Server:nginx/1.10.2 Date:Thu, 06 Apr 2017 16:28:01 GMT # 響應內容 >>> response.content '<html><body>此處省略一萬字...</body></html>

requests 除了支持 GET 請求外,還支持 HTTP 規範中的其它全部方法,包括 POST、PUT、DELTET、HEADT、OPTIONS方法。編程

>>> r = requests.post('http://httpbin.org/post', data = {'key':'value'}) >>> r = requests.put('http://httpbin.org/put', data = {'key':'value'}) >>> r = requests.delete('http://httpbin.org/delete') >>> r = requests.head('http://httpbin.org/get') >>> r = requests.options('http://httpbin.org/get')

構建請求查詢參數

不少URL都帶有很長一串參數,咱們稱這些參數爲URL的查詢參數,用"?"附加在URL連接後面,多個參數之間用"&"隔開,好比:http://fav.foofish.net/?p=4&s=20 ,如今你能夠用字典來構建查詢參數:json

>>> args = {"p": 4, "s": 20} >>> response = requests.get("http://fav.foofish.net", params = args) >>> response.url 'http://fav.foofish.net/?p=4&s=2'

構建請求首部 Headers

requests 能夠很簡單地指定請求首部字段 Headers,好比有時要指定 User-Agent 假裝成瀏覽器發送請求,以此來矇騙服務器。直接傳遞一個字典對象給參數 headers 便可。api

>>> r = requests.get(url, headers={'user-agent': 'Mozilla/5.0'})

構建 POST 請求數據

requests 能夠很是靈活地構建 POST 請求須要的數據,若是服務器要求發送的數據是表單數據,則能夠指定關鍵字參數 data,若是要求傳遞 json 格式字符串參數,則可使用json關鍵字參數,參數的值均可以字典的形式傳過去。瀏覽器

做爲表單數據傳輸給服務器服務器

>>> payload = {'key1': 'value1', 'key2': 'value2'} >>> r = requests.post("http://httpbin.org/post", data=payload)

做爲 json 格式的字符串格式傳輸給服務器

>>> import json >>> url = 'http://httpbin.org/post' >>> payload = {'some': 'data'} >>> r = requests.post(url, json=payload)

Response中的響應體

HTTP返回的響應消息中很重要的一部份內容是響應體,響應體在 requests 中處理很是靈活,與響應體相關的屬性有:content、text、json()。

content 是 byte 類型,適合直接將內容保存到文件系統或者傳輸到網絡中

>>> r = requests.get("https://pic1.zhimg.com/v2-2e92ebadb4a967829dcd7d05908ccab0_b.jpg")
>>> type(r.content)
<class 'bytes'>
# 另存爲 test.jpg
>>> with open("test.jpg", "wb") as f:
...     f.write(r.content)

text 是 str 類型,好比一個普通的 HTML 頁面,須要對文本進一步分析時,使用 text。

>>> r = requests.get("https://foofish.net/understand-http.html")
>>> type(r.text)
<class 'str'>
>>> re.compile('xxx').findall(r.text)

若是使用第三方開放平臺或者API接口爬取數據時,返回的內容是json格式的數據時,那麼能夠直接使用json()方法返回一個通過json.loads()處理後的對象。

>>> r = requests.get('https://www.v2ex.com/api/topics/hot.json') >>> r.json() [{'id': 352833, 'title': '在長沙,父母同住...

代理設置

當爬蟲頻繁地對服務器進行抓取內容時,很容易被服務器屏蔽掉,所以要想繼續順利的進行爬取數據,使用代理是明智的選擇。若是你想爬取牆外的數據,一樣設置代理能夠解決問題,requests 完美支持代理。

import requests proxies = { 'http': 'http://10.10.1.10:3128', 'https': 'http://10.10.1.10:1080', } requests.get('http://example.org', proxies=proxies)

超時設置

requests 發送請求時,默認請求下線程一直阻塞,直到有響應返回才處理後面的邏輯。若是遇到服務器沒有響應的狀況時,問題就變得很嚴重了,它將致使整個應用程序一直處於阻塞狀態而無法處理其餘請求。

>>> import requests >>> r = requests.get("http://www.google.coma") ...一直阻塞中

正確的方式的是給每一個請求顯示地指定一個超時時間。

>>> r = requests.get("http://www.google.coma", timeout=5) 5秒後報錯 Traceback (most recent call last): socket.timeout: timed out

Session

爬蟲入門系列(一):快速理解HTTP協議中介紹過HTTP協議是一中無狀態的協議,爲了維持客戶端與服務器之間的通訊狀態,使用 Cookie 技術使之保持雙方的通訊狀態。

有些網頁是須要登陸才能進行爬蟲操做的,而登陸的原理就是瀏覽器首次經過用戶名密碼登陸以後,服務器給客戶端發送一個隨機的Cookie,下次瀏覽器請求其它頁面時,就把剛纔的 cookie 隨着請求一塊兒發送給服務器,這樣服務器就知道該用戶已是登陸用戶。

import requests # 構建會話 session = requests.Session() # 登陸url session.post(login_url, data={username, password}) # 登陸後才能訪問的url r = session.get(home_url) session.close()

構建一個session會話以後,客戶端第一次發起請求登陸帳戶,服務器自動把cookie信息保存在session對象中,發起第二次請求時requests 自動把session中的cookie信息發送給服務器,使之保持通訊狀態。

項目實戰

最後是一個實戰項目,如何用 requests 實現知乎自動登陸並給用戶發私信,我會在下一篇文章中進行講解,關注公衆號 ‘Python之禪’。

延伸閱讀:

同步發表博客:https://foofish.net/http-requests.html公衆號:Python之禪 (id:VTtalk),分享 Python 等技術乾貨