1. 程式人生 > >【Python3 爬蟲學習筆記】基本庫的使用 7 —— 使用requests

【Python3 爬蟲學習筆記】基本庫的使用 7 —— 使用requests

抓取二進位制資料

前面我們抓取知乎的一個頁面,實際上它返回的是一個HTML文件。如何抓取圖片、音訊、視訊?

圖片、音訊、視訊這些檔案本質上都是由二進位制碼組成的,由於有特定的儲存格式和對應的解析方式,我們才可以看到這些形形色色的多媒體,所以要抓取它們,就要拿到它們的二進位制碼。
抓取GItHub的站點圖示:

import requests

r = requests.get("https://github.com/favicon.ico")
print(r.text)
print(r.content)

這裡列印了Response物件的兩個屬性,一個是text,另一個是content。
如果按照以上的程式碼,text屬性會出現亂碼,content前面會出現一個b,這代表bytes型別的資料。由於圖片時二進位制資料,所以前者在列印時轉化為str型別,也就是圖片直接轉化為字串,所以會出現亂碼。

將提取的圖片儲存下來:

import requests

r = requests.get("https://github.com/favicon.ico")
with open('favicon.ico', 'wb') as f:
    f.write(r.content)

這裡用了open()方法,它的第一個引數是檔名稱,第二個引數代表以二進位制寫的形式開啟,可以向檔案裡寫入二進位制資料。
執行結束之後,可以發現在資料夾中出現了名為favicon.ico的圖示。
這裡寫圖片描述

1.3 POST請求

import requests

data = {'name':'germey', 'age'
:'22'} r = requests.post("http://httpbin.org/post", data=data) print(r.text)

執行結果:

{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "age": "22",
    "name": "germey"
  },
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Connection": "close",
    "Content-Length"
: "18", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.18.4" }, "json": null, "origin": "221.216.169.171", "url": "http://httpbin.org/post" }

1.4 響應

傳送請求後,得到的自然就是響應。在上面的例項中,我們使用text和content獲取了響應的內容。刺蝟,還有很多屬性和方法可以用來獲取其他資訊,比如狀態碼、響應頭、Cookies等。示例如下:

import requests

r = requests.get('http://www.jianshu.com')
print(type(r.status_code), r.status_code)
print(type(r.headers), r.headers)
print(type(r.cookies), r.cookies)
print(type(r.url), r.url)
print(type(r.history), r.history)

這裡分別列印輸出status_code屬性得到狀態碼,輸出headers屬性得到響應頭,輸出cookies屬性得到Cookies,輸出url屬性得到URL,輸出history屬性得到請求歷史。
執行結果如下:
這裡寫圖片描述

狀態碼常用來判斷請求是否成功,而requests還提供了一個內建的狀態碼查詢物件requests.codes。

2.2 高階用法

2.2.1 檔案上傳

requests可以模擬提交一些資料。同樣也可以使用requests上傳檔案,示例如下:

import requests

files = {'file':open('favicon.ico', 'rb')}
r = requests.post("http://httpbin.org/post", files=files)
print(r.text)

2.2.2 Cookies

import requests

r = requests.get("https://www.baidu.com")
print(r.cookies)
for key, value in r.cookies.items():
    print(key + '=' + value)

執行結果:
這裡寫圖片描述
這裡首先呼叫cookies屬性即可成功得到Cookies,可以發現它是RequestCookiesJar型別。然後用items()方法將其轉化Wie元組組成的列表,便利輸出每一個Cookie的名稱和值,實現Cookie的遍歷解析。

2.2.3 會話維持

在requests中,如果直接利用get()或post()等方法的確可以做到模擬網頁的請求,但是這實際上是相當遠不同的會話,也就是說相當於你用了兩個瀏覽器打開了不同的頁面。
維持同一個會話,要開啟一個新的瀏覽器選項卡而不是新開一個瀏覽器。使用Session物件。
利用Session,可以做到模擬同一個會話而不用擔心Cookies的問題,它通常用於模擬登陸成功之後再進行下一步的操作。
一個示例

import requests

s = requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456789')
r = s.get('http://httpbin.org/cookies')
print(r.text)

執行結果:

{
  "cookies": {
    "number": "123456789"
  }
}

2.2.4 SSL證書驗證

requests提供了證書驗證的功能。當傳送HTTP請求的時候,它會檢查SSL證書,我們可以使用verify引數控制是否檢查此證書。如果不加verify引數的話,預設是True,會自動驗證。

import requests

response = requests.get('https://www.12306.cn', verify=False)
print(response.status_code)

2.2.5 代理設定

對於某些網站,在測試的時候請求幾次,能正常獲取內容。但是一旦開始大規模爬取,對於大規模且頻繁的請求,網站可能會彈出驗證碼,或者跳轉到登入認證頁面,更甚者可能會直接封禁客戶端的IP,導致一定時間段內無法訪問。
為了防止這種情況發生,需要設定代理來解決這個問題,這就需要用到proxies引數。
可以用這樣的方式設定:

import requests

proxies = {
    "http":"http://10.10.1.10:2128",
    "https":"http://10.10.1.10:1080",
}
requests.get("https://www.taobao.com", proxies=proxies)

這個代理可能無效,需要換成有效代理。

若代理需要使用HTTP Basic Auth,可以使用類似http://user:[email protected]:port 這樣的語法來設定代理,示例如下:

import requests

proxies = {
    "http":"http://user:[email protected]:3128/",
}
requests.get("https://www.taobao.com", proxies=porxies)

除了基本的HTTP代理外,requests還支援SOCKS協議的代理。
首先需要安裝socks這個庫:
pip3 install ‘requests[socks]’
然後就可以使用SOCKS協議代理了,示例如下:

import requests

proxies = {
    'http':'socks5://user:[email protected]:port',
    'https':'socks5://user:[email protected]:port'
}
requests.get("https://www.taobao.com", proxies=proxies)

2.2.6 超時設定

在本機網路狀況不好或者伺服器網路響應太慢甚至無響應時,可能會等待特別久的時間才可能收到響應,甚至到最後收不到響應而報錯。為了防止伺服器不能及時響應,應該設定一個超時時間,即超過了這個時間還沒有得到響應,那就報錯。這需要用到timeout引數。這個時間的計算是發出請求到伺服器返回響應的時間。示例如下:

import requests

r = requests.get("https://www.taobao.com", timeout = 1)
print(r.status_code)

通過這樣的方式,可以將超時時間設定為1秒,如果1秒內沒有響應,就會丟擲異常。
實際上,請求分為兩個階段,即連線(connect)和讀取(read)。上面設定的timeout將用作連線和讀取這二者的timeout總和。
如果要分別指定,就可以傳入一個元組:

r = requests.get('https://www.taobao.com', timeout=(5,11,30))

如果想永遠等待,可以直接將timeout設定為None,或者不設定直接留空,因為預設是None。這樣的話,如果伺服器還在執行,但是響應特別慢,就只能慢慢等,它將永遠不會返回超時錯誤的。其用法如下:

r = requests.get("https://www.taobao.com', timeout=None)

2.2.7 身份認證

在訪問網站時,可能需要認證,此時可以使用requests自帶的身份認證功能,示例如下:

import requests
from requests.auth import HTTPBasicAuth

r = requests.get('http://localhost:5000', auth=HTTPBasicAuth('username', 'password')
print(r.status_code)

如果使用者名稱和密碼正確的話,請求時就會自動認證成功,會返回200狀態碼;如果認證失敗,則返回401狀態碼。
當然,如果引數都傳一個HTTPBasicAuth類,就顯得煩瑣,所以requests提供了一個更簡單的寫法,可以直接傳一個元組,它hi預設使用HTTPBasicAuth這個類來認證。

import requests

r = requests.get('http://localhost:5000', auth=('username', 'password'))
print(r.status_code)

此外,requests還提供了其他認證方式,如OAuth認證,不過此時需要安裝oauth包,安裝命令如下:

pip3 install requests_oauthlib

使用OAuth1認證的方法如下:

import requests
from requests_oauthlib import OAuth1

url = 'https://api.twitter.com/1.1/account/verify_credentials.json'
auth = OAuth1('YOUR_APP_KEY', 'YOUR_APP_SECRET', 'USER_OAUTH_TOKEN', 'USER_OAUTH_TOKEN_SECRET')
requests.get(url, auth=auth)

2.2.8 Prepared Request

使用urllib時,可以將請求表示為資料結構,其中各個引數都可以通過一個Request物件來表示。在requests裡同樣可以做到,這個資料結構就叫Prepared Request。示例如下:

from requests import Request, Session

url = 'http://httpbin.org/post'
data = {
    'name':'germey'
}
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36'}
s = Session()
req = Request('POST', url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)

這裡引入了Request,然後用url、data和headers引數構造了一個Request物件,這時需要再呼叫Session的prepare_request()方法將其轉換為一個Prepared Request物件,然後呼叫send()方法傳送即可,執行結果如下:

{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "name": "germey"
  },
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Connection": "close",
    "Content-Length": "11",
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "httpbin.org",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36"
  },
  "json": null,
  "origin": "221.216.169.171",
  "url": "http://httpbin.org/post"
}

有了Request這個物件,就可以將請求當作獨立的物件來看待,這樣在進行佇列排程時會非常方便。