文章目錄
- 一、requests簡介及安裝
-
- 1. 簡介
- 2. 安裝
- 二、requests使用方法介紹
-
- 1. 請求方式
- 2. 基本用法
-
- 2.1 GET請求
- 2.2 POST請求
- 3. 進階用法
-
- 3.1 添加請求頭
- 3.2 會話維持
- 3.3 代理設定
- 3.4 逾時設定
- 3.5 身份認證
- 4. 響應
-
- 4.1 響應的組成
-
- 4.1.1 響應狀态碼
- 4.1.2 響應頭
- 4.1.3 響應體
- 4.2 響應的擷取
一、requests簡介及安裝
1. 簡介
Requests庫是由python語言基于urllib編寫的,采用的是Apache2 Licensed開源協定的HTTP庫,它在做網絡請求上會比urllib使用更加友善。
2. 安裝
直接使用pip安裝即可
pip install requests
二、requests使用方法介紹
1. 請求方式
requests
包含多種請求方式:
- GET- 請求頁面,并傳回頁面内容
- POST- 大多用于送出表單或上傳檔案,資料包含在請求體中
- HEAD- 類似于GET請求,隻不過傳回的響應中沒有具體的内容,用于擷取報頭
- PUT- 從用戶端向伺服器傳送的資料取代指定文檔中的内容
- DELETE- 請求伺服器删除指定的頁面
- CONNECT- 把伺服器當作跳闆,讓伺服器代替用戶端通路其他網頁
- OPTIONS- 允許用戶端檢視伺服器的性能
- TRACE- 回顯伺服器收到的請求,主要用于測試或診斷
2. 基本用法
這裡隻介紹常用的GET請求和POST請求
2.1 GET請求
GET請求中的參數包含在URL裡面,并且資料是明文的,可以在URL中看到。
GET請求送出的資料最多隻有1024位元組。
以實驗網址為例(
http://httpbin.org/get
)
基本請求:
import requests
__author__ = 'Evan'
r = requests.get(url='http://httpbin.org/get') # 使用GET請求通路
print(r.text) # 列印網頁的HTML文本
列印結果:
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"origin": "12.192.229.251, 12.192.229.251",
"url": "https://httpbin.org/get"
}
可以發現,我們成功的發起了GET請求,傳回結果中包含
請求頭
、
URL
、
IP
等資訊。
那麼,對于GET請求,如果要附加額外的資訊,要怎麼添加呢?
使用params參數構造帶請求參數的GET請求:
import requests
__author__ = 'Evan'
# 請求參數
params = {
'name': 'Evan',
'age': '24'
}
r = requests.get(url='http://httpbin.org/get', params=params) # 帶請求參數的GET請求
print(r.text)
列印結果:
{
"args": {
"age": "24",
"name": "Evan"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"origin": "12.192.229.251, 12.192.229.251",
"url": "https://httpbin.org/get?name=Evan&age=24"
}
可以看到設定的
params
參數已經起作用了,不過還有一種方法也可以提供請求參數,就是建構完整的URL,因為GET請求的參數會包含在URL裡面。
使用 urlencode子產品 将字典序列化為GET請求參數:
import requests
from urllib.parse import urlencode
__author__ = 'Evan'
# 請求參數
params = {
'name': 'Evan',
'age': '24'
}
r = requests.get(url='http://httpbin.org/get?' + urlencode(params))
print(r.text)
列印結果:
{
"args": {
"age": "24",
"name": "Evan"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"origin": "12.192.229.251, 12.192.229.251",
"url": "https://httpbin.org/get?name=Evan&age=24"
}
可以看到結果和使用
params
參數的GET請求是一樣的。
2.2 POST請求
POST請求大多在表單送出時發起。比如一個登陸表單,輸入使用者名和密碼後,點選“登陸”按鈕,這通常會發起一個POST請求,其資料通常以表單的形式傳輸,表單資料會放在請求體中,而不會展現在URL中,是以送出的資料是保密的,不會洩露敏感資訊,并且 POST請求送出的資料大小沒有限制。
以實驗網址為例(
http://httpbin.org/post
)
基本請求:
import requests
__author__ = 'Evan'
# 請求參數
data = {
'name': 'Evan',
'age': '24'
}
r = requests.post(url='http://httpbin.org/post', data=data) # 使用POST請求通路
print(r.text)
列印結果:
{
"args": {},
"data": "",
"files": {},
"form": {
"age": "24",
"name": "Evan"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "16",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"origin": "12.192.229.251, 12.192.229.251",
"url": "https://httpbin.org/post"
}
可以發現,其中
form
部分就是我們送出的資料,這就證明POST請求成功發送了。
requests還可以模拟送出一些資料,比如上傳檔案,要怎麼添加呢?
使用files參數構造帶上傳檔案的POST請求:
import requests
__author__ = 'Evan'
files = {'file': open('haimianbaobao.ico', 'rb')} # 檔案路徑
r = requests.post(url='http://httpbin.org/post', files=files) # 帶上傳檔案的POST請求
print(r.text)
列印結果:
{
"args": {},
"data": "",
"files": {
"file": "data:application/octet-stream;base64,R0lGODlhkQCCAHAAACH5BABBAAAALAAAAA...="
},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "8732",
"Content-Type": "multipart/form-data; boundary=c15f3180298f305a48359831993ed6b8",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.22.0"
},
"json": null,
"origin": "12.192.229.251, 12.192.229.251",
"url": "https://httpbin.org/post"
}
以上省略部分内容,可以發現,裡面包含
files
這個字段,而
form
字段是空的,這證明檔案上傳部分會單獨有一個
files
字段來辨別。
3. 進階用法
現在大部分網站都有反爬機制,是以在請求網頁的時候一般都要添加請求頭才可以得到響應,某些網站限制登陸時還要設定cookies等,下面介紹一些常用的進階用法。(
POST請求和GET請求同理,這裡以GET請求為例
)
3.1 添加請求頭
請求頭,用來說明伺服器要使用的附加資訊,比較重要的資訊有Cookie、Referer、User-Agent等
下面簡要說明一些常用的請求頭資訊:
- Accept- 請求報頭域,用于指定用戶端可接受哪些類型的資訊。
- Accept-Language- 指定用戶端可接受的語言類型
- Accept-Encoding- 指定用戶端可接受的内容編碼
- Host- 用于指定請求資源的主機IP和端口号,其内容為請求URL的原始伺服器或網關的位置
- Cookie- 也常用複數形式Cookies,它的主要功能是維持目前通路會話,伺服器會用會話儲存登陸狀态資訊
- Referer- 此内容用來辨別這個請求是從哪個頁面發過來的,伺服器可以拿這一資訊做相應的處理,如做來源統計,放盜鍊處理等
- User-Agent- 簡稱UA,它是一個特殊的字元串頭,可以使伺服器識别客戶使用的作業系統及版本、浏覽器及版本等資訊。在做爬蟲時加上此資訊,可以僞裝為浏覽器,如果不加,很可能會被識别出為爬蟲
- Content-Type- 也叫網際網路媒體類型(Internet Media Type)或者MIME類型,它用來表示具體請求中的媒體類型資訊。例如,text/html代表HTML格式,image/gif代表GIF圖檔,application/json代表JSON類型等
看到這相信你已經了解請求頭中大部分參數的含義了,現在開始用程式實作這些功能
使用headers參數添加”User-Agent“:
import requests
__author__ = 'Evan'
# 請求頭參數
headers = {
"User-Agent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/78.0.3904.108 Safari/537.36'
}
r = requests.get(url='http://httpbin.org/get', headers=headers) # 帶請求頭的GET請求
print(r.text)
列印結果:
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"
},
"origin": "12.192.229.251, 12.192.229.251",
"url": "https://httpbin.org/get"
}
可以看到,
“User-Agent”
已經被添加上去了,是以添加請求頭很簡單,隻要添加
headers
參數即可,
headers
是一個字典類型,根據需求填入相應的請求頭資訊就可以輕松的送出各種請求方式了。
3.2 會話維持
說到會話維持,第一想到的就是使用cookies,網頁為什麼能保持會話,在登陸後不用重新登陸,就是因為cookies保持會話了,是以我們想要會話維持就要在請求頭中添加對應的cookies,但是問題來了,如果每次在請求的時候都去添加cookies,這未免也太麻煩了吧,是以requests有一個新的利器-
Session對象
,利用它,我們可以友善地維護一個會話,而且不用擔心cookies的問題,它會幫我們自動處理好。
示例如下:
沒有使用Session之前:
import requests
__author__ = 'Evan'
# 第一次通路,并設定cookies
r1 = requests.get(url='http://httpbin.org/cookies/set/number/123456789')
print('r1: {}'.format(r1.text))
# 第二次通路
r2 = requests.get(url='http://httpbin.org/cookies')
print('r2: {}'.format(r2.text))
列印結果:
r1: {
"cookies": {
"number": "123456789"
}
}
r2: {
"cookies": {}
}
這裡我們請求了一個測試網址(
http://httpbin.org/cookies/set/number/123456789
)
請求這個網址時,可以設定一個cookie,名稱叫做number,内容是123456789,
随後又請求了(
http://httpbin.org/cookies
),此網址可以擷取目前的Cookies,但是看列印結果cookies為空,是以使用2次requests是相當于打開兩個浏覽器,這兩次requests的内容是不共享的。
接下來看使用Session的例子:
import requests
__author__ = 'Evan'
# 執行個體化Session對象
s = requests.Session()
# 第一次通路,并設定cookies
r1 = s.get(url='http://httpbin.org/cookies/set/number/123456789')
print('r1: {}'.format(r1.text))
# 第二次通路
r2 = s.get(url='http://httpbin.org/cookies')
print('r2: {}'.format(r2.text))
列印結果:
r1: {
"cookies": {
"number": "123456789"
}
}
r2: {
"cookies": {
"number": "123456789"
}
}
成功擷取!是以需要登陸某些網站傳遞登陸資訊時就使用
Session
對象來保持同一個會話,這樣就免去了每次要設定cookies的煩瑣了。
3.3 代理設定
對于某些網站,在測試的時候請求幾次能正常擷取内容,但是一旦開始大規模爬取,網站可能會彈出驗證碼,或者跳轉到登陸認證頁面,更甚至可能會直接封禁用戶端的IP,導緻一定時間段内無法通路,那麼,為了防止這種情況發生,我們需要設定代理來解決這個問題。
使用proxies參數設定代理:
import requests
__author__ = 'Evan'
# 使用普通格式
proxies = {"http": "http://10.10.1.10:3128", "https": "http://10.10.1.10:1080"}
# 使用HTTP Basic Auth格式
proxies = {"http": "http://user:[email protected]:3128"}
# 使用SOCKS協定(需要安裝 'requests[socks]' 子產品)
proxies = {"http": "socks5://user:[email protected]:port", "https": "socks5://user:[email protected]:port"}
requests.get('http://httpbin.org/get', proxies=proxies) # 使用代理的GET請求
當然,直接運作這個執行個體可能不行,因為這些代理IP可能是無效的,這裡隻講解
proxies
的使用格式和方法,具體大家可以去代理IP網站下載下傳免費的代理或者付費的代理試驗。
3.4 逾時設定
在本機網絡狀況不好或者伺服器網絡響應太慢時,我們可能會等待很久的時間才能收到響應,這個時候就可以使用
timeout
參數,這個時間的計算是從送出請求到伺服器響應的時間。
示例如下:
import requests
__author__ = 'Evan'
r = requests.get(url='http://httpbin.org/get', timeout=1)
print(r.text)
列印結果:
Traceback (most recent call last):
File "C:/Evan/my_program/shining_star/trunk/unit_testing/test1.py", line 20, in <module>
r = requests.get(url='http://httpbin.org/get', timeout=1)
File "C:\pycharm_user\venv\lib\site-packages\requests\api.py", line 75, in get
return request('get', url, params=params, **kwargs)
File "C:\pycharm_user\venv\lib\site-packages\requests\api.py", line 60, in request
return session.request(method=method, url=url, **kwargs)
File "C:\pycharm_user\venv\lib\site-packages\requests\sessions.py", line 533, in request
resp = self.send(prep, **send_kwargs)
File "C:\pycharm_user\venv\lib\site-packages\requests\sessions.py", line 646, in send
r = adapter.send(request, **kwargs)
File "C:\pycharm_user\venv\lib\site-packages\requests\adapters.py", line 529, in send
raise ReadTimeout(e, request=request)
requests.exceptions.ReadTimeout: HTTPConnectionPool(host='httpbin.org', port=80): Read timed out. (read timeout=1)
通過這樣的方式,我們可以将逾時時間設定為1秒,如果在1秒内沒有收到響應,那就抛出異常,還可以加上
try-except
進行異常處理,防止等待過長而浪費時間,我們還可以直接設定為
None
,或者不設定直接留白,因為預設也是
None
,這樣的話表示永久等待下去,直到收到伺服器響應結果。
3.5 身份認證
在通路某些網站時,我們可能會遇到如下圖所示,彈出一個輸入框提示身份驗證,此時可以使用
auth
參數添加使用者名和密碼進行認證。
示例如下:
import requests
__author__ = 'Evan'
r = requests.get('http://localhost:5000', auth=('username', 'password'))
print(r.text)
auth
參數是一個元組,該元組第一個參數為使用者名,第二個參數為密碼,提供這個參數後requests會預設使用
HTTPBasicAuth
這個類來認證,這樣就可以解除認證,繼續通路後續頁面了。
4. 響應
當我們使用requests請求網頁時,會傳回一個response,我們就是要解析這個response,才能拿到我們想要的資訊,是以接下來先介紹響應是由哪些資訊組成的,然後再介紹怎麼用requests擷取這些資訊。
4.1 響應的組成
響應是指伺服器傳回用戶端的結果,可以分為三個部分:(響應狀态碼、響應頭、響應體)
4.1.1 響應狀态碼
響應狀态碼表示伺服器的響應狀态,如
200
代表伺服器正常響應,
404
代表頁面未找到,
500
代表伺服器内部發生錯誤。在爬蟲中,我們可以根據狀态碼來判斷伺服器的響應狀态然後再進行下一步的處理。
下面列出一些常見的狀态碼供參考:
- 200- 【
】伺服器已經成功處理了請求成功
- 301- 【
】請求的網頁已永久移動到新位置,即永久重定向永久移動
- 302- 【
】請求的網頁暫時跳轉到其他頁面,即暫時重定向臨時移動
- 400- 【
】伺服器無法解析該請求錯誤請求
- 401- 【
】請求沒有進行身份驗證或驗證未通過未授權
- 403- 【
】伺服器拒絕此請求禁止通路
- 404- 【
】伺服器找不到請求的網頁未找到
- 408- 【
】伺服器請求逾時請求逾時
- 410- 【
】請求的資源已永久删除已删除
- 500- 【
】伺服器遇到錯誤,無法完成請求伺服器内部錯誤
- 502- 【
】伺服器作為網關或代理,從上遊伺服器收到無效響應錯誤網關
- 503- 【
】伺服器目前無法使用服務不可用
- 504- 【
】伺服器作為網關或代理,但是沒有及時從上遊伺服器收到請求網關逾時
- 505- 【
】伺服器不支援請求中所有的HTTP協定版本HTTP版本不支援
4.1.2 響應頭
響應頭包含了伺服器對請求的應答資訊,如
Content-Type
、
Server
、
Set-Cookie
等。
下面簡要說明一些常用的響應頭資訊:
- Date- 辨別響應産生的時間
- Last-Modified- 指定資源的最後修改時間
- Content-Encoding- 指定響應内容的編碼
- Server- 包含伺服器的資訊,比如名稱、版本号等
- Content-Type- 文檔類型,指定傳回的資料類型是什麼,如
代表傳回HTML文檔,text/html
則代表傳回JavaScript檔案,application/x-javascript
則代表傳回圖檔image/jpeg
- Set-Cookie- 設定Cookies,響應頭中的
告訴浏覽器需要将此内容放在Cookies中,下次請求攜帶Cookies請求Set-Cookie
- Expires- 指定響應的過期時間,可以使代理伺服器或浏覽器将加載的内容更新到緩存中,如果再次通路時,就可以直接從換從中加載,降低伺服器負載,縮短加載時間
4.1.3 響應體
響應體是最重要的内容,響應的正文資料都是在響應體中,比如請求網頁時,它的響應體就是網頁的HTML代碼,請求一張圖檔時,它的響應體就是圖檔的二進制資料,在做爬蟲時,我們主要通過響應體得到網頁的源代碼,JSON資料等,然後從中做相應内容的提取。
當然,在我們不使用爬蟲時也可以直接看到響應體(也就是網頁源代碼),是以在開始寫爬蟲前應先看一遍網頁源代碼,了解自己要抓取哪些資訊,這些資訊放在哪個位置等等。
下面介紹一些檢視網頁源代碼的方法:
- 打開浏覽器開發者工具(
),然後在浏覽器開發者工具中點選按F12
,就可以看到網頁的源代碼了,也就是響應體的内容,它是解析的目标Elements
- 在網頁上按
,然後點選滑鼠右鍵
,這個時候會彈出一個新的視窗,裡面的内容就是目前頁面的源代碼了檢視網頁源代碼
4.2 響應的擷取
在發送請求後,得到的自然就是響應了,上面我們已經介紹了響應是由哪些資訊組成的,現在介紹怎麼用requests去擷取這些資訊。
示例如下:
# -*- coding:utf-8 -*-
import requests
__author__ = 'Evan'
r = requests.get(url='http://httpbin.org/get') # 使用GET請求通路
# 擷取網頁資訊
print('請求的URL: {}'.format(r.url)) # 擷取目前URL,傳回一個字元串
print('響應狀态碼: {}'.format(r.status_code)) # 擷取響應狀态碼,傳回一個整形
print('響應頭部資訊: {}'.format(r.headers)) # 擷取響應頭部資訊,傳回一個字典
print('響應Cookies: {}'.format(r.cookies)) # 擷取響應Cookies,傳回一個字典
print('通路的曆史記錄: {}'.format(r.history)) # 擷取通路的曆史記錄,可以檢視是否重定向,傳回一個清單
print('網頁源代碼: {}'.format(r.text)) # 擷取網頁源代碼,傳回一個字元串
print('網頁二進制資料: {}'.format(r.content)) # 擷取網頁内容的二進制格式,傳回一個二進制資料
print('JSON資料: {}'.format(r.json)) # 如果響應資訊是JSON資料則調用此方法,傳回一個字典
列印結果:
請求的URL: http://httpbin.org/get
響應狀态碼: 200
響應頭部資訊: {'Access-Control-Allow-Credentials': 'true', 'Access-Control-Allow-Origin': '*', 'Content-Encoding': 'gzip', 'Content-Type': 'application/json', 'Date': 'Sat, 21 Dec 2019 13:50:15 GMT', 'Referrer-Policy': 'no-referrer-when-downgrade', 'Server': 'nginx', 'X-Content-Type-Options': 'nosniff', 'X-Frame-Options': 'DENY', 'X-XSS-Protection': '1; mode=block', 'Content-Length': '181', 'Connection': 'keep-alive'}
響應Cookies: <RequestsCookieJar[]>
通路的曆史記錄: []
網頁源代碼: {
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.21.0"
},
"origin": "119.123.1.99, 119.123.1.99",
"url": "https://httpbin.org/get"
}
網頁二進制資料: b'{\n "args": {}, \n "headers": {\n "Accept": "*/*", \n "Accept-Encoding": "gzip, deflate", \n "Host": "httpbin.org", \n "User-Agent": "python-requests/2.21.0"\n }, \n "origin": "119.123.1.99, 119.123.1.99", \n "url": "https://httpbin.org/get"\n}\n'
JSON資料: <bound method Response.json of <Response [200]>>
Over~