1. 程式人生 > >Python從零開始寫爬蟲(一)requests庫使用

Python從零開始寫爬蟲(一)requests庫使用

requests是一個強大的網路請求庫,簡單易用-讓 HTTP 服務人類。可以參考這個網站的介紹:http://cn.python-requests.org/zh_CN/latest/index.html

直接使用pip install requests安裝此模組之後,開始吧。

一、網路請求和響應

常用的請求方式有以下幾種:

  • GET請求獲取URL位置的資源
  • HEAD請求獲取URL位置的資源的頭部資訊
  • POST請求想URL位置的資源後附加新的資料
  • PUT覆蓋原URL位置的資源
  • PATCH請求區域性更新URL位置的資源,即改變該處資源的部分內容
  • DELETE請求刪除該URL位置的資源

這些方式在python的requests庫中提供了全面的支援。

1、get

基本的get請求:

# encoding=utf-8
import requests
r = requests.get('https://github.com/timeline.json')

print(r.text)

同理我們可以得到其他方式的請求:

r2 = requests.post("http://httpbin.org/post")
r3 = requests.delete("http://httpbin.org/delete")
r4 = requests.head
("http://httpbin.org/get") r5 = requests.options("http://httpbin.org/get")

任何時候呼叫 requests.*() 你都在做兩件主要的事情。其一,你在構建一個 Request 物件, 該物件將被髮送到某個伺服器請求或查詢一些資源。其二,一旦 requests 得到一個從 伺服器返回的響應就會產生一個 Response 物件。該響應物件包含伺服器返回的所有資訊, 也包含你原來建立的 Request 物件。

帶引數的get請求:

# encoding=utf-8

import requests
payload = {'key1'
: 'value1', 'key2': 'value2'} r = requests.get("http://httpbin.org/get", params=payload) print(r.text)

這裡通過一個字典,向請求的網址中傳參。可以通過print(r.url)確認網址已被正確的編碼為http://httpbin.org/get?key1=value1&key2=value2

requests庫的兩個重要物件:request(請求)、response(響應)。

上面我們用的是request物件的get方法,及帶引數的get方法。獲取了響應內容之後,就可以呼叫response物件的一些方法來獲取響應的相關資訊了。

r                       #response物件
r.status_code           #狀態碼
r.text                  #請求返回的正文
r.url                   #請求的URL
r.content               #二進位制響應內容
r.apparent_encoding     #從響應中分析出來的編碼格式
r.json()                #內建的json解析器,將響應解析成json
# encoding=utf-8
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)

print(r.json())

上面程式碼演示了json解析返回的內容,可以看到返回為:{'args': {'key1': 'value1', 'key2': 'value2'}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', ...(省略)


HTTP狀態碼:

2xx 用來表示請求成功
206 部分內容 (Partial Content),如果一個應用只請求某範圍之內的檔案,那麼就會返回206.

3xx來表示重定向
如,301 表示Moved Permanently,This and all future requests should be directed to the given URI

4xx用來表示客戶端請求出現問題
403 Forbidden,404 Not Found等等

5xx 用來表示伺服器出現問題
如,503 Service Unavailable,服務端過載、維護中等等……

從這裡可以獲取到更詳細的資訊:https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

2、定製請求頭

如果你想為請求新增 HTTP 頭部,只要簡單地傳遞一個 dict 給 headers 引數就可以了。HTTP Headers是HTTP請求和相應的核心,它承載了關於客戶端瀏覽器,請求頁面,伺服器等相關的資訊。可以通過Chrome的開發者工具來檢視header資訊:

Request

response

User-Agent:
攜帶如下幾條資訊:瀏覽器名和版本號、作業系統名和版本號、預設語言;是某些網站用來收集訪客資訊的一般手段。如上圖中的Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.109 Safari/537.36

Accept-Language:
如上面的Accept-Language: zh-CN,zh;q=0.8,說明使用者的預設語言設定。如果網站有不同的語言版本,那麼就可以通過這個資訊來重定向使用者的瀏覽器。它可以通過逗號分割來攜帶多國語言。第一個會是首選的語言,其它語言會攜帶一個“q”值,來表示使用者對該語言的喜好程度(0~1)。

Cookie:
會發送你瀏覽器中儲存的Cookie資訊給伺服器,內容中用分號來分割一組鍵值對。

在requests中使用headers也很簡單,如下構造了一個簡單的headers:

headers = {'user-agent': 'my-app/0.0.1'}
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload, headers=headers)

使用 r.headers來訪問返回的伺服器響應頭:

#返回的是字典形式的headers
print(r.headers)
>>>{'Connection': 'keep-alive', 'Server': 'meinheld/0.6.1', 'Date': 'Fri, 30 Jun 2017 08:13:17 GMT', 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*', ...(省略)

同時我們可以訪問其中的某一項資訊,可以用以下兩種方式:

print(r.headers.get("Date"))  #獲取date資訊
print(r.headers["Server"])    #獲取Server資訊

#輸出如下:
#Fri, 30 Jun 2017 08:15:40 GMT
#meinheld/0.6.1

3、會話物件

會話物件讓你能夠跨請求保持某些引數。它也會在同一個 Session 例項發出的所有請求之間保持 cookie,期間使用 urllib3 的 connection pooling 功能。所以如果你向同一主機發送多個請求,底層的 TCP 連線將會被重用,從而帶來顯著的效能提升。

看下面一個簡單示例:

import requests
#構造會話物件
s = requests.Session()
s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
#注意這裡更換了請求
r = s.get("http://httpbin.org/cookies")

print(r.text)
#打印出的仍然是我們在第一個請求裡面寫入的cookies
#'{"cookies": {"sessioncookie": "123456789"}}'

會話級別的引數和方法級別的引數:
這裡要區分一下上面兩個概念,我們直接通過會話物件的屬性設定的引數叫做會話級別的引數,如可以設定s.headers、s.cookies等等;而通過方法(如get方法中設定headers等)設定的引數叫做方法級別的引數。

  1. 方法層的引數覆蓋會話的引數。
  2. 就算使用了會話,方法級別的引數也不會被跨請求保持。

看看下面這個簡單的例子:

# encoding=utf-8

import requests
s = requests.Session()
r = s.get('http://httpbin.org/cookies', cookies={'from-my': 'browser'})
print(r.text)
r = s.get('http://httpbin.org/cookies')
print(r.text)

輸出為:

{
  "cookies": {
    "from-my": "browser"
  }
}

{
  "cookies": {}
}

可以看見,方法級別的引數沒有被跨請求保持!