爬蟲入門系列(二):優雅的HTTP庫requests

在系列文章的第一篇中介紹了 HTTP 協議,Python 提供了很多模塊來基於 HTTP 協議的網路編程,urllib、urllib2、urllib3、httplib、httplib2,都是和 HTTP 相關的模塊,看名字覺得很反人類,更糟糕的是這些模塊在 Python2 與 Python3 中有很大的差異,如果業務代碼要同時兼容 2 和 3,寫起來會讓人崩潰。

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

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

快速入門

requests 的安裝可以直接使用 pip 方法:pip install requests

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

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

# 狀態碼n>>> response.status_coden200nn# 原因短語n>>> response.reasonnOKnn# 響應首部n>>> for name,value in response.headers.items():n... print("%s:%s" % (name, value))n...nContent-Encoding:gzipnServer:nginx/1.10.2nDate:Thu, 06 Apr 2017 16:28:01 GMTnn# 響應內容n>>> response.contentnn<html><body>此處省略一萬字...</body></html>n

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

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

構建請求查詢參數

很多URL都帶有很長一串參數,我們稱這些參數為URL的查詢參數,用"?"附加在URL鏈接後面,多個參數之間用"&"隔開,比如:http://fav.foofish.net/?p=4&s=20 ,現在你可以用字典來構建查詢參數:

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

構建請求首部 Headers

requests 可以很簡單地指定請求首部欄位 Headers,比如有時要指定 User-Agent 偽裝成瀏覽器發送請求,以此來矇騙伺服器。直接傳遞一個字典對象給參數 headers 即可。

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

構建 POST 請求數據

requests 可以非常靈活地構建 POST 請求需要的數據,如果伺服器要求發送的數據是表單數據,則可以指定關鍵字參數 data,如果要求傳遞 json 格式字元串參數,則可以使用json關鍵字參數,參數的值都可以字典的形式傳過去。

作為表單數據傳輸給伺服器

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

作為 json 格式的字元串格式傳輸給伺服器

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

Response中的響應體

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

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

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

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

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

如果使用第三方開放平台或者API介面爬取數據時,返回的內容是json格式的數據時,那麼可以直接使用json()方法返回一個經過json.loads()處理後的對象。

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

代理設置

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

import requestsnnproxies = {n http: http://10.10.1.10:3128,n https: http://10.10.1.10:1080,n}nnrequests.get(http://example.org, proxies=proxies)n

超時設置

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

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

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

>>> r = requests.get("http://www.google.coma", timeout=5)n5秒後報錯nTraceback (most recent call last):nsocket.timeout: timed outn

Session

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

有些網頁是需要登錄才能進行爬蟲操作的,而登錄的原理就是瀏覽器首次通過用戶名密碼登錄之後,伺服器給客戶端發送一個隨機的Cookie,下次瀏覽器請求其它頁面時,就把剛才的 cookie 隨著請求一起發送給伺服器,這樣伺服器就知道該用戶已經是登錄用戶。

import requestsn# 構建會話nsession = requests.Session()n# 登錄urlnsession.post(login_url, data={username, password})n# 登錄後才能訪問的urlnr = session.get(home_url)nsession.close()n

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

項目實戰

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

延伸閱讀:

  • Python實現知乎自動登錄:https://foofish.net/python-auto-login-zhihu.html
  • requests文檔:http://docs.python-requests.org/en/master/
  • 如何閱讀 requests 源碼: https://www.slideshare.net/onceuponatimeforever/lets-read-code-pythonrequests-library?qid=9f3099df-4c9e-419a-ae62-b601f55b39f3&v=&b=&from_search=3

推薦閱讀:

10min手寫(b四):b寫配置文件生成增刪改查系統
跟黃哥學習python第三章
python爬蟲實習?
Pyinstaller打包後運行,程序一閃而過,怎麼解決?

TAG:Python | 爬虫 | requests |