python網絡爬蟲教程(四):強大便捷的請求庫requests詳解與編程實戰

上一章中,我們瞭解了urllib的基本用法,詳情可瀏覽如下鏈接python網絡爬蟲教程(三):詳解urllib庫,但其中確實有不方便的地方,爲此,我們可以使用更方便更簡潔的HTTP請求庫requests來幫我們完成爬蟲任務。

如果你沒有安裝requests,無論是Windows、Linux還是Mac,都可以在命令行界面中運行如下命令,即可完成requests庫的安裝:

pip install requests

如果你沒有安裝pip,可參考以下文章:寫給初學者的Python與pip安裝教程

基本用法

1. GET請求

1. 基本實例
HTTP中最常見的就是GET請求,在requests中可以用如下方法實現:

import requests

response = requests.get('http://httpbin.org/get')
print(type(response))
print(response.text)

結果如下:

<class 'requests.models.Response'>
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.23.0",
    "X-Amzn-Trace-Id": "Root=1-5eccc552-e9bfd8204c6d591075a2b890"
  },
  "origin": "171.107.139.104",
  "url": "http://httpbin.org/get"
}

可以發現,get()方法返回值是requests.model.Response類型對象,並且這樣的請求方法與urllib中的urlopen()方法如出一轍。

如果要添加參數,除了在URL中構造外,還可以使用get()方法的params參數:

import requests

data = {
    'name': 'germey',
    'age': 22
}

response = requests.get('http://httpbin.org/get', params=data)
print(response.text)

運行結果如下:

{
  "args": {
    "age": "22",
    "name": "germey"
  },
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.23.0",
    "X-Amzn-Trace-Id": "Root=1-5eccc6f8-ee3d14ec71ec38bec92961aa"
  },
  "origin": "171.107.139.104",
  "url": "http://httpbin.org/get?name=germey&age=22"
}

我們構造一個字典類型的參數data,利用params參數將data構造爲URL的參數,這種方法更加簡便,且可讀性更強。
另外,網頁的返回結果是str類型,但是它很特殊,是JSON格式的,如果我們要解析返回結果,得到一個字典的話,可以用jsos()方法:

import requests

response = requests.get('http://httpbin.org/get')
print(type(response.text))
print(response.json())
print(type(response.json()))

運行結果如下:

<class 'str'>
{'args': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'User-Agent': 'python-requests/2.23.0', 'X-Amzn-Trace-Id': 'Root=1-5eccc86b-7372a90f1143321aa6393206'}, 'origin': '171.107.139.104', 'url': 'http://httpbin.org/get'}
<class 'dict'>

可以發現,調用json()後,返回結果轉化爲了字典。但是如果返回結果不是JSON格式,便會出現解析錯誤。

2. 抓取二進制數據
如果我們要獲取網頁內容,可以在返回結果的Request中用text屬性,實際上它的內容是一個HTML文檔,如果想抓取圖片、音頻、視頻等內容,可以使用Response的content屬性,它的內容是這些文件的二進制碼。

下面我們來試着爬取本頁面菜單欄上的CSDN圖標,如下所示

在這裏插入圖片描述

import requests

response = requests.get('https://csdnimg.cn/cdn/content-toolbar/csdn-logo.png?v=20200416.1')
print(type(response.text))
print(type(response.content))

運行結果如下:

<class 'str'>
<class 'bytes'>

其中content屬性的內容是bytes類型,試着將它保存到文件中:

import requests

response = requests.get('https://csdnimg.cn/cdn/content-toolbar/csdn-logo.png?v=20200416.1')
with open('text.ico', 'wb+') as f:
    f.write(response.content)

可以看到本目錄中保存的文件就是我們要提取的圖片:
在這裏插入圖片描述同樣地,音頻和視頻文件也可以用這樣的方法提取。

3. 添加headers
與urllib.request一樣,我們也可以通過headers參數來傳遞頭信息,下面以知乎的發現頁面爲例,如果不加請求頭:

import requests

response = requests.get('https://www.zhihu.com/explore')
print(response.text)

結果如下:

<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>openresty</center>
</body>
</html>

我們發現訪問被拒絕了,原因是如果我們不加請求頭,目標服務器識別出我們的請求並非是由瀏覽器發出來的,於是拒絕我們的訪問,我們可以在請求頭的User-Agent字段中僞造請求源,令請求源爲Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36,表示該請求是由Chrome瀏覽器發出來的,這樣就成功實現了僞裝,我們將上例代碼改成以下所示:

import requests

headers = {
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36'
}
response = requests.get('https://www.zhihu.com/explore', headers=headers)
print(response.text)

運行結果爲:
在這裏插入圖片描述
成功訪問了頁面。

2. POST請求

瞭解了GET請求的用法,POST請求的方法也同樣簡單:

import requests

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

結果如下:

  "args": {},
  "data": "",
  "files": {},
  "form": {
    "age": "22",
    "name": "germey"
  },
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Content-Length": "18",
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.23.0",
    "X-Amzn-Trace-Id": "Root=1-5eccd5c6-b1b0d97280f0059458476556"
  },
  "json": null,
  "origin": "171.107.139.104",
  "url": "http://httpbin.org/post"
}

3. 響應

在上面的實例中,我們通過text和content屬性獲得了響應的內容,此外還有很多屬性和方法可以獲取其他信息,比如狀態碼、響應頭、Cookie等,如下:

import  requests

response = requests.get('https://www.baidu.com')
print(type(response.status_code), response.status_code)
print(type(response.headers), response.headers)
print(type(response.cookies), response.cookies)
print(type(response.url), response.url)
print(type(response.history), response.history)

運行結果如下:在這裏插入圖片描述這裏分別打印出status_code屬性得到狀態碼,輸出headers屬性得到響應頭,輸出cookies屬性得到Cookies,輸出url屬性得到URL,輸出history屬性得到請求歷史。

高級用法

1. 文件上傳

假如有些網站需要上傳文件,我們也可以用requests模塊實現,如下:

import requests

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

結果如下:

{
  "args": {},
  "data": "",
  "files": {
    "file": "data:application/octet-stream;base64,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"
  },
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Content-Length": "5134",
    "Content-Type": "multipart/form-data; boundary=cb3879890fe3ecc2242d77aed4456739",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.23.0",
    "X-Amzn-Trace-Id": "Root=1-5eccd9cb-fd61d63c5b7393a0a4820390"
  },
  "json": null,
  "origin": "171.107.139.104",
  "url": "http://httpbin.org/post"
}

前一節中我們保存了一個CSDN圖標文件,這次用它來模擬文件上傳的過程,從運行結果可以看出,我們提交的文件被放在了files字段內,並且文件被加密成了base64格式。

2. Cookies

前面我們使用urllib處理過Cookies,寫法非常複雜,而在requests中,獲取和設置Cookie一步即可完成:

import requests

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

運行結果如下:

<RequestsCookieJar[<Cookie BDORZ=27315 for .baidu.com/>]>
BDORZ=27315

我們首先登陸百度取得cookies,可以發現它是RequestsCookieJar類型,然後用items()方法遍歷出每個Cookie的名稱和值,實現Cookies的遍歷和解析。我們也可以用Cookies來維持登陸狀態,以知乎爲例。
首先,登陸知乎,將Headers中的Cookie複製下來,如圖所示:在這裏插入圖片描述將Cookie複製下來,添加到Headers裏面,再發送請求:

import requests

headers = {
    'Cookie':'_zap=3f3a8847-850e-43e0-be78-b4be0bfa6995; d_c0="AIDX3Ryz2RCPTmMuf_Mm8rKi-lXSeAtT9EU=|1582267483"; _ga=GA1.2.903862747.1583308568; _xsrf=gJaEH2r1y8UDTP1Ej3IozSme9zAcufUL; tst=r; capsion_ticket="2|1:0|10:1588241682|14:capsion_ticket|44:YTY0NmRlOGM2NGE0NDY4OWJhNjRkNDI3ZDM2MjUyZjc=|2845e561cc3deefa38a0f3af569a97c251a4295347df5a19499c63cd06fc96c1"; r_cap_id="MjljZWU0MDJiZWQ4NDEyN2I1YWU2YWY0MzQyMGVmZTk=|1588241690|9a83e301b5a66e0c3a88b97148b2ae53b2f17438"; cap_id="ODEwZWI3NGM0ZDFjNGM2Yjg1MzhmY2YzN2Y5MzJiNDU=|1588241690|abd8b0789de34c3c9deaaff5a955957633d3f9f1"; l_cap_id="NDhlODVkZGI4MGJiNDMzZGJmMjk0NTcwOTczMmVhNmU=|1588241690|31dedb916b6140599e8cd7efc4c69fde323c7f4b"; z_c0=Mi4xbElYOUR3QUFBQUFBZ05mZEhMUFpFQmNBQUFCaEFsVk5KUE9YWHdDOEt2cFJDUW9qMlFnclZMLWNhRUdzX0YwNE5B|1588241700|b205b28d7e4b0a1bf4e8b554ab73574164eb0c73; q_c1=67dc75e659a445e3aab6b904ca4772ed|1588242255000|1588242255000; __utmv=51854390.110--|2=registration_date=20190531=1^3=entry_date=20190531=1; _gid=GA1.2.28121021.1590480973; __utmc=51854390; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1589720541,1589788910,1590480972,1590484318; BAIDU_SSP_lcr=https://www.baidu.com/link?url=C8qsxEG_x3OMJtP83xu1k1mrHxJPpf20TPUUFxPi7BS&wd=&eqid=ea3bb79e00024eb9000000065eccdd58; SESSIONID=ErO66ceM7PuCJd223PseKNutezkIlS8HiDTqimrnydQ; JOID=Vl8TA0i1_WTj2O72K7GZPsICyaY4844t1umOkmCFrhCmkY3HGNMnrbnc7PEuNDz0unQt3Q6KyGjuLwaRnKm_58E=; osd=V10VB0K0_2Ln0u_0LbWTP8AEzaw58Ygp3OiMlGSPrxKglYfGGtUjp7je6vUkNT7yvn4s3wiOwmnsKQKbnau548s=; __utma=51854390.903862747.1583308568.1590480996.1590484903.3; __utmb=51854390.0.10.1590484903; __utmz=51854390.1590484903.3.3.utmcsr=zhihu.com|utmccn=(referral)|utmcmd=referral|utmcct=/people/jude-78-40; _gat_gtag_UA_149949619_1=1; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1590485091; KLBRSID=0a401b23e8a71b70de2f4b37f5b4e379|1590485093|1590480970',
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36'
}
response = requests.get('https://www.zhihu.com/people/jude-78-40', headers=headers)
print(response.text)

我們發現運行結果中包含了登陸後的結果:在這裏插入圖片描述這說明登陸成功。

3. 會話維持

在requests中,如果直接用get()或post()等方法可以做到模擬網頁的請求,但實際上這相當於不同的會話,也就是說相當於你用兩個瀏覽器打開了不同的頁面,如果你利用post()方法登陸了某個網站,然後再進入個人頁面,企圖用get()方法獲得個人信息,這樣顯然是不能成功獲得個人信息的,因爲這是不同的會話,解決這個問題就是要維持同一個會話,我們可以在每次請求時設置同一個Cookie,但是顯然這個過程非常繁瑣,在requests模塊中,提供了一個Session對象來幫我們解決這個問題。httpbin這個網站中,我們可以設置一個Cookie,名稱是name,內容爲germey,接着再請求當前網址獲得Cookie,代碼如下:

import requests

requests.get('http://httpbin.org/cookies/set/number/germer')
response = requests.get('http://httpbin.org/cookies')
print(response.text)

運行結果如下:

{
  "cookies": {}
}

說明我們並沒有獲得Cookie,再用Session試試看:

import requests

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

運行結果如下:

{
  "cookies": {
    "number": "germer"
  }
}

成功獲得了Cookie。說明Session可以維持會話,通常用於模擬登陸後的下一步操作。

4. SSL證書驗證

requests提供了證書驗證的功能,當發送HTTP請求的時候,它會檢查SSL證書,如果訪問頁面的SSL證書過期或無效,就會出現一個證書問題的頁面:在這裏插入圖片描述在requests中我們可以使用verify參數來控制是否檢查此證書,如果不加verify的話,默認是True,會自動驗證。例如:

import requests

re = requests.get('https://www.xxxx.cn', verify=False)
print(re.text)

我們也可以指定一個本地證書用作客戶端證書,這可以是單個文件,也可以是一個包含兩個文件路徑的元組:

import requests

re = requests.get('https://www.xxxx.cn', cert=('/path/server.crt', '/path/key'))
print(re.text)

5. 代理設置

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

import requests

proxy = {
        'http': '120.25.253.234:812',
        'https':'163.125.222.244:8123'
    }
re = requests.get('http://httpbin.org/get', proxies=proxy)
print(re.text)

其中代理服務器地址可以換成有效的地址

6. 超時設置

在本機網絡狀態不好或者服務器網絡響應太慢或無法響應時,我們可能會等待特別久的時間才能收到響應,甚至最後接收不到響應,爲了防止服務器不能及時響應,應該設置一個超時時間,即超過了這個時間還沒有接收到響應,那就報錯。者需要用到timeout參數,實例如下:

import requests

r = requests.get('https://www.baidu.com', timeout= 0.1)
print(r.status_code)

如果0.1秒內沒有響應,則拋出異常
實際上,請求分爲兩個階段,即連接和讀取,上面設置的timeout將作用於兩個階段,如需分別指定,可以傳入一個元組:

r = requests.get('https://www.baidu.com', timeout = (0.1, 0.5))

如果想永久等待,可以將timeout設爲None,或者不指定timeout參數,因爲其默認值就是None。

7. 身份驗證

在訪問網站時,我們可能會遇到這樣的驗證頁面:在這裏插入圖片描述此時可以使用requests自帶的身份驗證功能:

import requests

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

如果用戶名密碼正確,驗證成功,就會返回200狀態碼

8. Prepared Request

前面我們介紹urllib時,我們可以將請求表示爲一個數據結構,其中各個參數都可以通過一個Request對象來表示,這在requests裏同樣可以做到:

from requests import Request, Session

url = 'http://httpbin.org/post'
data = {
    'name': 'germey'
}
headers = {
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36'
}
s = Session()
req = Request('POST', url, headers, data=data)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)

運行結果如下:

{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "name": "germey"
  },
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Content-Length": "11",
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "httpbin.org",
    "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36",
    "X-Amzn-Trace-Id": "Root=1-5ecd0951-17a8dc447274d384cb1cd7e0"
  },
  "json": null,
  "origin": "171.107.139.104",
  "url": "http://httpbin.org/post"
}

可以看到,我們達到了同樣的POST請求效果,有了Request這個對象,就可以將請求當中獨立的對象來看待,這樣在進行隊列調度時會非常方便。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章