人生苦短,我用 Python
前文傳送門:
小白學 Python 爬蟲(2):前置准備(一)基本類庫的安裝
小白學 Python 爬蟲(3):前置准備(二)Linux基礎入門
小白學 Python 爬蟲(4):前置准備(三)Docker基礎入門
小白學 Python 爬蟲(6):前置准備(五)爬蟲框架的安裝
小白學 Python 爬蟲(10):Session 和 Cookies
小白學 Python 爬蟲(11):urllib 基礎使用(一)
小白學 Python 爬蟲(12):urllib 基礎使用(二)
小白學 Python 爬蟲(13):urllib 基礎使用(三)
小白學 Python 爬蟲(14):urllib 基礎使用(四)
小白學 Python 爬蟲(15):urllib 基礎使用(五)
小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖
小白學 Python 爬蟲(17):Requests 基礎使用
超時設置
前面我們在介紹 urllib 的時候也介紹過超時,我們現在來看下在 Requests 中的超時應該怎么寫。
import requests
r = requests.get("https://www.geekdigging.com/", timeout = 1)
print(r.status_code)
具體的執行結果小編就不貼了。
注意
timeout 僅對連接過程有效,與響應體的下載無關。 timeout 並不是整個下載響應的時間限制,而是如果服務器在 timeout 秒內沒有應答,將會引發一個異常(更精確地說,是在 timeout 秒內沒有從基礎套接字上接收到任何字節的數據時)If no timeout is specified explicitly, requests do not time out.
代理設置
和 urllib 一樣,多的介紹就不說了,直接上代碼:
import requests
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
requests.get("https://www.geekdigging.com/", proxies=proxies)
當然,直接運行這個示例可能不行,因為這個代理可能是無效的,可以自己找一些免費的代理進行測試。
而 Requests 除了支持 HTTP 代理,還支持 Socket 代理,因為這是一個可選的功能,在 Requests 的標准庫中並未包含,所以在使用前需要先安裝。
pip install requests[socks]
安裝好依賴以后,使用 SOCKS 代理和使用 HTTP 代理一樣簡單:
import requests
proxies_socket = {
'http': 'socks5://user:pass@host:port',
'https': 'socks5://user:pass@host:port'
}
requests.get("https://www.geekdigging.com/", proxies = proxies_socket)
Cookies
前面我們使用 urllib 處理 Cookies 的時候,寫法比較復雜,而使用 Requests 會使證件事情變得非常簡單,獲取和設置 Cookies 只需一步就能完成。先看一個簡單的示例:
import requests
r = requests.get("https://www.csdn.net")
print(type(r.cookies), r.cookies)
for key, value in r.cookies.items():
print(key + '=' + value)
結果如下:
<class 'requests.cookies.RequestsCookieJar'> <RequestsCookieJar[<Cookie dc_session_id=10_1575798031732.659641 for .csdn.net/>, <Cookie uuid_tt_dd=10_19615575150-1575798031732-646184 for .csdn.net/>, <Cookie acw_tc=2760827715757980317314369e26895215355a996a74e112d9936f512dacd1 for www.csdn.net/>]>
dc_session_id=10_1575798031732.659641
uuid_tt_dd=10_19615575150-1575798031732-646184
acw_tc=2760827715757980317314369e26895215355a996a74e112d9936f512dacd1
在 Requests 中我們使用 cookies
屬性就可以直接得到 Cookies 。通過打印我們可以發現它的類型是 requests.cookies.RequestsCookieJar
,然后用 items()
方法將其轉化為元組組成的列表,遍歷輸出每一個 Cookie 的名稱和值,實現 Cookie 的遍歷解析。
通過 Cookies 維持會話狀態
因為知乎是需要登錄才能訪問的,我們選址知乎作為測試的站點,首先直接訪問知乎,看下返回的狀態碼。
import requests
r = requests.get('https://www.zhihu.com')
print(r.status_code)
結果如下:
400
狀態碼 400 的含義是請求無效(Bad request)。
我們打開瀏覽器,登錄知乎,打開 F12 開發者模式,看下我們登錄后的 Cookies 是什么。
我們將這段內容 copy 下來,加到訪問頭中:
import requests
headers = {
'cookie': '_zap=7c875737-af7a-4d55-b265-4e3726f8bd30; _xsrf=MU9NN2kHxdMZBVlENJkgnAarY6lFlPmu; d_c0="ALCiqBcc8Q-PTryJU9ro0XH9RqT4NIEHsMU=|1566658638"; UM_distinctid=16d16b54075bed-05edc85e15710b-5373e62-1fa400-16d16b54076e3d; tst=r; q_c1=1a9d0d0f293f4880806c995d7453718f|1573961075000|1566816770000; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1574492254,1574954599,1575721552,1575721901; tgw_l7_route=f2979fdd289e2265b2f12e4f4a478330; CNZZDATA1272960301=1829573289-1568039631-%7C1575793922; capsion_ticket="2|1:0|10:1575798464|14:capsion_ticket|44:M2FlYTAzMDdkYjIzNDQzZWJhMDcyZGQyZTZiYzA1NmU=|46043c1e4e6d9c381eb18f5dd8e5ca0ddbf6da90cddf10a6845d5d8c589e7754"; z_c0="2|1:0|10:1575798467|4:z_c0|92:Mi4xLXNyV0FnQUFBQUFBc0tLb0Z4enhEeVlBQUFCZ0FsVk53eFRhWGdBSlc3WFo1Vk5RUThBMHMtanZIQ2tYcGFXV2pn|02268679f394bd32662a43630236c2fd97e439151b0132995db7322736857ab6"; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1575798469',
'host': 'www.zhihu.com',
'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('https://www.zhihu.com', headers = headers)
print(r.text)
執行結果如下:
結果太長了,小編就直接截個圖。
有一點需要注意的是,這里的請求頭增加了 UA 和 host ,不然也是無法訪問的。
當然除了直接貼這么一串字符串,也是可以通過構造 cookies 的參數來設置 cookies ,這樣需要構建一個 RequestsCookieJar 對象,步驟相對會復雜一點,結果是一樣的。
# 構建 RequestsCookieJar 對象
cookies = '_zap=7c875737-af7a-4d55-b265-4e3726f8bd30; _xsrf=MU9NN2kHxdMZBVlENJkgnAarY6lFlPmu; d_c0="ALCiqBcc8Q-PTryJU9ro0XH9RqT4NIEHsMU=|1566658638"; UM_distinctid=16d16b54075bed-05edc85e15710b-5373e62-1fa400-16d16b54076e3d; tst=r; q_c1=1a9d0d0f293f4880806c995d7453718f|1573961075000|1566816770000; Hm_lvt_98beee57fd2ef70ccdd5ca52b9740c49=1574492254,1574954599,1575721552,1575721901; tgw_l7_route=f2979fdd289e2265b2f12e4f4a478330; CNZZDATA1272960301=1829573289-1568039631-%7C1575793922; capsion_ticket="2|1:0|10:1575798464|14:capsion_ticket|44:M2FlYTAzMDdkYjIzNDQzZWJhMDcyZGQyZTZiYzA1NmU=|46043c1e4e6d9c381eb18f5dd8e5ca0ddbf6da90cddf10a6845d5d8c589e7754"; z_c0="2|1:0|10:1575798467|4:z_c0|92:Mi4xLXNyV0FnQUFBQUFBc0tLb0Z4enhEeVlBQUFCZ0FsVk53eFRhWGdBSlc3WFo1Vk5RUThBMHMtanZIQ2tYcGFXV2pn|02268679f394bd32662a43630236c2fd97e439151b0132995db7322736857ab6"; Hm_lpvt_98beee57fd2ef70ccdd5ca52b9740c49=1575798469'
jar = requests.cookies.RequestsCookieJar()
for cookie in cookies.split(';'):
key, value = cookie.split('=', 1)
jar.set(key, value)
headers_request = {
'host': 'www.zhihu.com',
'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('https://www.zhihu.com', cookies = jar, headers = headers)
print(r.text)
結果是可以訪問成功的,小編這里就不貼了。
簡單講一下實現思路,將上面復制下來的 cookies 使用 split() 進行切割,然后使用 set() 方法將 key 和 value 賦值到 RequestsCookieJar 這個對象中,然后在訪問知乎的時候將 RequestsCookieJar 賦值給 cookies 參數即可。需要注意的是這里的 header 參數不能少,只是原來 header 里面的 cookies 無需再設置了。
會話維持
接下來這一個是大招,這個功能在 urllib 中是沒有的。
先想像一個場景,我們在爬取一個網站的數據,其中有一部分需要使用 GET 請求,有一部分需要使用 POST 請求。但是我們在程序中寫一個 get() 再寫一個 post() ,實際上是兩個不同的會話。
可能有的同學要說了,老師,我們前面講的會話維持是通過 Cookies 來做的,可以在每次請求的時候添加上 Cookies 。
沒問題,這樣確實是可以的,但是這么干有些麻煩。 Requests 為我們提供了更加簡潔高效的方法—— Session 。
我們還是通過前面介紹過的 https://httpbin.org/ 來進行演示,我們可以通過訪問鏈接:https://httpbin.org/cookies/set/number/123456789 來設置一個 Cookies ,名稱叫做 number ,內容是 123456789 。
首先看直接使用 Requests 的示例:
import requests
requests.get('https://httpbin.org/cookies/set/number/123456789')
r = requests.get('https://httpbin.org/cookies')
print(r.text)
結果如下:
{
"cookies": {}
}
我們直接調用兩次 get() 方法,並沒有在第二次調用的時候獲得 Cookies 。接下來我們換 Session 再看一下:
import requests
s = requests.Session()
s.get('https://httpbin.org/cookies/set/number/123456789')
r = s.get('https://httpbin.org/cookies')
print(r.text)
結果如下:
{
"cookies": {
"number": "123456789"
}
}
顯而易見,我們成功獲取到了之前設置的 Cookies 。
所以,利用 Session 可以做到模擬同一個會話而不用手動再去設置 Cookies,它在我們平時的使用中使用的極其廣泛,因為它可以模擬在同一個瀏覽器中訪問同一個站點的不同的頁面,這在我們爬取很多需要登錄的網頁時,極大的方便了我們代碼的書寫。
示例代碼
本系列的所有代碼小編都會放在代碼管理倉庫 Github 和 Gitee 上,方便大家取用。